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 
174f85db7f7SDuncan P. N. Exon Smith Optional<FileEntryRef> 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 
181f85db7f7SDuncan P. N. Exon Smith   auto GetFile = [&](StringRef Filename) -> Optional<FileEntryRef> {
182f85db7f7SDuncan P. N. Exon Smith     auto File =
183f85db7f7SDuncan P. N. Exon Smith         expectedToOptional(SourceMgr.getFileManager().getFileRef(Filename));
184f85db7f7SDuncan P. N. Exon Smith     if (!File || (Header.Size && File->getSize() != *Header.Size) ||
185f85db7f7SDuncan P. N. Exon Smith         (Header.ModTime && File->getModificationTime() != *Header.ModTime))
186f85db7f7SDuncan P. N. Exon Smith       return None;
1878d323d15SHarlan Haskins     return *File;
188040e1266SRichard Smith   };
189040e1266SRichard Smith 
190f85db7f7SDuncan P. N. Exon Smith   auto GetFrameworkFile = [&]() -> Optional<FileEntryRef> {
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);
198f85db7f7SDuncan P. N. Exon 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);
230f85db7f7SDuncan P. N. Exon Smith   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     }
244f85db7f7SDuncan P. N. Exon Smith     return None;
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;
254f85db7f7SDuncan P. N. Exon Smith   if (Optional<FileEntryRef> File =
2559f6020bcSBruno Cardoso Lopes           findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
256040e1266SRichard Smith     if (Header.IsUmbrella) {
257f85db7f7SDuncan P. N. Exon Smith       const DirectoryEntry *UmbrellaDir = &File->getDir().getDirEntry();
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.
263d3676d4bSMichael Spencer         setUmbrellaHeader(Mod, *File, Header.FileName, RelativePathName.str());
264040e1266SRichard Smith     } else {
265d3676d4bSMichael Spencer       Module::Header H = {Header.FileName, std::string(RelativePathName.str()),
266d3676d4bSMichael Spencer                           *File};
267040e1266SRichard Smith       if (Header.Kind == Module::HK_Excluded)
268040e1266SRichard Smith         excludeHeader(Mod, H);
269040e1266SRichard Smith       else
270040e1266SRichard Smith         addHeader(Mod, H, headerKindToRole(Header.Kind));
271040e1266SRichard Smith     }
272040e1266SRichard Smith   } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
273040e1266SRichard Smith     // There's a builtin header but no corresponding on-disk header. Assume
274040e1266SRichard Smith     // this was supposed to modularize the builtin header alone.
275040e1266SRichard Smith   } else if (Header.Kind == Module::HK_Excluded) {
276040e1266SRichard Smith     // Ignore missing excluded header files. They're optional anyway.
277040e1266SRichard Smith   } else {
278040e1266SRichard Smith     // If we find a module that has a missing header, we mark this module as
279040e1266SRichard Smith     // unavailable and store the header directive for displaying diagnostics.
280040e1266SRichard Smith     Mod->MissingHeaders.push_back(Header);
281040e1266SRichard Smith     // A missing header with stat information doesn't make the module
282040e1266SRichard Smith     // unavailable; this keeps our behavior consistent as headers are lazily
283040e1266SRichard Smith     // resolved. (Such a module still can't be built though, except from
284040e1266SRichard Smith     // preprocessed source.)
285040e1266SRichard Smith     if (!Header.Size && !Header.ModTime)
286fc76b4adSRichard Smith       Mod->markUnavailable(/*Unimportable=*/false);
287040e1266SRichard Smith   }
288040e1266SRichard Smith }
289040e1266SRichard Smith 
290040e1266SRichard Smith bool ModuleMap::resolveAsBuiltinHeader(
291040e1266SRichard Smith     Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
292040e1266SRichard Smith   if (Header.Kind == Module::HK_Excluded ||
293040e1266SRichard Smith       llvm::sys::path::is_absolute(Header.FileName) ||
294040e1266SRichard Smith       Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
295040e1266SRichard Smith       !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
296040e1266SRichard Smith       !isBuiltinHeader(Header.FileName))
297040e1266SRichard Smith     return false;
2981d60987fSRichard Smith 
2991d60987fSRichard Smith   // This is a system module with a top-level header. This header
3001d60987fSRichard Smith   // may have a counterpart (or replacement) in the set of headers
3011d60987fSRichard Smith   // supplied by Clang. Find that builtin header.
302040e1266SRichard Smith   SmallString<128> Path;
303040e1266SRichard Smith   llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
30464d8c781SDuncan P. N. Exon Smith   auto File = SourceMgr.getFileManager().getFile(Path);
305040e1266SRichard Smith   if (!File)
306040e1266SRichard Smith     return false;
307040e1266SRichard Smith 
308040e1266SRichard Smith   auto Role = headerKindToRole(Header.Kind);
309d3676d4bSMichael Spencer   Module::Header H = {Header.FileName, std::string(Path.str()), *File};
310040e1266SRichard Smith   addHeader(Mod, H, Role);
311040e1266SRichard Smith   return true;
3121d60987fSRichard Smith }
3131d60987fSRichard Smith 
3140761a8a0SDaniel Jasper ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
315b146baabSArgyrios Kyrtzidis                      const LangOptions &LangOpts, const TargetInfo *Target,
316b146baabSArgyrios Kyrtzidis                      HeaderSearch &HeaderInfo)
3170761a8a0SDaniel Jasper     : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
318056bf77fSRichard Smith       HeaderInfo(HeaderInfo) {
3190414b857SRichard Smith   MMapLangOpts.LineComment = true;
3200414b857SRichard Smith }
321718292f2SDouglas Gregor 
322718292f2SDouglas Gregor ModuleMap::~ModuleMap() {
32321668754SDavide Italiano   for (auto &M : Modules)
32421668754SDavide Italiano     delete M.getValue();
3258587dfd9SBruno Cardoso Lopes   for (auto *M : ShadowModules)
3268587dfd9SBruno Cardoso Lopes     delete M;
327718292f2SDouglas Gregor }
328718292f2SDouglas Gregor 
32989929282SDouglas Gregor void ModuleMap::setTarget(const TargetInfo &Target) {
33089929282SDouglas Gregor   assert((!this->Target || this->Target == &Target) &&
33189929282SDouglas Gregor          "Improper target override");
33289929282SDouglas Gregor   this->Target = &Target;
33389929282SDouglas Gregor }
33489929282SDouglas Gregor 
3359fc8faf9SAdrian Prantl /// "Sanitize" a filename so that it can be used as an identifier.
336056396aeSDouglas Gregor static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
337056396aeSDouglas Gregor                                               SmallVectorImpl<char> &Buffer) {
338056396aeSDouglas Gregor   if (Name.empty())
339056396aeSDouglas Gregor     return Name;
340056396aeSDouglas Gregor 
341*601102d2SCorentin Jabot   if (!isValidAsciiIdentifier(Name)) {
342056396aeSDouglas Gregor     // If we don't already have something with the form of an identifier,
343056396aeSDouglas Gregor     // create a buffer with the sanitized name.
344056396aeSDouglas Gregor     Buffer.clear();
345a7d03840SJordan Rose     if (isDigit(Name[0]))
346056396aeSDouglas Gregor       Buffer.push_back('_');
347056396aeSDouglas Gregor     Buffer.reserve(Buffer.size() + Name.size());
348056396aeSDouglas Gregor     for (unsigned I = 0, N = Name.size(); I != N; ++I) {
349*601102d2SCorentin Jabot       if (isAsciiIdentifierContinue(Name[I]))
350056396aeSDouglas Gregor         Buffer.push_back(Name[I]);
351056396aeSDouglas Gregor       else
352056396aeSDouglas Gregor         Buffer.push_back('_');
353056396aeSDouglas Gregor     }
354056396aeSDouglas Gregor 
355056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
356056396aeSDouglas Gregor   }
357056396aeSDouglas Gregor 
358056396aeSDouglas Gregor   while (llvm::StringSwitch<bool>(Name)
359056396aeSDouglas Gregor #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
360056396aeSDouglas Gregor #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
361056396aeSDouglas Gregor #include "clang/Basic/TokenKinds.def"
362056396aeSDouglas Gregor            .Default(false)) {
363056396aeSDouglas Gregor     if (Name.data() != Buffer.data())
364056396aeSDouglas Gregor       Buffer.append(Name.begin(), Name.end());
365056396aeSDouglas Gregor     Buffer.push_back('_');
366056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
367056396aeSDouglas Gregor   }
368056396aeSDouglas Gregor 
369056396aeSDouglas Gregor   return Name;
370056396aeSDouglas Gregor }
371056396aeSDouglas Gregor 
3729fc8faf9SAdrian Prantl /// Determine whether the given file name is the name of a builtin
37334d52749SDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system
37434d52749SDouglas Gregor /// headers.
375ba1b5c98SBruno Cardoso Lopes bool ModuleMap::isBuiltinHeader(StringRef FileName) {
37634d52749SDouglas Gregor   return llvm::StringSwitch<bool>(FileName)
37734d52749SDouglas Gregor            .Case("float.h", true)
37834d52749SDouglas Gregor            .Case("iso646.h", true)
37934d52749SDouglas Gregor            .Case("limits.h", true)
38034d52749SDouglas Gregor            .Case("stdalign.h", true)
38134d52749SDouglas Gregor            .Case("stdarg.h", true)
3823c4b1290SBen Langmuir            .Case("stdatomic.h", true)
38334d52749SDouglas Gregor            .Case("stdbool.h", true)
38434d52749SDouglas Gregor            .Case("stddef.h", true)
38534d52749SDouglas Gregor            .Case("stdint.h", true)
38634d52749SDouglas Gregor            .Case("tgmath.h", true)
38734d52749SDouglas Gregor            .Case("unwind.h", true)
38834d52749SDouglas Gregor            .Default(false);
38934d52749SDouglas Gregor }
39034d52749SDouglas Gregor 
3918d74de9dSMartin Boehme bool ModuleMap::isBuiltinHeader(const FileEntry *File) {
3928d74de9dSMartin Boehme   return File->getDir() == BuiltinIncludeDir &&
3938d74de9dSMartin Boehme          ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()));
3948d74de9dSMartin Boehme }
3958d74de9dSMartin Boehme 
39692669ee4SDaniel Jasper ModuleMap::HeadersMap::iterator
39792669ee4SDaniel Jasper ModuleMap::findKnownHeader(const FileEntry *File) {
398040e1266SRichard Smith   resolveHeaderDirectives(File);
39959527666SDouglas Gregor   HeadersMap::iterator Known = Headers.find(File);
40047972afdSRichard Smith   if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
4018d74de9dSMartin Boehme       Known == Headers.end() && ModuleMap::isBuiltinHeader(File)) {
4024eaf0a6cSDaniel Jasper     HeaderInfo.loadTopLevelSystemModules();
40392669ee4SDaniel Jasper     return Headers.find(File);
4044eaf0a6cSDaniel Jasper   }
40592669ee4SDaniel Jasper   return Known;
40692669ee4SDaniel Jasper }
40792669ee4SDaniel Jasper 
4084469138eSBen Langmuir ModuleMap::KnownHeader
4094469138eSBen Langmuir ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
4104469138eSBen Langmuir                     SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
41147972afdSRichard Smith   if (UmbrellaDirs.empty())
412afd1b1c9SEugene Zelenko     return {};
41347972afdSRichard Smith 
4144469138eSBen Langmuir   const DirectoryEntry *Dir = File->getDir();
4154469138eSBen Langmuir   assert(Dir && "file in no directory");
4164469138eSBen Langmuir 
4174469138eSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
4184469138eSBen Langmuir   // frameworks moving from top-level frameworks to embedded frameworks tend
4194469138eSBen Langmuir   // to be symlinked from the top-level location to the embedded location,
4204469138eSBen Langmuir   // and we need to resolve lookups as if we had found the embedded location.
4214469138eSBen Langmuir   StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
4224469138eSBen Langmuir 
4234469138eSBen Langmuir   // Keep walking up the directory hierarchy, looking for a directory with
4244469138eSBen Langmuir   // an umbrella header.
4254469138eSBen Langmuir   do {
4264469138eSBen Langmuir     auto KnownDir = UmbrellaDirs.find(Dir);
4274469138eSBen Langmuir     if (KnownDir != UmbrellaDirs.end())
4284469138eSBen Langmuir       return KnownHeader(KnownDir->second, NormalHeader);
4294469138eSBen Langmuir 
4304469138eSBen Langmuir     IntermediateDirs.push_back(Dir);
4314469138eSBen Langmuir 
4324469138eSBen Langmuir     // Retrieve our parent path.
4334469138eSBen Langmuir     DirName = llvm::sys::path::parent_path(DirName);
4344469138eSBen Langmuir     if (DirName.empty())
4354469138eSBen Langmuir       break;
4364469138eSBen Langmuir 
4374469138eSBen Langmuir     // Resolve the parent path to a directory entry.
4388d323d15SHarlan Haskins     if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName))
4398d323d15SHarlan Haskins       Dir = *DirEntry;
4408d323d15SHarlan Haskins     else
4418d323d15SHarlan Haskins       Dir = nullptr;
4424469138eSBen Langmuir   } while (Dir);
443afd1b1c9SEugene Zelenko   return {};
4444469138eSBen Langmuir }
4454469138eSBen Langmuir 
44692669ee4SDaniel Jasper static bool violatesPrivateInclude(Module *RequestingModule,
44792669ee4SDaniel Jasper                                    const FileEntry *IncFileEnt,
4484eb8393cSRichard Smith                                    ModuleMap::KnownHeader Header) {
44992669ee4SDaniel Jasper #ifndef NDEBUG
4504eb8393cSRichard Smith   if (Header.getRole() & ModuleMap::PrivateHeader) {
45192669ee4SDaniel Jasper     // Check for consistency between the module header role
45292669ee4SDaniel Jasper     // as obtained from the lookup and as obtained from the module.
45392669ee4SDaniel Jasper     // This check is not cheap, so enable it only for debugging.
4542708e520SRichard Smith     bool IsPrivate = false;
4552708e520SRichard Smith     SmallVectorImpl<Module::Header> *HeaderList[] = {
4564eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_Private],
4574eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_PrivateTextual]};
4582708e520SRichard Smith     for (auto *Hs : HeaderList)
4592708e520SRichard Smith       IsPrivate |=
4602708e520SRichard Smith           std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) {
4613c1a41adSRichard Smith             return H.Entry == IncFileEnt;
4622708e520SRichard Smith           }) != Hs->end();
4634eb8393cSRichard Smith     assert(IsPrivate && "inconsistent headers and roles");
46400bc95ecSRichard Smith   }
46592669ee4SDaniel Jasper #endif
4664eb8393cSRichard Smith   return !Header.isAccessibleFrom(RequestingModule);
46792669ee4SDaniel Jasper }
46892669ee4SDaniel Jasper 
46971e1a64fSBen Langmuir static Module *getTopLevelOrNull(Module *M) {
47071e1a64fSBen Langmuir   return M ? M->getTopLevelModule() : nullptr;
47171e1a64fSBen Langmuir }
47271e1a64fSBen Langmuir 
47392669ee4SDaniel Jasper void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
4748d4e90b3SRichard Smith                                         bool RequestingModuleIsModuleInterface,
47592669ee4SDaniel Jasper                                         SourceLocation FilenameLoc,
47692669ee4SDaniel Jasper                                         StringRef Filename,
47792669ee4SDaniel Jasper                                         const FileEntry *File) {
47892669ee4SDaniel Jasper   // No errors for indirect modules. This may be a bit of a problem for modules
47992669ee4SDaniel Jasper   // with no source files.
48071e1a64fSBen Langmuir   if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
48192669ee4SDaniel Jasper     return;
48292669ee4SDaniel Jasper 
483040e1266SRichard Smith   if (RequestingModule) {
48492669ee4SDaniel Jasper     resolveUses(RequestingModule, /*Complain=*/false);
485040e1266SRichard Smith     resolveHeaderDirectives(RequestingModule);
486040e1266SRichard Smith   }
48792669ee4SDaniel Jasper 
48871e1a64fSBen Langmuir   bool Excluded = false;
489d2d442caSCraig Topper   Module *Private = nullptr;
490d2d442caSCraig Topper   Module *NotUsed = nullptr;
49171e1a64fSBen Langmuir 
49271e1a64fSBen Langmuir   HeadersMap::iterator Known = findKnownHeader(File);
49371e1a64fSBen Langmuir   if (Known != Headers.end()) {
49471e1a64fSBen Langmuir     for (const KnownHeader &Header : Known->second) {
49592669ee4SDaniel Jasper       // Remember private headers for later printing of a diagnostic.
4964eb8393cSRichard Smith       if (violatesPrivateInclude(RequestingModule, File, Header)) {
49771e1a64fSBen Langmuir         Private = Header.getModule();
49892669ee4SDaniel Jasper         continue;
49992669ee4SDaniel Jasper       }
50092669ee4SDaniel Jasper 
50192669ee4SDaniel Jasper       // If uses need to be specified explicitly, we are only allowed to return
50292669ee4SDaniel Jasper       // modules that are explicitly used by the requesting module.
50392669ee4SDaniel Jasper       if (RequestingModule && LangOpts.ModulesDeclUse &&
5048f4d3ff1SRichard Smith           !RequestingModule->directlyUses(Header.getModule())) {
50571e1a64fSBen Langmuir         NotUsed = Header.getModule();
50692669ee4SDaniel Jasper         continue;
50792669ee4SDaniel Jasper       }
50892669ee4SDaniel Jasper 
50992669ee4SDaniel Jasper       // We have found a module that we can happily use.
51092669ee4SDaniel Jasper       return;
51192669ee4SDaniel Jasper     }
512feb54b6dSRichard Smith 
513feb54b6dSRichard Smith     Excluded = true;
51471e1a64fSBen Langmuir   }
51592669ee4SDaniel Jasper 
51692669ee4SDaniel Jasper   // We have found a header, but it is private.
517d2d442caSCraig Topper   if (Private) {
51811152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
51992669ee4SDaniel Jasper         << Filename;
52092669ee4SDaniel Jasper     return;
52192669ee4SDaniel Jasper   }
52292669ee4SDaniel Jasper 
52392669ee4SDaniel Jasper   // We have found a module, but we don't use it.
524d2d442caSCraig Topper   if (NotUsed) {
52511152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5264ea330c8SDaniel Jasper         << RequestingModule->getTopLevelModule()->Name << Filename;
52792669ee4SDaniel Jasper     return;
52892669ee4SDaniel Jasper   }
52992669ee4SDaniel Jasper 
53071e1a64fSBen Langmuir   if (Excluded || isHeaderInUmbrellaDirs(File))
53171e1a64fSBen Langmuir     return;
53271e1a64fSBen Langmuir 
53371e1a64fSBen Langmuir   // At this point, only non-modular includes remain.
53471e1a64fSBen Langmuir 
5355904c41eSBenjamin Kramer   if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
53611152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5374ea330c8SDaniel Jasper         << RequestingModule->getTopLevelModule()->Name << Filename;
538a67e4d32SManman Ren   } else if (RequestingModule && RequestingModuleIsModuleInterface &&
539a67e4d32SManman Ren              LangOpts.isCompilingModule()) {
540a67e4d32SManman Ren     // Do not diagnose when we are not compiling a module.
54171e1a64fSBen Langmuir     diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
54271e1a64fSBen Langmuir         diag::warn_non_modular_include_in_framework_module :
54371e1a64fSBen Langmuir         diag::warn_non_modular_include_in_module;
54470a7738fSManman Ren     Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
54570a7738fSManman Ren         << File->getName();
54671e1a64fSBen Langmuir   }
54792669ee4SDaniel Jasper }
54892669ee4SDaniel Jasper 
549ec87a50aSRichard Smith static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
550ec87a50aSRichard Smith                                 const ModuleMap::KnownHeader &Old) {
5518b7c0398SSean Silva   // Prefer available modules.
5526bc75023SRichard Smith   // FIXME: Considering whether the module is available rather than merely
5536bc75023SRichard Smith   // importable is non-hermetic and can result in surprising behavior for
5546bc75023SRichard Smith   // prebuilt modules. Consider only checking for importability here.
5558b7c0398SSean Silva   if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
5568b7c0398SSean Silva     return true;
5578b7c0398SSean Silva 
558ec87a50aSRichard Smith   // Prefer a public header over a private header.
559ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::PrivateHeader) !=
560ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::PrivateHeader))
561ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::PrivateHeader);
562ec87a50aSRichard Smith 
563ec87a50aSRichard Smith   // Prefer a non-textual header over a textual header.
564ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::TextualHeader) !=
565ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::TextualHeader))
566ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::TextualHeader);
567ec87a50aSRichard Smith 
568ec87a50aSRichard Smith   // Don't have a reason to choose between these. Just keep the first one.
569ec87a50aSRichard Smith   return false;
570ec87a50aSRichard Smith }
571ec87a50aSRichard Smith 
572ed84df00SBruno Cardoso Lopes ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
573ed84df00SBruno Cardoso Lopes                                                       bool AllowTextual) {
574306d8920SRichard Smith   auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
575ed84df00SBruno Cardoso Lopes     if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
576afd1b1c9SEugene Zelenko       return {};
577306d8920SRichard Smith     return R;
578306d8920SRichard Smith   };
579306d8920SRichard Smith 
5804881e8b2SSean Silva   HeadersMap::iterator Known = findKnownHeader(File);
5811fb5c3a6SDouglas Gregor   if (Known != Headers.end()) {
582202210b3SRichard Smith     ModuleMap::KnownHeader Result;
58397da9178SDaniel Jasper     // Iterate over all modules that 'File' is part of to find the best fit.
5844881e8b2SSean Silva     for (KnownHeader &H : Known->second) {
5857e82e019SRichard Smith       // Prefer a header from the source module over all others.
5867e82e019SRichard Smith       if (H.getModule()->getTopLevelModule() == SourceModule)
5872f633e7cSRichard Smith         return MakeResult(H);
5884881e8b2SSean Silva       if (!Result || isBetterKnownHeader(H, Result))
5894881e8b2SSean Silva         Result = H;
59097da9178SDaniel Jasper     }
591306d8920SRichard Smith     return MakeResult(Result);
5921fb5c3a6SDouglas Gregor   }
593ab0c8a84SDouglas Gregor 
594386bb073SRichard Smith   return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
595386bb073SRichard Smith }
596386bb073SRichard Smith 
597386bb073SRichard Smith ModuleMap::KnownHeader
598386bb073SRichard Smith ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
599386bb073SRichard Smith   assert(!Headers.count(File) && "already have a module for this header");
600386bb073SRichard Smith 
601f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
6024469138eSBen Langmuir   KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
6034469138eSBen Langmuir   if (H) {
6044469138eSBen Langmuir     Module *Result = H.getModule();
605930a85ccSDouglas Gregor 
606930a85ccSDouglas Gregor     // Search up the module stack until we find a module with an umbrella
60773141fa9SDouglas Gregor     // directory.
608930a85ccSDouglas Gregor     Module *UmbrellaModule = Result;
60973141fa9SDouglas Gregor     while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
610930a85ccSDouglas Gregor       UmbrellaModule = UmbrellaModule->Parent;
611930a85ccSDouglas Gregor 
612930a85ccSDouglas Gregor     if (UmbrellaModule->InferSubmodules) {
6139d6448b1SBen Langmuir       const FileEntry *UmbrellaModuleMap =
6149d6448b1SBen Langmuir           getModuleMapFileForUniquing(UmbrellaModule);
6159d6448b1SBen Langmuir 
616a89c5ac4SDouglas Gregor       // Infer submodules for each of the directories we found between
617a89c5ac4SDouglas Gregor       // the directory of the umbrella header and the directory where
618a89c5ac4SDouglas Gregor       // the actual header is located.
6199458f82dSDouglas Gregor       bool Explicit = UmbrellaModule->InferExplicitSubmodules;
6209458f82dSDouglas Gregor 
6217033127bSDouglas Gregor       for (unsigned I = SkippedDirs.size(); I != 0; --I) {
622a89c5ac4SDouglas Gregor         // Find or create the module that corresponds to this directory name.
623056396aeSDouglas Gregor         SmallString<32> NameBuf;
624056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
6254469138eSBen Langmuir             llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
6269d6448b1SBen Langmuir         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6279d6448b1SBen Langmuir                                     Explicit).first;
6289d6448b1SBen Langmuir         InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
629ffbafa2aSBen Langmuir         Result->IsInferred = true;
630a89c5ac4SDouglas Gregor 
631a89c5ac4SDouglas Gregor         // Associate the module and the directory.
632a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I-1]] = Result;
633a89c5ac4SDouglas Gregor 
634a89c5ac4SDouglas Gregor         // If inferred submodules export everything they import, add a
635a89c5ac4SDouglas Gregor         // wildcard to the set of exports.
636930a85ccSDouglas Gregor         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
637d2d442caSCraig Topper           Result->Exports.push_back(Module::ExportDecl(nullptr, true));
638a89c5ac4SDouglas Gregor       }
639a89c5ac4SDouglas Gregor 
640a89c5ac4SDouglas Gregor       // Infer a submodule with the same name as this header file.
641056396aeSDouglas Gregor       SmallString<32> NameBuf;
642056396aeSDouglas Gregor       StringRef Name = sanitizeFilenameAsIdentifier(
643056396aeSDouglas Gregor                          llvm::sys::path::stem(File->getName()), NameBuf);
6449d6448b1SBen Langmuir       Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6459d6448b1SBen Langmuir                                   Explicit).first;
6469d6448b1SBen Langmuir       InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
647ffbafa2aSBen Langmuir       Result->IsInferred = true;
6483c5305c1SArgyrios Kyrtzidis       Result->addTopHeader(File);
649a89c5ac4SDouglas Gregor 
650a89c5ac4SDouglas Gregor       // If inferred submodules export everything they import, add a
651a89c5ac4SDouglas Gregor       // wildcard to the set of exports.
652930a85ccSDouglas Gregor       if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
653d2d442caSCraig Topper         Result->Exports.push_back(Module::ExportDecl(nullptr, true));
654a89c5ac4SDouglas Gregor     } else {
655a89c5ac4SDouglas Gregor       // Record each of the directories we stepped through as being part of
656a89c5ac4SDouglas Gregor       // the module we found, since the umbrella header covers them all.
657a89c5ac4SDouglas Gregor       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
658a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I]] = Result;
659a89c5ac4SDouglas Gregor     }
660a89c5ac4SDouglas Gregor 
661386bb073SRichard Smith     KnownHeader Header(Result, NormalHeader);
662386bb073SRichard Smith     Headers[File].push_back(Header);
663386bb073SRichard Smith     return Header;
664a89c5ac4SDouglas Gregor   }
665a89c5ac4SDouglas Gregor 
666afd1b1c9SEugene Zelenko   return {};
667ab0c8a84SDouglas Gregor }
668ab0c8a84SDouglas Gregor 
669386bb073SRichard Smith ArrayRef<ModuleMap::KnownHeader>
6700a088eadSRichard Smith ModuleMap::findAllModulesForHeader(const FileEntry *File) {
6710a088eadSRichard Smith   HeadersMap::iterator Known = findKnownHeader(File);
6720a088eadSRichard Smith   if (Known != Headers.end())
6730a088eadSRichard Smith     return Known->second;
6740a088eadSRichard Smith 
6750a088eadSRichard Smith   if (findOrCreateModuleForHeaderInUmbrellaDir(File))
6760a088eadSRichard Smith     return Headers.find(File)->second;
6770a088eadSRichard Smith 
6780a088eadSRichard Smith   return None;
6790a088eadSRichard Smith }
6800a088eadSRichard Smith 
6810a088eadSRichard Smith ArrayRef<ModuleMap::KnownHeader>
6820a088eadSRichard Smith ModuleMap::findResolvedModulesForHeader(const FileEntry *File) const {
6830a088eadSRichard Smith   // FIXME: Is this necessary?
684040e1266SRichard Smith   resolveHeaderDirectives(File);
685386bb073SRichard Smith   auto It = Headers.find(File);
686386bb073SRichard Smith   if (It == Headers.end())
687386bb073SRichard Smith     return None;
688386bb073SRichard Smith   return It->second;
689386bb073SRichard Smith }
690386bb073SRichard Smith 
691e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
692d2d442caSCraig Topper   return isHeaderUnavailableInModule(Header, nullptr);
69350996ce1SRichard Smith }
69450996ce1SRichard Smith 
69562bcd925SDmitri Gribenko bool
69662bcd925SDmitri Gribenko ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
69762bcd925SDmitri Gribenko                                        const Module *RequestingModule) const {
698040e1266SRichard Smith   resolveHeaderDirectives(Header);
699e4412640SArgyrios Kyrtzidis   HeadersMap::const_iterator Known = Headers.find(Header);
70097da9178SDaniel Jasper   if (Known != Headers.end()) {
70197da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator
70297da9178SDaniel Jasper              I = Known->second.begin(),
70397da9178SDaniel Jasper              E = Known->second.end();
70497da9178SDaniel Jasper          I != E; ++I) {
705052d95a6SBruno Cardoso Lopes 
706052d95a6SBruno Cardoso Lopes       if (I->isAvailable() &&
707052d95a6SBruno Cardoso Lopes           (!RequestingModule ||
708052d95a6SBruno Cardoso Lopes            I->getModule()->isSubModuleOf(RequestingModule))) {
709052d95a6SBruno Cardoso Lopes         // When no requesting module is available, the caller is looking if a
710052d95a6SBruno Cardoso Lopes         // header is part a module by only looking into the module map. This is
711052d95a6SBruno Cardoso Lopes         // done by warn_uncovered_module_header checks; don't consider textual
712052d95a6SBruno Cardoso Lopes         // headers part of it in this mode, otherwise we get misleading warnings
713052d95a6SBruno Cardoso Lopes         // that a umbrella header is not including a textual header.
714052d95a6SBruno Cardoso Lopes         if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
715052d95a6SBruno Cardoso Lopes           continue;
71697da9178SDaniel Jasper         return false;
71797da9178SDaniel Jasper       }
718052d95a6SBruno Cardoso Lopes     }
71997da9178SDaniel Jasper     return true;
72097da9178SDaniel Jasper   }
7211fb5c3a6SDouglas Gregor 
7221fb5c3a6SDouglas Gregor   const DirectoryEntry *Dir = Header->getDir();
723f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
7241fb5c3a6SDouglas Gregor   StringRef DirName = Dir->getName();
7251fb5c3a6SDouglas Gregor 
72650996ce1SRichard Smith   auto IsUnavailable = [&](const Module *M) {
72750996ce1SRichard Smith     return !M->isAvailable() && (!RequestingModule ||
72850996ce1SRichard Smith                                  M->isSubModuleOf(RequestingModule));
72950996ce1SRichard Smith   };
73050996ce1SRichard Smith 
7311fb5c3a6SDouglas Gregor   // Keep walking up the directory hierarchy, looking for a directory with
7321fb5c3a6SDouglas Gregor   // an umbrella header.
7331fb5c3a6SDouglas Gregor   do {
734e4412640SArgyrios Kyrtzidis     llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
7351fb5c3a6SDouglas Gregor       = UmbrellaDirs.find(Dir);
7361fb5c3a6SDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
7371fb5c3a6SDouglas Gregor       Module *Found = KnownDir->second;
73850996ce1SRichard Smith       if (IsUnavailable(Found))
7391fb5c3a6SDouglas Gregor         return true;
7401fb5c3a6SDouglas Gregor 
7411fb5c3a6SDouglas Gregor       // Search up the module stack until we find a module with an umbrella
7421fb5c3a6SDouglas Gregor       // directory.
7431fb5c3a6SDouglas Gregor       Module *UmbrellaModule = Found;
7441fb5c3a6SDouglas Gregor       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
7451fb5c3a6SDouglas Gregor         UmbrellaModule = UmbrellaModule->Parent;
7461fb5c3a6SDouglas Gregor 
7471fb5c3a6SDouglas Gregor       if (UmbrellaModule->InferSubmodules) {
7481fb5c3a6SDouglas Gregor         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
7491fb5c3a6SDouglas Gregor           // Find or create the module that corresponds to this directory name.
750056396aeSDouglas Gregor           SmallString<32> NameBuf;
751056396aeSDouglas Gregor           StringRef Name = sanitizeFilenameAsIdentifier(
752056396aeSDouglas Gregor                              llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
753056396aeSDouglas Gregor                              NameBuf);
7541fb5c3a6SDouglas Gregor           Found = lookupModuleQualified(Name, Found);
7551fb5c3a6SDouglas Gregor           if (!Found)
7561fb5c3a6SDouglas Gregor             return false;
75750996ce1SRichard Smith           if (IsUnavailable(Found))
7581fb5c3a6SDouglas Gregor             return true;
7591fb5c3a6SDouglas Gregor         }
7601fb5c3a6SDouglas Gregor 
7611fb5c3a6SDouglas Gregor         // Infer a submodule with the same name as this header file.
762056396aeSDouglas Gregor         SmallString<32> NameBuf;
763056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
764056396aeSDouglas Gregor                            llvm::sys::path::stem(Header->getName()),
765056396aeSDouglas Gregor                            NameBuf);
7661fb5c3a6SDouglas Gregor         Found = lookupModuleQualified(Name, Found);
7671fb5c3a6SDouglas Gregor         if (!Found)
7681fb5c3a6SDouglas Gregor           return false;
7691fb5c3a6SDouglas Gregor       }
7701fb5c3a6SDouglas Gregor 
77150996ce1SRichard Smith       return IsUnavailable(Found);
7721fb5c3a6SDouglas Gregor     }
7731fb5c3a6SDouglas Gregor 
7741fb5c3a6SDouglas Gregor     SkippedDirs.push_back(Dir);
7751fb5c3a6SDouglas Gregor 
7761fb5c3a6SDouglas Gregor     // Retrieve our parent path.
7771fb5c3a6SDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
7781fb5c3a6SDouglas Gregor     if (DirName.empty())
7791fb5c3a6SDouglas Gregor       break;
7801fb5c3a6SDouglas Gregor 
7811fb5c3a6SDouglas Gregor     // Resolve the parent path to a directory entry.
7828d323d15SHarlan Haskins     if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName))
7838d323d15SHarlan Haskins       Dir = *DirEntry;
7848d323d15SHarlan Haskins     else
7858d323d15SHarlan Haskins       Dir = nullptr;
7861fb5c3a6SDouglas Gregor   } while (Dir);
7871fb5c3a6SDouglas Gregor 
7881fb5c3a6SDouglas Gregor   return false;
7891fb5c3a6SDouglas Gregor }
7901fb5c3a6SDouglas Gregor 
791e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const {
792e4412640SArgyrios Kyrtzidis   llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
79388bdfb0eSDouglas Gregor   if (Known != Modules.end())
79488bdfb0eSDouglas Gregor     return Known->getValue();
79588bdfb0eSDouglas Gregor 
796d2d442caSCraig Topper   return nullptr;
79788bdfb0eSDouglas Gregor }
79888bdfb0eSDouglas Gregor 
799e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
800e4412640SArgyrios Kyrtzidis                                            Module *Context) const {
8012b82c2a5SDouglas Gregor   for(; Context; Context = Context->Parent) {
8022b82c2a5SDouglas Gregor     if (Module *Sub = lookupModuleQualified(Name, Context))
8032b82c2a5SDouglas Gregor       return Sub;
8042b82c2a5SDouglas Gregor   }
8052b82c2a5SDouglas Gregor 
8062b82c2a5SDouglas Gregor   return findModule(Name);
8072b82c2a5SDouglas Gregor }
8082b82c2a5SDouglas Gregor 
809e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
8102b82c2a5SDouglas Gregor   if (!Context)
8112b82c2a5SDouglas Gregor     return findModule(Name);
8122b82c2a5SDouglas Gregor 
813eb90e830SDouglas Gregor   return Context->findSubmodule(Name);
8142b82c2a5SDouglas Gregor }
8152b82c2a5SDouglas Gregor 
816c192d194SBruno Cardoso Lopes std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
817c192d194SBruno Cardoso Lopes                                                         Module *Parent,
818c192d194SBruno Cardoso Lopes                                                         bool IsFramework,
819c192d194SBruno Cardoso Lopes                                                         bool IsExplicit) {
82069021974SDouglas Gregor   // Try to find an existing module with this name.
821eb90e830SDouglas Gregor   if (Module *Sub = lookupModuleQualified(Name, Parent))
822eb90e830SDouglas Gregor     return std::make_pair(Sub, false);
82369021974SDouglas Gregor 
82469021974SDouglas Gregor   // Create a new module with this name.
8259ffe5a35SDavid Blaikie   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
8269ffe5a35SDavid Blaikie                               IsExplicit, NumCreatedModules++);
8276f722b4eSArgyrios Kyrtzidis   if (!Parent) {
8287e82e019SRichard Smith     if (LangOpts.CurrentModule == Name)
8297e82e019SRichard Smith       SourceModule = Result;
83069021974SDouglas Gregor     Modules[Name] = Result;
831c192d194SBruno Cardoso Lopes     ModuleScopeIDs[Result] = CurrentModuleScopeID;
8326f722b4eSArgyrios Kyrtzidis   }
83369021974SDouglas Gregor   return std::make_pair(Result, true);
83469021974SDouglas Gregor }
83569021974SDouglas Gregor 
836a5bbbfefSRichard Smith Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc) {
837d6509cf2SRichard Smith   PendingSubmodules.emplace_back(
838056bf77fSRichard Smith       new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
839056bf77fSRichard Smith                  /*IsExplicit*/ true, NumCreatedModules++));
840d6509cf2SRichard Smith   PendingSubmodules.back()->Kind = Module::GlobalModuleFragment;
841d6509cf2SRichard Smith   return PendingSubmodules.back().get();
842dd8b5337SRichard Smith }
843dd8b5337SRichard Smith 
844a5bbbfefSRichard Smith Module *
845a5bbbfefSRichard Smith ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
846a5bbbfefSRichard Smith                                                        SourceLocation Loc) {
847a5bbbfefSRichard Smith   auto *Result =
848a5bbbfefSRichard Smith       new Module("<private>", Loc, Parent, /*IsFramework*/ false,
849a5bbbfefSRichard Smith                  /*IsExplicit*/ true, NumCreatedModules++);
850a5bbbfefSRichard Smith   Result->Kind = Module::PrivateModuleFragment;
851a5bbbfefSRichard Smith   return Result;
852a5bbbfefSRichard Smith }
853a5bbbfefSRichard Smith 
854bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
855dd8b5337SRichard Smith                                                 StringRef Name,
856dd8b5337SRichard Smith                                                 Module *GlobalModule) {
857bbcc9f04SRichard Smith   assert(LangOpts.CurrentModule == Name && "module name mismatch");
858bbcc9f04SRichard Smith   assert(!Modules[Name] && "redefining existing module");
859bbcc9f04SRichard Smith 
860bbcc9f04SRichard Smith   auto *Result =
861bbcc9f04SRichard Smith       new Module(Name, Loc, nullptr, /*IsFramework*/ false,
862bbcc9f04SRichard Smith                  /*IsExplicit*/ false, NumCreatedModules++);
863145e15a3SRichard Smith   Result->Kind = Module::ModuleInterfaceUnit;
864bbcc9f04SRichard Smith   Modules[Name] = SourceModule = Result;
865bbcc9f04SRichard Smith 
866dd8b5337SRichard Smith   // Reparent the current global module fragment as a submodule of this module.
867d6509cf2SRichard Smith   for (auto &Submodule : PendingSubmodules) {
868d6509cf2SRichard Smith     Submodule->setParent(Result);
869d6509cf2SRichard Smith     Submodule.release(); // now owned by parent
870d6509cf2SRichard Smith   }
871d6509cf2SRichard Smith   PendingSubmodules.clear();
872dd8b5337SRichard Smith 
873bbcc9f04SRichard Smith   // Mark the main source file as being within the newly-created module so that
874bbcc9f04SRichard Smith   // declarations and macros are properly visibility-restricted to it.
875bbcc9f04SRichard Smith   auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
876bbcc9f04SRichard Smith   assert(MainFile && "no input file for module interface");
877bbcc9f04SRichard Smith   Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader));
878bbcc9f04SRichard Smith 
879bbcc9f04SRichard Smith   return Result;
880bbcc9f04SRichard Smith }
881bbcc9f04SRichard Smith 
882d6509cf2SRichard Smith Module *ModuleMap::createHeaderModule(StringRef Name,
883d6509cf2SRichard Smith                                       ArrayRef<Module::Header> Headers) {
884d6509cf2SRichard Smith   assert(LangOpts.CurrentModule == Name && "module name mismatch");
885d6509cf2SRichard Smith   assert(!Modules[Name] && "redefining existing module");
886d6509cf2SRichard Smith 
887d6509cf2SRichard Smith   auto *Result =
888d6509cf2SRichard Smith       new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false,
889d6509cf2SRichard Smith                  /*IsExplicit*/ false, NumCreatedModules++);
890d6509cf2SRichard Smith   Result->Kind = Module::ModuleInterfaceUnit;
891d6509cf2SRichard Smith   Modules[Name] = SourceModule = Result;
892d6509cf2SRichard Smith 
893d6509cf2SRichard Smith   for (const Module::Header &H : Headers) {
894d6509cf2SRichard Smith     auto *M = new Module(H.NameAsWritten, SourceLocation(), Result,
895d6509cf2SRichard Smith                          /*IsFramework*/ false,
896d6509cf2SRichard Smith                          /*IsExplicit*/ true, NumCreatedModules++);
897d6509cf2SRichard Smith     // Header modules are implicitly 'export *'.
898d6509cf2SRichard Smith     M->Exports.push_back(Module::ExportDecl(nullptr, true));
899d6509cf2SRichard Smith     addHeader(M, H, NormalHeader);
900d6509cf2SRichard Smith   }
901d6509cf2SRichard Smith 
902d6509cf2SRichard Smith   return Result;
903d6509cf2SRichard Smith }
904d6509cf2SRichard Smith 
9059fc8faf9SAdrian Prantl /// For a framework module, infer the framework against which we
90611dfe6feSDouglas Gregor /// should link.
90711dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
90811dfe6feSDouglas Gregor                                FileManager &FileMgr) {
90911dfe6feSDouglas Gregor   assert(Mod->IsFramework && "Can only infer linking for framework modules");
91011dfe6feSDouglas Gregor   assert(!Mod->isSubFramework() &&
91111dfe6feSDouglas Gregor          "Can only infer linking for top-level frameworks");
91211dfe6feSDouglas Gregor 
91311dfe6feSDouglas Gregor   SmallString<128> LibName;
91411dfe6feSDouglas Gregor   LibName += FrameworkDir->getName();
91511dfe6feSDouglas Gregor   llvm::sys::path::append(LibName, Mod->Name);
9168aaae5a9SJuergen Ributzka 
9178aaae5a9SJuergen Ributzka   // The library name of a framework has more than one possible extension since
9188aaae5a9SJuergen Ributzka   // the introduction of the text-based dynamic library format. We need to check
9198aaae5a9SJuergen Ributzka   // for both before we give up.
9208013e81dSBenjamin Kramer   for (const char *extension : {"", ".tbd"}) {
9218aaae5a9SJuergen Ributzka     llvm::sys::path::replace_extension(LibName, extension);
92211dfe6feSDouglas Gregor     if (FileMgr.getFile(LibName)) {
92311dfe6feSDouglas Gregor       Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
92411dfe6feSDouglas Gregor                                                        /*IsFramework=*/true));
9258aaae5a9SJuergen Ributzka       return;
9268aaae5a9SJuergen Ributzka     }
92711dfe6feSDouglas Gregor   }
92811dfe6feSDouglas Gregor }
92911dfe6feSDouglas Gregor 
930a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
931a525400dSBen Langmuir                                         bool IsSystem, Module *Parent) {
932c1d88ea5SBen Langmuir   Attributes Attrs;
933c1d88ea5SBen Langmuir   Attrs.IsSystem = IsSystem;
934a525400dSBen Langmuir   return inferFrameworkModule(FrameworkDir, Attrs, Parent);
935c1d88ea5SBen Langmuir }
936c1d88ea5SBen Langmuir 
937a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
938c1d88ea5SBen Langmuir                                         Attributes Attrs, Module *Parent) {
939a525400dSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
940a525400dSBen Langmuir   // we might be looking at an embedded framework that symlinks out to a
941a525400dSBen Langmuir   // top-level framework, and we need to infer as if we were naming the
942a525400dSBen Langmuir   // top-level framework.
943a525400dSBen Langmuir   StringRef FrameworkDirName =
944a525400dSBen Langmuir       SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
945a525400dSBen Langmuir 
946a525400dSBen Langmuir   // In case this is a case-insensitive filesystem, use the canonical
947a525400dSBen Langmuir   // directory name as the ModuleName, since modules are case-sensitive.
948a525400dSBen Langmuir   // FIXME: we should be able to give a fix-it hint for the correct spelling.
949a525400dSBen Langmuir   SmallString<32> ModuleNameStorage;
950a525400dSBen Langmuir   StringRef ModuleName = sanitizeFilenameAsIdentifier(
951a525400dSBen Langmuir       llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
952c1d88ea5SBen Langmuir 
95356c64013SDouglas Gregor   // Check whether we've already found this module.
954e89dbc1dSDouglas Gregor   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
955e89dbc1dSDouglas Gregor     return Mod;
956e89dbc1dSDouglas Gregor 
9571f76c4e8SManuel Klimek   FileManager &FileMgr = SourceMgr.getFileManager();
95856c64013SDouglas Gregor 
9599194a91dSDouglas Gregor   // If the framework has a parent path from which we're allowed to infer
9609194a91dSDouglas Gregor   // a framework module, do so.
961beee15e7SBen Langmuir   const FileEntry *ModuleMapFile = nullptr;
9629194a91dSDouglas Gregor   if (!Parent) {
9634ddf2221SDouglas Gregor     // Determine whether we're allowed to infer a module map.
9649194a91dSDouglas Gregor     bool canInfer = false;
9654ddf2221SDouglas Gregor     if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
9669194a91dSDouglas Gregor       // Figure out the parent path.
9674ddf2221SDouglas Gregor       StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
9688d323d15SHarlan Haskins       if (auto ParentDir = FileMgr.getDirectory(Parent)) {
9699194a91dSDouglas Gregor         // Check whether we have already looked into the parent directory
9709194a91dSDouglas Gregor         // for a module map.
971e4412640SArgyrios Kyrtzidis         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
9728d323d15SHarlan Haskins           inferred = InferredDirectories.find(*ParentDir);
9739194a91dSDouglas Gregor         if (inferred == InferredDirectories.end()) {
9749194a91dSDouglas Gregor           // We haven't looked here before. Load a module map, if there is
9759194a91dSDouglas Gregor           // one.
976984e1df7SBen Langmuir           bool IsFrameworkDir = Parent.endswith(".framework");
9777799ef71SNico Weber           if (const FileEntry *ModMapFile =
9788d323d15SHarlan Haskins                 HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) {
9797799ef71SNico Weber             parseModuleMapFile(ModMapFile, Attrs.IsSystem, *ParentDir);
9808d323d15SHarlan Haskins             inferred = InferredDirectories.find(*ParentDir);
9819194a91dSDouglas Gregor           }
9829194a91dSDouglas Gregor 
9839194a91dSDouglas Gregor           if (inferred == InferredDirectories.end())
9849194a91dSDouglas Gregor             inferred = InferredDirectories.insert(
9858d323d15SHarlan Haskins                          std::make_pair(*ParentDir, InferredDirectory())).first;
9869194a91dSDouglas Gregor         }
9879194a91dSDouglas Gregor 
9889194a91dSDouglas Gregor         if (inferred->second.InferModules) {
9899194a91dSDouglas Gregor           // We're allowed to infer for this directory, but make sure it's okay
9909194a91dSDouglas Gregor           // to infer this particular module.
9914ddf2221SDouglas Gregor           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
9929194a91dSDouglas Gregor           canInfer = std::find(inferred->second.ExcludedModules.begin(),
9939194a91dSDouglas Gregor                                inferred->second.ExcludedModules.end(),
9949194a91dSDouglas Gregor                                Name) == inferred->second.ExcludedModules.end();
9959194a91dSDouglas Gregor 
996c1d88ea5SBen Langmuir           Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
997c1d88ea5SBen Langmuir           Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
998c1d88ea5SBen Langmuir           Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
999ed84df00SBruno Cardoso Lopes           Attrs.NoUndeclaredIncludes |=
1000ed84df00SBruno Cardoso Lopes               inferred->second.Attrs.NoUndeclaredIncludes;
1001beee15e7SBen Langmuir           ModuleMapFile = inferred->second.ModuleMapFile;
10029194a91dSDouglas Gregor         }
10039194a91dSDouglas Gregor       }
10049194a91dSDouglas Gregor     }
10059194a91dSDouglas Gregor 
10069194a91dSDouglas Gregor     // If we're not allowed to infer a framework module, don't.
10079194a91dSDouglas Gregor     if (!canInfer)
1008d2d442caSCraig Topper       return nullptr;
1009beee15e7SBen Langmuir   } else
10109d6448b1SBen Langmuir     ModuleMapFile = getModuleMapFileForUniquing(Parent);
10119194a91dSDouglas Gregor 
10129194a91dSDouglas Gregor 
101356c64013SDouglas Gregor   // Look for an umbrella header.
10142c1dd271SDylan Noblesmith   SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
101517381a06SBenjamin Kramer   llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
101664d8c781SDuncan P. N. Exon Smith   auto UmbrellaHeader = FileMgr.getFile(UmbrellaName);
101756c64013SDouglas Gregor 
101856c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
101956c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
102056c64013SDouglas Gregor   // idea.
102156c64013SDouglas Gregor   if (!UmbrellaHeader)
1022d2d442caSCraig Topper     return nullptr;
102356c64013SDouglas Gregor 
10249d6448b1SBen Langmuir   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
1025a7e2cc68SRichard Smith                               /*IsFramework=*/true, /*IsExplicit=*/false,
1026a7e2cc68SRichard Smith                               NumCreatedModules++);
10279d6448b1SBen Langmuir   InferredModuleAllowedBy[Result] = ModuleMapFile;
10289d6448b1SBen Langmuir   Result->IsInferred = true;
10297e82e019SRichard Smith   if (!Parent) {
10307e82e019SRichard Smith     if (LangOpts.CurrentModule == ModuleName)
1031ba7f2f71SDaniel Jasper       SourceModule = Result;
10327e82e019SRichard Smith     Modules[ModuleName] = Result;
1033c192d194SBruno Cardoso Lopes     ModuleScopeIDs[Result] = CurrentModuleScopeID;
1034ba7f2f71SDaniel Jasper   }
1035c1d88ea5SBen Langmuir 
1036c1d88ea5SBen Langmuir   Result->IsSystem |= Attrs.IsSystem;
1037c1d88ea5SBen Langmuir   Result->IsExternC |= Attrs.IsExternC;
1038c1d88ea5SBen Langmuir   Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
1039ed84df00SBruno Cardoso Lopes   Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
10402b63d15fSRichard Smith   Result->Directory = FrameworkDir;
1041a686e1b0SDouglas Gregor 
1042d3676d4bSMichael Spencer   // Chop off the first framework bit, as that is implied.
1043d3676d4bSMichael Spencer   StringRef RelativePath = UmbrellaName.str().substr(
1044d3676d4bSMichael Spencer       Result->getTopLevelModule()->Directory->getName().size());
1045d3676d4bSMichael Spencer   RelativePath = llvm::sys::path::relative_path(RelativePath);
1046d3676d4bSMichael Spencer 
1047322f633cSDouglas Gregor   // umbrella header "umbrella-header-name"
1048d3676d4bSMichael Spencer   setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h", RelativePath);
1049d8bd7537SDouglas Gregor 
1050d8bd7537SDouglas Gregor   // export *
1051d2d442caSCraig Topper   Result->Exports.push_back(Module::ExportDecl(nullptr, true));
1052d8bd7537SDouglas Gregor 
1053a89c5ac4SDouglas Gregor   // module * { export * }
1054a89c5ac4SDouglas Gregor   Result->InferSubmodules = true;
1055a89c5ac4SDouglas Gregor   Result->InferExportWildcard = true;
1056a89c5ac4SDouglas Gregor 
1057e89dbc1dSDouglas Gregor   // Look for subframeworks.
1058c080917eSRafael Espindola   std::error_code EC;
10592c1dd271SDylan Noblesmith   SmallString<128> SubframeworksDirName
1060ddaa69cbSDouglas Gregor     = StringRef(FrameworkDir->getName());
1061e89dbc1dSDouglas Gregor   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
10622d4d8cb3SBenjamin Kramer   llvm::sys::path::native(SubframeworksDirName);
1063db8a7422SDuncan P. N. Exon Smith   llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
1064fc51490bSJonas Devlieghere   for (llvm::vfs::directory_iterator
1065fc51490bSJonas Devlieghere            Dir = FS.dir_begin(SubframeworksDirName, EC),
1066b171a59bSBruno Cardoso Lopes            DirEnd;
1067e89dbc1dSDouglas Gregor        Dir != DirEnd && !EC; Dir.increment(EC)) {
10680ae00567SSam McCall     if (!StringRef(Dir->path()).endswith(".framework"))
1069e89dbc1dSDouglas Gregor       continue;
1070f2161a70SDouglas Gregor 
10718d323d15SHarlan Haskins     if (auto SubframeworkDir =
10720ae00567SSam McCall             FileMgr.getDirectory(Dir->path())) {
107307c22b78SDouglas Gregor       // Note: as an egregious but useful hack, we use the real path here and
107407c22b78SDouglas Gregor       // check whether it is actually a subdirectory of the parent directory.
107507c22b78SDouglas Gregor       // This will not be the case if the 'subframework' is actually a symlink
107607c22b78SDouglas Gregor       // out to a top-level framework.
10778d323d15SHarlan Haskins       StringRef SubframeworkDirName =
10788d323d15SHarlan Haskins           FileMgr.getCanonicalName(*SubframeworkDir);
107907c22b78SDouglas Gregor       bool FoundParent = false;
108007c22b78SDouglas Gregor       do {
108107c22b78SDouglas Gregor         // Get the parent directory name.
108207c22b78SDouglas Gregor         SubframeworkDirName
108307c22b78SDouglas Gregor           = llvm::sys::path::parent_path(SubframeworkDirName);
108407c22b78SDouglas Gregor         if (SubframeworkDirName.empty())
108507c22b78SDouglas Gregor           break;
108607c22b78SDouglas Gregor 
10878d323d15SHarlan Haskins         if (auto SubDir = FileMgr.getDirectory(SubframeworkDirName)) {
10888d323d15SHarlan Haskins           if (*SubDir == FrameworkDir) {
108907c22b78SDouglas Gregor             FoundParent = true;
109007c22b78SDouglas Gregor             break;
109107c22b78SDouglas Gregor           }
10928d323d15SHarlan Haskins         }
109307c22b78SDouglas Gregor       } while (true);
109407c22b78SDouglas Gregor 
109507c22b78SDouglas Gregor       if (!FoundParent)
109607c22b78SDouglas Gregor         continue;
109707c22b78SDouglas Gregor 
1098e89dbc1dSDouglas Gregor       // FIXME: Do we want to warn about subframeworks without umbrella headers?
10998d323d15SHarlan Haskins       inferFrameworkModule(*SubframeworkDir, Attrs, Result);
1100e89dbc1dSDouglas Gregor     }
1101e89dbc1dSDouglas Gregor   }
1102e89dbc1dSDouglas Gregor 
110311dfe6feSDouglas Gregor   // If the module is a top-level framework, automatically link against the
110411dfe6feSDouglas Gregor   // framework.
110511dfe6feSDouglas Gregor   if (!Result->isSubFramework()) {
110611dfe6feSDouglas Gregor     inferFrameworkLink(Result, FrameworkDir, FileMgr);
110711dfe6feSDouglas Gregor   }
110811dfe6feSDouglas Gregor 
110956c64013SDouglas Gregor   return Result;
111056c64013SDouglas Gregor }
111156c64013SDouglas Gregor 
11128587dfd9SBruno Cardoso Lopes Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
11138587dfd9SBruno Cardoso Lopes                                         Module *ShadowingModule) {
11148587dfd9SBruno Cardoso Lopes 
11158587dfd9SBruno Cardoso Lopes   // Create a new module with this name.
11168587dfd9SBruno Cardoso Lopes   Module *Result =
11178587dfd9SBruno Cardoso Lopes       new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
11188587dfd9SBruno Cardoso Lopes                  /*IsExplicit=*/false, NumCreatedModules++);
11198587dfd9SBruno Cardoso Lopes   Result->ShadowingModule = ShadowingModule;
1120fc76b4adSRichard Smith   Result->markUnavailable(/*Unimportable*/true);
1121c192d194SBruno Cardoso Lopes   ModuleScopeIDs[Result] = CurrentModuleScopeID;
11228587dfd9SBruno Cardoso Lopes   ShadowModules.push_back(Result);
11238587dfd9SBruno Cardoso Lopes 
11248587dfd9SBruno Cardoso Lopes   return Result;
11258587dfd9SBruno Cardoso Lopes }
11268587dfd9SBruno Cardoso Lopes 
1127d3676d4bSMichael Spencer void ModuleMap::setUmbrellaHeader(
1128d3676d4bSMichael Spencer     Module *Mod, const FileEntry *UmbrellaHeader, const Twine &NameAsWritten,
1129d3676d4bSMichael Spencer     const Twine &PathRelativeToRootModuleDirectory) {
113097da9178SDaniel Jasper   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
113164d8c781SDuncan P. N. Exon Smith   Mod->Umbrella = UmbrellaHeader;
11322b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
1133d3676d4bSMichael Spencer   Mod->UmbrellaRelativeToRootModuleDirectory =
1134d3676d4bSMichael Spencer       PathRelativeToRootModuleDirectory.str();
113564d8c781SDuncan P. N. Exon Smith   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
1136b3a0fa48SBruno Cardoso Lopes 
1137b3a0fa48SBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1138b3a0fa48SBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1139b3a0fa48SBruno Cardoso Lopes     Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
1140a89c5ac4SDouglas Gregor }
1141a89c5ac4SDouglas Gregor 
114264d8c781SDuncan P. N. Exon Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
1143d3676d4bSMichael Spencer                                const Twine &NameAsWritten,
1144d3676d4bSMichael Spencer                                const Twine &PathRelativeToRootModuleDirectory) {
114564d8c781SDuncan P. N. Exon Smith   Mod->Umbrella = UmbrellaDir;
11462b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
1147d3676d4bSMichael Spencer   Mod->UmbrellaRelativeToRootModuleDirectory =
1148d3676d4bSMichael Spencer       PathRelativeToRootModuleDirectory.str();
1149524e33e1SDouglas Gregor   UmbrellaDirs[UmbrellaDir] = Mod;
1150524e33e1SDouglas Gregor }
1151524e33e1SDouglas Gregor 
1152040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod,
11539f6020bcSBruno Cardoso Lopes                                     Module::UnresolvedHeaderDirective Header,
11549f6020bcSBruno Cardoso Lopes                                     bool &NeedsFramework) {
1155040e1266SRichard Smith   // If there is a builtin counterpart to this file, add it now so it can
1156040e1266SRichard Smith   // wrap the system header.
1157040e1266SRichard Smith   if (resolveAsBuiltinHeader(Mod, Header)) {
1158040e1266SRichard Smith     // If we have both a builtin and system version of the file, the
1159040e1266SRichard Smith     // builtin version may want to inject macros into the system header, so
1160040e1266SRichard Smith     // force the system header to be treated as a textual header in this
1161040e1266SRichard Smith     // case.
1162040e1266SRichard Smith     Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
1163040e1266SRichard Smith         headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
1164040e1266SRichard Smith     Header.HasBuiltinHeader = true;
11653c1a41adSRichard Smith   }
1166040e1266SRichard Smith 
1167040e1266SRichard Smith   // If possible, don't stat the header until we need to. This requires the
1168040e1266SRichard Smith   // user to have provided us with some stat information about the file.
1169040e1266SRichard Smith   // FIXME: Add support for lazily stat'ing umbrella headers and excluded
1170040e1266SRichard Smith   // headers.
1171040e1266SRichard Smith   if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
1172040e1266SRichard Smith       Header.Kind != Module::HK_Excluded) {
1173040e1266SRichard Smith     // We expect more variation in mtime than size, so if we're given both,
1174040e1266SRichard Smith     // use the mtime as the key.
1175040e1266SRichard Smith     if (Header.ModTime)
1176040e1266SRichard Smith       LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
1177040e1266SRichard Smith     else
1178040e1266SRichard Smith       LazyHeadersBySize[*Header.Size].push_back(Mod);
1179040e1266SRichard Smith     Mod->UnresolvedHeaders.push_back(Header);
1180040e1266SRichard Smith     return;
1181040e1266SRichard Smith   }
1182040e1266SRichard Smith 
1183040e1266SRichard Smith   // We don't have stat information or can't defer looking this file up.
1184040e1266SRichard Smith   // Perform the lookup now.
11859f6020bcSBruno Cardoso Lopes   resolveHeader(Mod, Header, NeedsFramework);
1186040e1266SRichard Smith }
1187040e1266SRichard Smith 
1188040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
1189040e1266SRichard Smith   auto BySize = LazyHeadersBySize.find(File->getSize());
1190040e1266SRichard Smith   if (BySize != LazyHeadersBySize.end()) {
1191040e1266SRichard Smith     for (auto *M : BySize->second)
1192040e1266SRichard Smith       resolveHeaderDirectives(M);
1193040e1266SRichard Smith     LazyHeadersBySize.erase(BySize);
1194040e1266SRichard Smith   }
1195040e1266SRichard Smith 
1196040e1266SRichard Smith   auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
1197040e1266SRichard Smith   if (ByModTime != LazyHeadersByModTime.end()) {
1198040e1266SRichard Smith     for (auto *M : ByModTime->second)
1199040e1266SRichard Smith       resolveHeaderDirectives(M);
1200040e1266SRichard Smith     LazyHeadersByModTime.erase(ByModTime);
1201040e1266SRichard Smith   }
1202040e1266SRichard Smith }
1203040e1266SRichard Smith 
1204040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(Module *Mod) const {
12059f6020bcSBruno Cardoso Lopes   bool NeedsFramework = false;
1206040e1266SRichard Smith   for (auto &Header : Mod->UnresolvedHeaders)
1207040e1266SRichard Smith     // This operation is logically const; we're just changing how we represent
1208040e1266SRichard Smith     // the header information for this file.
12099f6020bcSBruno Cardoso Lopes     const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework);
1210040e1266SRichard Smith   Mod->UnresolvedHeaders.clear();
12110e98d938SNAKAMURA Takumi }
1212202210b3SRichard Smith 
12133c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header,
1214d8879c85SRichard Smith                           ModuleHeaderRole Role, bool Imported) {
1215386bb073SRichard Smith   KnownHeader KH(Mod, Role);
12163c1a41adSRichard Smith 
1217386bb073SRichard Smith   // Only add each header to the headers list once.
1218386bb073SRichard Smith   // FIXME: Should we diagnose if a header is listed twice in the
1219386bb073SRichard Smith   // same module definition?
1220386bb073SRichard Smith   auto &HeaderList = Headers[Header.Entry];
1221386bb073SRichard Smith   for (auto H : HeaderList)
1222386bb073SRichard Smith     if (H == KH)
1223386bb073SRichard Smith       return;
1224386bb073SRichard Smith 
1225386bb073SRichard Smith   HeaderList.push_back(KH);
12261ec383c7SPiotr Padlewski   Mod->Headers[headerRoleToKind(Role)].push_back(Header);
1227386bb073SRichard Smith 
12287e82e019SRichard Smith   bool isCompilingModuleHeader =
1229bbcc9f04SRichard Smith       LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
1230d8879c85SRichard Smith   if (!Imported || isCompilingModuleHeader) {
1231d8879c85SRichard Smith     // When we import HeaderFileInfo, the external source is expected to
1232d8879c85SRichard Smith     // set the isModuleHeader flag itself.
1233d8879c85SRichard Smith     HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
1234d8879c85SRichard Smith                                     isCompilingModuleHeader);
1235d8879c85SRichard Smith   }
1236e62cfd7cSBruno Cardoso Lopes 
1237e62cfd7cSBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1238e62cfd7cSBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1239f0841790SBruno Cardoso Lopes     Cb->moduleMapAddHeader(Header.Entry->getName());
1240a89c5ac4SDouglas Gregor }
1241a89c5ac4SDouglas Gregor 
12423c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
1243feb54b6dSRichard Smith   // Add this as a known header so we won't implicitly add it to any
1244feb54b6dSRichard Smith   // umbrella directory module.
1245feb54b6dSRichard Smith   // FIXME: Should we only exclude it from umbrella modules within the
1246feb54b6dSRichard Smith   // specified module?
12473c1a41adSRichard Smith   (void) Headers[Header.Entry];
12483c1a41adSRichard Smith 
12493c1a41adSRichard Smith   Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
1250feb54b6dSRichard Smith }
1251feb54b6dSRichard Smith 
1252514b636aSDouglas Gregor const FileEntry *
12534b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const {
12541f76c4e8SManuel Klimek   if (Module->DefinitionLoc.isInvalid())
1255d2d442caSCraig Topper     return nullptr;
1256514b636aSDouglas Gregor 
12571f76c4e8SManuel Klimek   return SourceMgr.getFileEntryForID(
12581f76c4e8SManuel Klimek            SourceMgr.getFileID(Module->DefinitionLoc));
1259514b636aSDouglas Gregor }
1260514b636aSDouglas Gregor 
12614b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
12629d6448b1SBen Langmuir   if (M->IsInferred) {
12639d6448b1SBen Langmuir     assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
12649d6448b1SBen Langmuir     return InferredModuleAllowedBy.find(M)->second;
12659d6448b1SBen Langmuir   }
12669d6448b1SBen Langmuir   return getContainingModuleMapFile(M);
12679d6448b1SBen Langmuir }
12689d6448b1SBen Langmuir 
12699d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
12709d6448b1SBen Langmuir   assert(M->IsInferred && "module not inferred");
12719d6448b1SBen Langmuir   InferredModuleAllowedBy[M] = ModMap;
12729d6448b1SBen Langmuir }
12739d6448b1SBen Langmuir 
1274e08464fbSReid Kleckner void ModuleMap::addAdditionalModuleMapFile(const Module *M,
1275e08464fbSReid Kleckner                                            const FileEntry *ModuleMap) {
1276e08464fbSReid Kleckner   AdditionalModMaps[M].insert(ModuleMap);
1277e08464fbSReid Kleckner }
1278e08464fbSReid Kleckner 
1279cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() {
1280718292f2SDouglas Gregor   llvm::errs() << "Modules:";
1281718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1282718292f2SDouglas Gregor                                         MEnd = Modules.end();
1283718292f2SDouglas Gregor        M != MEnd; ++M)
1284d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
1285718292f2SDouglas Gregor 
1286718292f2SDouglas Gregor   llvm::errs() << "Headers:";
128759527666SDouglas Gregor   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1288718292f2SDouglas Gregor        H != HEnd; ++H) {
128997da9178SDaniel Jasper     llvm::errs() << "  \"" << H->first->getName() << "\" -> ";
129097da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
129197da9178SDaniel Jasper                                                       E = H->second.end();
129297da9178SDaniel Jasper          I != E; ++I) {
129397da9178SDaniel Jasper       if (I != H->second.begin())
129497da9178SDaniel Jasper         llvm::errs() << ",";
129597da9178SDaniel Jasper       llvm::errs() << I->getModule()->getFullModuleName();
129697da9178SDaniel Jasper     }
129797da9178SDaniel Jasper     llvm::errs() << "\n";
1298718292f2SDouglas Gregor   }
1299718292f2SDouglas Gregor }
1300718292f2SDouglas Gregor 
13012b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
130242413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedExports);
130342413141SRichard Smith   Mod->UnresolvedExports.clear();
130442413141SRichard Smith   for (auto &UE : Unresolved) {
130542413141SRichard Smith     Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
1306f5eedd05SDouglas Gregor     if (Export.getPointer() || Export.getInt())
13072b82c2a5SDouglas Gregor       Mod->Exports.push_back(Export);
13082b82c2a5SDouglas Gregor     else
130942413141SRichard Smith       Mod->UnresolvedExports.push_back(UE);
13102b82c2a5SDouglas Gregor   }
131142413141SRichard Smith   return !Mod->UnresolvedExports.empty();
13122b82c2a5SDouglas Gregor }
13132b82c2a5SDouglas Gregor 
1314ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
131542413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedDirectUses);
131642413141SRichard Smith   Mod->UnresolvedDirectUses.clear();
131742413141SRichard Smith   for (auto &UDU : Unresolved) {
131842413141SRichard Smith     Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
1319ba7f2f71SDaniel Jasper     if (DirectUse)
1320ba7f2f71SDaniel Jasper       Mod->DirectUses.push_back(DirectUse);
1321ba7f2f71SDaniel Jasper     else
132242413141SRichard Smith       Mod->UnresolvedDirectUses.push_back(UDU);
1323ba7f2f71SDaniel Jasper   }
132442413141SRichard Smith   return !Mod->UnresolvedDirectUses.empty();
1325ba7f2f71SDaniel Jasper }
1326ba7f2f71SDaniel Jasper 
1327fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
132842413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedConflicts);
132942413141SRichard Smith   Mod->UnresolvedConflicts.clear();
133042413141SRichard Smith   for (auto &UC : Unresolved) {
133142413141SRichard Smith     if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1332fb912657SDouglas Gregor       Module::Conflict Conflict;
1333fb912657SDouglas Gregor       Conflict.Other = OtherMod;
133442413141SRichard Smith       Conflict.Message = UC.Message;
1335fb912657SDouglas Gregor       Mod->Conflicts.push_back(Conflict);
133642413141SRichard Smith     } else
133742413141SRichard Smith       Mod->UnresolvedConflicts.push_back(UC);
1338fb912657SDouglas Gregor   }
133942413141SRichard Smith   return !Mod->UnresolvedConflicts.empty();
1340fb912657SDouglas Gregor }
1341fb912657SDouglas Gregor 
1342718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1343718292f2SDouglas Gregor // Module map file parser
1344718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1345718292f2SDouglas Gregor 
1346718292f2SDouglas Gregor namespace clang {
1347afd1b1c9SEugene Zelenko 
13489fc8faf9SAdrian Prantl   /// A token in a module map file.
1349718292f2SDouglas Gregor   struct MMToken {
1350718292f2SDouglas Gregor     enum TokenKind {
13511fb5c3a6SDouglas Gregor       Comma,
135235b13eceSDouglas Gregor       ConfigMacros,
1353fb912657SDouglas Gregor       Conflict,
1354718292f2SDouglas Gregor       EndOfFile,
1355718292f2SDouglas Gregor       HeaderKeyword,
1356718292f2SDouglas Gregor       Identifier,
1357a3feee2aSRichard Smith       Exclaim,
135859527666SDouglas Gregor       ExcludeKeyword,
1359718292f2SDouglas Gregor       ExplicitKeyword,
13602b82c2a5SDouglas Gregor       ExportKeyword,
1361f0b11de2SDouglas Gregor       ExportAsKeyword,
136297292843SDaniel Jasper       ExternKeyword,
1363755b2055SDouglas Gregor       FrameworkKeyword,
13646ddfca91SDouglas Gregor       LinkKeyword,
1365718292f2SDouglas Gregor       ModuleKeyword,
13662b82c2a5SDouglas Gregor       Period,
1367b53e5483SLawrence Crowl       PrivateKeyword,
1368718292f2SDouglas Gregor       UmbrellaKeyword,
1369ba7f2f71SDaniel Jasper       UseKeyword,
13701fb5c3a6SDouglas Gregor       RequiresKeyword,
13712b82c2a5SDouglas Gregor       Star,
1372718292f2SDouglas Gregor       StringLiteral,
1373040e1266SRichard Smith       IntegerLiteral,
1374306d8920SRichard Smith       TextualKeyword,
1375718292f2SDouglas Gregor       LBrace,
1376a686e1b0SDouglas Gregor       RBrace,
1377a686e1b0SDouglas Gregor       LSquare,
1378a686e1b0SDouglas Gregor       RSquare
1379718292f2SDouglas Gregor     } Kind;
1380718292f2SDouglas Gregor 
138121401a72SSimon Tatham     SourceLocation::UIntTy Location;
1382718292f2SDouglas Gregor     unsigned StringLength;
1383040e1266SRichard Smith     union {
1384040e1266SRichard Smith       // If Kind != IntegerLiteral.
1385718292f2SDouglas Gregor       const char *StringData;
1386afd1b1c9SEugene Zelenko 
1387040e1266SRichard Smith       // If Kind == IntegerLiteral.
1388040e1266SRichard Smith       uint64_t IntegerValue;
1389040e1266SRichard Smith     };
1390718292f2SDouglas Gregor 
1391718292f2SDouglas Gregor     void clear() {
1392718292f2SDouglas Gregor       Kind = EndOfFile;
1393718292f2SDouglas Gregor       Location = 0;
1394718292f2SDouglas Gregor       StringLength = 0;
1395d2d442caSCraig Topper       StringData = nullptr;
1396718292f2SDouglas Gregor     }
1397718292f2SDouglas Gregor 
1398718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
1399718292f2SDouglas Gregor 
1400718292f2SDouglas Gregor     SourceLocation getLocation() const {
1401718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
1402718292f2SDouglas Gregor     }
1403718292f2SDouglas Gregor 
1404040e1266SRichard Smith     uint64_t getInteger() const {
1405040e1266SRichard Smith       return Kind == IntegerLiteral ? IntegerValue : 0;
1406040e1266SRichard Smith     }
1407040e1266SRichard Smith 
1408718292f2SDouglas Gregor     StringRef getString() const {
1409040e1266SRichard Smith       return Kind == IntegerLiteral ? StringRef()
1410040e1266SRichard Smith                                     : StringRef(StringData, StringLength);
1411718292f2SDouglas Gregor     }
1412718292f2SDouglas Gregor   };
1413718292f2SDouglas Gregor 
1414718292f2SDouglas Gregor   class ModuleMapParser {
1415718292f2SDouglas Gregor     Lexer &L;
1416718292f2SDouglas Gregor     SourceManager &SourceMgr;
1417bc10b9fbSDouglas Gregor 
14189fc8faf9SAdrian Prantl     /// Default target information, used only for string literal
1419bc10b9fbSDouglas Gregor     /// parsing.
1420bc10b9fbSDouglas Gregor     const TargetInfo *Target;
1421bc10b9fbSDouglas Gregor 
1422718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
1423718292f2SDouglas Gregor     ModuleMap &Map;
1424718292f2SDouglas Gregor 
14259fc8faf9SAdrian Prantl     /// The current module map file.
1426beee15e7SBen Langmuir     const FileEntry *ModuleMapFile;
1427beee15e7SBen Langmuir 
14289f6020bcSBruno Cardoso Lopes     /// Source location of most recent parsed module declaration
14299f6020bcSBruno Cardoso Lopes     SourceLocation CurrModuleDeclLoc;
14309f6020bcSBruno Cardoso Lopes 
14319fc8faf9SAdrian Prantl     /// The directory that file names in this module map file should
14329acb99e3SRichard Smith     /// be resolved relative to.
14335257fc63SDouglas Gregor     const DirectoryEntry *Directory;
14345257fc63SDouglas Gregor 
14359fc8faf9SAdrian Prantl     /// Whether this module map is in a system header directory.
1436963c5535SDouglas Gregor     bool IsSystem;
1437963c5535SDouglas Gregor 
14389fc8faf9SAdrian Prantl     /// Whether an error occurred.
1439afd1b1c9SEugene Zelenko     bool HadError = false;
1440718292f2SDouglas Gregor 
14419fc8faf9SAdrian Prantl     /// Stores string data for the various string literals referenced
1442718292f2SDouglas Gregor     /// during parsing.
1443718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
1444718292f2SDouglas Gregor 
14459fc8faf9SAdrian Prantl     /// The current token.
1446718292f2SDouglas Gregor     MMToken Tok;
1447718292f2SDouglas Gregor 
14489fc8faf9SAdrian Prantl     /// The active module.
1449afd1b1c9SEugene Zelenko     Module *ActiveModule = nullptr;
1450718292f2SDouglas Gregor 
14519fc8faf9SAdrian Prantl     /// Whether a module uses the 'requires excluded' hack to mark its
14527ff29148SBen Langmuir     /// contents as 'textual'.
14537ff29148SBen Langmuir     ///
14547ff29148SBen Langmuir     /// On older Darwin SDK versions, 'requires excluded' is used to mark the
14557ff29148SBen Langmuir     /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
14567ff29148SBen Langmuir     /// non-modular headers.  For backwards compatibility, we continue to
14577ff29148SBen Langmuir     /// support this idiom for just these modules, and map the headers to
14587ff29148SBen Langmuir     /// 'textual' to match the original intent.
14597ff29148SBen Langmuir     llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
14607ff29148SBen Langmuir 
14619fc8faf9SAdrian Prantl     /// Consume the current token and return its location.
1462718292f2SDouglas Gregor     SourceLocation consumeToken();
1463718292f2SDouglas Gregor 
14649fc8faf9SAdrian Prantl     /// Skip tokens until we reach the a token with the given kind
1465718292f2SDouglas Gregor     /// (or the end of the file).
1466718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
1467718292f2SDouglas Gregor 
1468afd1b1c9SEugene Zelenko     using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
1469afd1b1c9SEugene Zelenko 
1470e7ab3669SDouglas Gregor     bool parseModuleId(ModuleId &Id);
1471718292f2SDouglas Gregor     void parseModuleDecl();
147297292843SDaniel Jasper     void parseExternModuleDecl();
14731fb5c3a6SDouglas Gregor     void parseRequiresDecl();
1474afd1b1c9SEugene Zelenko     void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
1475524e33e1SDouglas Gregor     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
14762b82c2a5SDouglas Gregor     void parseExportDecl();
1477f0b11de2SDouglas Gregor     void parseExportAsDecl();
1478ba7f2f71SDaniel Jasper     void parseUseDecl();
14796ddfca91SDouglas Gregor     void parseLinkDecl();
148035b13eceSDouglas Gregor     void parseConfigMacros();
1481fb912657SDouglas Gregor     void parseConflict();
14829194a91dSDouglas Gregor     void parseInferredModuleDecl(bool Framework, bool Explicit);
1483c1d88ea5SBen Langmuir 
14845f11e128SBruno Cardoso Lopes     /// Private modules are canonicalized as Foo_Private. Clang provides extra
14855f11e128SBruno Cardoso Lopes     /// module map search logic to find the appropriate private module when PCH
14865f11e128SBruno Cardoso Lopes     /// is used with implicit module maps. Warn when private modules are written
14875f11e128SBruno Cardoso Lopes     /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
14885f11e128SBruno Cardoso Lopes     void diagnosePrivateModules(SourceLocation ExplicitLoc,
14895f11e128SBruno Cardoso Lopes                                 SourceLocation FrameworkLoc);
14905f11e128SBruno Cardoso Lopes 
1491afd1b1c9SEugene Zelenko     using Attributes = ModuleMap::Attributes;
1492afd1b1c9SEugene Zelenko 
14934442605fSBill Wendling     bool parseOptionalAttributes(Attributes &Attrs);
1494718292f2SDouglas Gregor 
1495718292f2SDouglas Gregor   public:
1496718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
14978587dfd9SBruno Cardoso Lopes                              const TargetInfo *Target, DiagnosticsEngine &Diags,
14988587dfd9SBruno Cardoso Lopes                              ModuleMap &Map, const FileEntry *ModuleMapFile,
1499c192d194SBruno Cardoso Lopes                              const DirectoryEntry *Directory, bool IsSystem)
1500bc10b9fbSDouglas Gregor         : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
1501beee15e7SBen Langmuir           ModuleMapFile(ModuleMapFile), Directory(Directory),
1502c192d194SBruno Cardoso Lopes           IsSystem(IsSystem) {
1503718292f2SDouglas Gregor       Tok.clear();
1504718292f2SDouglas Gregor       consumeToken();
1505718292f2SDouglas Gregor     }
1506718292f2SDouglas Gregor 
1507718292f2SDouglas Gregor     bool parseModuleMapFile();
15088128f332SRichard Smith 
15098128f332SRichard Smith     bool terminatedByDirective() { return false; }
15108128f332SRichard Smith     SourceLocation getLocation() { return Tok.getLocation(); }
1511718292f2SDouglas Gregor   };
1512afd1b1c9SEugene Zelenko 
1513afd1b1c9SEugene Zelenko } // namespace clang
1514718292f2SDouglas Gregor 
1515718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
1516718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
1517718292f2SDouglas Gregor 
15188128f332SRichard Smith retry:
15198128f332SRichard Smith   Tok.clear();
1520718292f2SDouglas Gregor   Token LToken;
1521718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
1522718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
1523718292f2SDouglas Gregor   switch (LToken.getKind()) {
15242d57cea2SAlp Toker   case tok::raw_identifier: {
15252d57cea2SAlp Toker     StringRef RI = LToken.getRawIdentifier();
15262d57cea2SAlp Toker     Tok.StringData = RI.data();
15272d57cea2SAlp Toker     Tok.StringLength = RI.size();
15282d57cea2SAlp Toker     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
152935b13eceSDouglas Gregor                  .Case("config_macros", MMToken::ConfigMacros)
1530fb912657SDouglas Gregor                  .Case("conflict", MMToken::Conflict)
153159527666SDouglas Gregor                  .Case("exclude", MMToken::ExcludeKeyword)
1532718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
15332b82c2a5SDouglas Gregor                  .Case("export", MMToken::ExportKeyword)
1534f0b11de2SDouglas Gregor                  .Case("export_as", MMToken::ExportAsKeyword)
153597292843SDaniel Jasper                  .Case("extern", MMToken::ExternKeyword)
1536755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
153735b13eceSDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
15386ddfca91SDouglas Gregor                  .Case("link", MMToken::LinkKeyword)
1539718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
1540b53e5483SLawrence Crowl                  .Case("private", MMToken::PrivateKeyword)
15411fb5c3a6SDouglas Gregor                  .Case("requires", MMToken::RequiresKeyword)
1542306d8920SRichard Smith                  .Case("textual", MMToken::TextualKeyword)
1543718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
1544ba7f2f71SDaniel Jasper                  .Case("use", MMToken::UseKeyword)
1545718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
1546718292f2SDouglas Gregor     break;
15472d57cea2SAlp Toker   }
1548718292f2SDouglas Gregor 
15491fb5c3a6SDouglas Gregor   case tok::comma:
15501fb5c3a6SDouglas Gregor     Tok.Kind = MMToken::Comma;
15511fb5c3a6SDouglas Gregor     break;
15521fb5c3a6SDouglas Gregor 
1553718292f2SDouglas Gregor   case tok::eof:
1554718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
1555718292f2SDouglas Gregor     break;
1556718292f2SDouglas Gregor 
1557718292f2SDouglas Gregor   case tok::l_brace:
1558718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
1559718292f2SDouglas Gregor     break;
1560718292f2SDouglas Gregor 
1561a686e1b0SDouglas Gregor   case tok::l_square:
1562a686e1b0SDouglas Gregor     Tok.Kind = MMToken::LSquare;
1563a686e1b0SDouglas Gregor     break;
1564a686e1b0SDouglas Gregor 
15652b82c2a5SDouglas Gregor   case tok::period:
15662b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Period;
15672b82c2a5SDouglas Gregor     break;
15682b82c2a5SDouglas Gregor 
1569718292f2SDouglas Gregor   case tok::r_brace:
1570718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
1571718292f2SDouglas Gregor     break;
1572718292f2SDouglas Gregor 
1573a686e1b0SDouglas Gregor   case tok::r_square:
1574a686e1b0SDouglas Gregor     Tok.Kind = MMToken::RSquare;
1575a686e1b0SDouglas Gregor     break;
1576a686e1b0SDouglas Gregor 
15772b82c2a5SDouglas Gregor   case tok::star:
15782b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Star;
15792b82c2a5SDouglas Gregor     break;
15802b82c2a5SDouglas Gregor 
1581a3feee2aSRichard Smith   case tok::exclaim:
1582a3feee2aSRichard Smith     Tok.Kind = MMToken::Exclaim;
1583a3feee2aSRichard Smith     break;
1584a3feee2aSRichard Smith 
1585718292f2SDouglas Gregor   case tok::string_literal: {
1586d67aea28SRichard Smith     if (LToken.hasUDSuffix()) {
1587d67aea28SRichard Smith       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
1588d67aea28SRichard Smith       HadError = true;
1589d67aea28SRichard Smith       goto retry;
1590d67aea28SRichard Smith     }
1591d67aea28SRichard Smith 
1592718292f2SDouglas Gregor     // Parse the string literal.
1593718292f2SDouglas Gregor     LangOptions LangOpts;
15949d5583efSCraig Topper     StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
1595718292f2SDouglas Gregor     if (StringLiteral.hadError)
1596718292f2SDouglas Gregor       goto retry;
1597718292f2SDouglas Gregor 
1598718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
1599718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
1600718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
1601718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
1602718292f2SDouglas Gregor     Saved[Length] = 0;
1603718292f2SDouglas Gregor 
1604718292f2SDouglas Gregor     // Form the token.
1605718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
1606718292f2SDouglas Gregor     Tok.StringData = Saved;
1607718292f2SDouglas Gregor     Tok.StringLength = Length;
1608718292f2SDouglas Gregor     break;
1609718292f2SDouglas Gregor   }
1610718292f2SDouglas Gregor 
1611040e1266SRichard Smith   case tok::numeric_constant: {
1612040e1266SRichard Smith     // We don't support any suffixes or other complications.
1613040e1266SRichard Smith     SmallString<32> SpellingBuffer;
1614040e1266SRichard Smith     SpellingBuffer.resize(LToken.getLength() + 1);
1615040e1266SRichard Smith     const char *Start = SpellingBuffer.data();
1616040e1266SRichard Smith     unsigned Length =
1617040e1266SRichard Smith         Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts());
1618040e1266SRichard Smith     uint64_t Value;
1619040e1266SRichard Smith     if (StringRef(Start, Length).getAsInteger(0, Value)) {
1620040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1621040e1266SRichard Smith       HadError = true;
1622040e1266SRichard Smith       goto retry;
1623040e1266SRichard Smith     }
1624040e1266SRichard Smith 
1625040e1266SRichard Smith     Tok.Kind = MMToken::IntegerLiteral;
1626040e1266SRichard Smith     Tok.IntegerValue = Value;
1627040e1266SRichard Smith     break;
1628040e1266SRichard Smith   }
1629040e1266SRichard Smith 
1630718292f2SDouglas Gregor   case tok::comment:
1631718292f2SDouglas Gregor     goto retry;
1632718292f2SDouglas Gregor 
16338128f332SRichard Smith   case tok::hash:
16348128f332SRichard Smith     // A module map can be terminated prematurely by
16358128f332SRichard Smith     //   #pragma clang module contents
16368128f332SRichard Smith     // When building the module, we'll treat the rest of the file as the
16378128f332SRichard Smith     // contents of the module.
16388128f332SRichard Smith     {
16398128f332SRichard Smith       auto NextIsIdent = [&](StringRef Str) -> bool {
16408128f332SRichard Smith         L.LexFromRawLexer(LToken);
16418128f332SRichard Smith         return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
16428128f332SRichard Smith                LToken.getRawIdentifier() == Str;
16438128f332SRichard Smith       };
16448128f332SRichard Smith       if (NextIsIdent("pragma") && NextIsIdent("clang") &&
16458128f332SRichard Smith           NextIsIdent("module") && NextIsIdent("contents")) {
16468128f332SRichard Smith         Tok.Kind = MMToken::EndOfFile;
16478128f332SRichard Smith         break;
16488128f332SRichard Smith       }
16498128f332SRichard Smith     }
16508128f332SRichard Smith     LLVM_FALLTHROUGH;
16518128f332SRichard Smith 
1652718292f2SDouglas Gregor   default:
16538128f332SRichard Smith     Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1654718292f2SDouglas Gregor     HadError = true;
1655718292f2SDouglas Gregor     goto retry;
1656718292f2SDouglas Gregor   }
1657718292f2SDouglas Gregor 
1658718292f2SDouglas Gregor   return Result;
1659718292f2SDouglas Gregor }
1660718292f2SDouglas Gregor 
1661718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
1662718292f2SDouglas Gregor   unsigned braceDepth = 0;
1663a686e1b0SDouglas Gregor   unsigned squareDepth = 0;
1664718292f2SDouglas Gregor   do {
1665718292f2SDouglas Gregor     switch (Tok.Kind) {
1666718292f2SDouglas Gregor     case MMToken::EndOfFile:
1667718292f2SDouglas Gregor       return;
1668718292f2SDouglas Gregor 
1669718292f2SDouglas Gregor     case MMToken::LBrace:
1670a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1671718292f2SDouglas Gregor         return;
1672718292f2SDouglas Gregor 
1673718292f2SDouglas Gregor       ++braceDepth;
1674718292f2SDouglas Gregor       break;
1675718292f2SDouglas Gregor 
1676a686e1b0SDouglas Gregor     case MMToken::LSquare:
1677a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1678a686e1b0SDouglas Gregor         return;
1679a686e1b0SDouglas Gregor 
1680a686e1b0SDouglas Gregor       ++squareDepth;
1681a686e1b0SDouglas Gregor       break;
1682a686e1b0SDouglas Gregor 
1683718292f2SDouglas Gregor     case MMToken::RBrace:
1684718292f2SDouglas Gregor       if (braceDepth > 0)
1685718292f2SDouglas Gregor         --braceDepth;
1686718292f2SDouglas Gregor       else if (Tok.is(K))
1687718292f2SDouglas Gregor         return;
1688718292f2SDouglas Gregor       break;
1689718292f2SDouglas Gregor 
1690a686e1b0SDouglas Gregor     case MMToken::RSquare:
1691a686e1b0SDouglas Gregor       if (squareDepth > 0)
1692a686e1b0SDouglas Gregor         --squareDepth;
1693a686e1b0SDouglas Gregor       else if (Tok.is(K))
1694a686e1b0SDouglas Gregor         return;
1695a686e1b0SDouglas Gregor       break;
1696a686e1b0SDouglas Gregor 
1697718292f2SDouglas Gregor     default:
1698a686e1b0SDouglas Gregor       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
1699718292f2SDouglas Gregor         return;
1700718292f2SDouglas Gregor       break;
1701718292f2SDouglas Gregor     }
1702718292f2SDouglas Gregor 
1703718292f2SDouglas Gregor    consumeToken();
1704718292f2SDouglas Gregor   } while (true);
1705718292f2SDouglas Gregor }
1706718292f2SDouglas Gregor 
17079fc8faf9SAdrian Prantl /// Parse a module-id.
1708e7ab3669SDouglas Gregor ///
1709e7ab3669SDouglas Gregor ///   module-id:
1710e7ab3669SDouglas Gregor ///     identifier
1711e7ab3669SDouglas Gregor ///     identifier '.' module-id
1712e7ab3669SDouglas Gregor ///
1713e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise.
1714e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) {
1715e7ab3669SDouglas Gregor   Id.clear();
1716e7ab3669SDouglas Gregor   do {
17173cd34c76SDaniel Jasper     if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1718adcd0268SBenjamin Kramer       Id.push_back(
1719adcd0268SBenjamin Kramer           std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
1720e7ab3669SDouglas Gregor       consumeToken();
1721e7ab3669SDouglas Gregor     } else {
1722e7ab3669SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1723e7ab3669SDouglas Gregor       return true;
1724e7ab3669SDouglas Gregor     }
1725e7ab3669SDouglas Gregor 
1726e7ab3669SDouglas Gregor     if (!Tok.is(MMToken::Period))
1727e7ab3669SDouglas Gregor       break;
1728e7ab3669SDouglas Gregor 
1729e7ab3669SDouglas Gregor     consumeToken();
1730e7ab3669SDouglas Gregor   } while (true);
1731e7ab3669SDouglas Gregor 
1732e7ab3669SDouglas Gregor   return false;
1733e7ab3669SDouglas Gregor }
1734e7ab3669SDouglas Gregor 
1735a686e1b0SDouglas Gregor namespace {
1736afd1b1c9SEugene Zelenko 
17379fc8faf9SAdrian Prantl   /// Enumerates the known attributes.
1738a686e1b0SDouglas Gregor   enum AttributeKind {
17399fc8faf9SAdrian Prantl     /// An unknown attribute.
1740a686e1b0SDouglas Gregor     AT_unknown,
1741afd1b1c9SEugene Zelenko 
17429fc8faf9SAdrian Prantl     /// The 'system' attribute.
174335b13eceSDouglas Gregor     AT_system,
1744afd1b1c9SEugene Zelenko 
17459fc8faf9SAdrian Prantl     /// The 'extern_c' attribute.
174677944868SRichard Smith     AT_extern_c,
1747afd1b1c9SEugene Zelenko 
17489fc8faf9SAdrian Prantl     /// The 'exhaustive' attribute.
1749ed84df00SBruno Cardoso Lopes     AT_exhaustive,
1750afd1b1c9SEugene Zelenko 
17519fc8faf9SAdrian Prantl     /// The 'no_undeclared_includes' attribute.
1752ed84df00SBruno Cardoso Lopes     AT_no_undeclared_includes
1753a686e1b0SDouglas Gregor   };
1754afd1b1c9SEugene Zelenko 
1755afd1b1c9SEugene Zelenko } // namespace
1756a686e1b0SDouglas Gregor 
175729729919SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra
175829729919SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH
175929729919SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written
176029729919SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
17615f11e128SBruno Cardoso Lopes void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
17625f11e128SBruno Cardoso Lopes                                              SourceLocation FrameworkLoc) {
176329729919SBruno Cardoso Lopes   auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
17647d29486dSBruno Cardoso Lopes                              const Module *M, SourceRange ReplLoc) {
176529729919SBruno Cardoso Lopes     auto D = Diags.Report(ActiveModule->DefinitionLoc,
176629729919SBruno Cardoso Lopes                           diag::note_mmap_rename_top_level_private_module);
176729729919SBruno Cardoso Lopes     D << BadName << M->Name;
17687d29486dSBruno Cardoso Lopes     D << FixItHint::CreateReplacement(ReplLoc, Canonical);
176929729919SBruno Cardoso Lopes   };
177029729919SBruno Cardoso Lopes 
177129729919SBruno Cardoso Lopes   for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
177229729919SBruno Cardoso Lopes     auto const *M = E->getValue();
177329729919SBruno Cardoso Lopes     if (M->Directory != ActiveModule->Directory)
177429729919SBruno Cardoso Lopes       continue;
177529729919SBruno Cardoso Lopes 
177629729919SBruno Cardoso Lopes     SmallString<128> FullName(ActiveModule->getFullModuleName());
177729729919SBruno Cardoso Lopes     if (!FullName.startswith(M->Name) && !FullName.endswith("Private"))
177829729919SBruno Cardoso Lopes       continue;
17795f11e128SBruno Cardoso Lopes     SmallString<128> FixedPrivModDecl;
178029729919SBruno Cardoso Lopes     SmallString<128> Canonical(M->Name);
178129729919SBruno Cardoso Lopes     Canonical.append("_Private");
178229729919SBruno Cardoso Lopes 
178329729919SBruno Cardoso Lopes     // Foo.Private -> Foo_Private
178429729919SBruno Cardoso Lopes     if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
178529729919SBruno Cardoso Lopes         M->Name == ActiveModule->Parent->Name) {
178629729919SBruno Cardoso Lopes       Diags.Report(ActiveModule->DefinitionLoc,
178729729919SBruno Cardoso Lopes                    diag::warn_mmap_mismatched_private_submodule)
178829729919SBruno Cardoso Lopes           << FullName;
17895f11e128SBruno Cardoso Lopes 
17905f11e128SBruno Cardoso Lopes       SourceLocation FixItInitBegin = CurrModuleDeclLoc;
17915f11e128SBruno Cardoso Lopes       if (FrameworkLoc.isValid())
17925f11e128SBruno Cardoso Lopes         FixItInitBegin = FrameworkLoc;
17935f11e128SBruno Cardoso Lopes       if (ExplicitLoc.isValid())
17945f11e128SBruno Cardoso Lopes         FixItInitBegin = ExplicitLoc;
17955f11e128SBruno Cardoso Lopes 
17965f11e128SBruno Cardoso Lopes       if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
17975f11e128SBruno Cardoso Lopes         FixedPrivModDecl.append("framework ");
17985f11e128SBruno Cardoso Lopes       FixedPrivModDecl.append("module ");
17995f11e128SBruno Cardoso Lopes       FixedPrivModDecl.append(Canonical);
18005f11e128SBruno Cardoso Lopes 
18015f11e128SBruno Cardoso Lopes       GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
18025f11e128SBruno Cardoso Lopes                       SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
180329729919SBruno Cardoso Lopes       continue;
180429729919SBruno Cardoso Lopes     }
180529729919SBruno Cardoso Lopes 
180629729919SBruno Cardoso Lopes     // FooPrivate and whatnots -> Foo_Private
180729729919SBruno Cardoso Lopes     if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
180829729919SBruno Cardoso Lopes         ActiveModule->Name != Canonical) {
180929729919SBruno Cardoso Lopes       Diags.Report(ActiveModule->DefinitionLoc,
181029729919SBruno Cardoso Lopes                    diag::warn_mmap_mismatched_private_module_name)
181129729919SBruno Cardoso Lopes           << ActiveModule->Name;
18127d29486dSBruno Cardoso Lopes       GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
18137d29486dSBruno Cardoso Lopes                       SourceRange(ActiveModule->DefinitionLoc));
181429729919SBruno Cardoso Lopes     }
181529729919SBruno Cardoso Lopes   }
181629729919SBruno Cardoso Lopes }
181729729919SBruno Cardoso Lopes 
18189fc8faf9SAdrian Prantl /// Parse a module declaration.
1819718292f2SDouglas Gregor ///
1820718292f2SDouglas Gregor ///   module-declaration:
182197292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
1822a686e1b0SDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1823a686e1b0SDouglas Gregor ///       { module-member* }
1824a686e1b0SDouglas Gregor ///
1825718292f2SDouglas Gregor ///   module-member:
18261fb5c3a6SDouglas Gregor ///     requires-declaration
1827718292f2SDouglas Gregor ///     header-declaration
1828e7ab3669SDouglas Gregor ///     submodule-declaration
18292b82c2a5SDouglas Gregor ///     export-declaration
1830f0b11de2SDouglas Gregor ///     export-as-declaration
18316ddfca91SDouglas Gregor ///     link-declaration
183273441091SDouglas Gregor ///
183373441091SDouglas Gregor ///   submodule-declaration:
183473441091SDouglas Gregor ///     module-declaration
183573441091SDouglas Gregor ///     inferred-submodule-declaration
1836718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
1837755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
183897292843SDaniel Jasper          Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
183997292843SDaniel Jasper   if (Tok.is(MMToken::ExternKeyword)) {
184097292843SDaniel Jasper     parseExternModuleDecl();
184197292843SDaniel Jasper     return;
184297292843SDaniel Jasper   }
184397292843SDaniel Jasper 
1844f2161a70SDouglas Gregor   // Parse 'explicit' or 'framework' keyword, if present.
1845e7ab3669SDouglas Gregor   SourceLocation ExplicitLoc;
18465f11e128SBruno Cardoso Lopes   SourceLocation FrameworkLoc;
1847718292f2SDouglas Gregor   bool Explicit = false;
1848f2161a70SDouglas Gregor   bool Framework = false;
1849755b2055SDouglas Gregor 
1850f2161a70SDouglas Gregor   // Parse 'explicit' keyword, if present.
1851f2161a70SDouglas Gregor   if (Tok.is(MMToken::ExplicitKeyword)) {
1852e7ab3669SDouglas Gregor     ExplicitLoc = consumeToken();
1853f2161a70SDouglas Gregor     Explicit = true;
1854f2161a70SDouglas Gregor   }
1855f2161a70SDouglas Gregor 
1856f2161a70SDouglas Gregor   // Parse 'framework' keyword, if present.
1857755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
18585f11e128SBruno Cardoso Lopes     FrameworkLoc = consumeToken();
1859755b2055SDouglas Gregor     Framework = true;
1860755b2055SDouglas Gregor   }
1861718292f2SDouglas Gregor 
1862718292f2SDouglas Gregor   // Parse 'module' keyword.
1863718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
1864d6343c99SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1865718292f2SDouglas Gregor     consumeToken();
1866718292f2SDouglas Gregor     HadError = true;
1867718292f2SDouglas Gregor     return;
1868718292f2SDouglas Gregor   }
18699f6020bcSBruno Cardoso Lopes   CurrModuleDeclLoc = consumeToken(); // 'module' keyword
1870718292f2SDouglas Gregor 
187173441091SDouglas Gregor   // If we have a wildcard for the module name, this is an inferred submodule.
187273441091SDouglas Gregor   // Parse it.
187373441091SDouglas Gregor   if (Tok.is(MMToken::Star))
18749194a91dSDouglas Gregor     return parseInferredModuleDecl(Framework, Explicit);
187573441091SDouglas Gregor 
1876718292f2SDouglas Gregor   // Parse the module name.
1877e7ab3669SDouglas Gregor   ModuleId Id;
1878e7ab3669SDouglas Gregor   if (parseModuleId(Id)) {
1879718292f2SDouglas Gregor     HadError = true;
1880718292f2SDouglas Gregor     return;
1881718292f2SDouglas Gregor   }
1882e7ab3669SDouglas Gregor 
1883e7ab3669SDouglas Gregor   if (ActiveModule) {
1884e7ab3669SDouglas Gregor     if (Id.size() > 1) {
1885e7ab3669SDouglas Gregor       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1886e7ab3669SDouglas Gregor         << SourceRange(Id.front().second, Id.back().second);
1887e7ab3669SDouglas Gregor 
1888e7ab3669SDouglas Gregor       HadError = true;
1889e7ab3669SDouglas Gregor       return;
1890e7ab3669SDouglas Gregor     }
1891e7ab3669SDouglas Gregor   } else if (Id.size() == 1 && Explicit) {
1892e7ab3669SDouglas Gregor     // Top-level modules can't be explicit.
1893e7ab3669SDouglas Gregor     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1894e7ab3669SDouglas Gregor     Explicit = false;
1895e7ab3669SDouglas Gregor     ExplicitLoc = SourceLocation();
1896e7ab3669SDouglas Gregor     HadError = true;
1897e7ab3669SDouglas Gregor   }
1898e7ab3669SDouglas Gregor 
1899e7ab3669SDouglas Gregor   Module *PreviousActiveModule = ActiveModule;
1900e7ab3669SDouglas Gregor   if (Id.size() > 1) {
1901e7ab3669SDouglas Gregor     // This module map defines a submodule. Go find the module of which it
1902e7ab3669SDouglas Gregor     // is a submodule.
1903d2d442caSCraig Topper     ActiveModule = nullptr;
19044b8a9e95SBen Langmuir     const Module *TopLevelModule = nullptr;
1905e7ab3669SDouglas Gregor     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1906e7ab3669SDouglas Gregor       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
19074b8a9e95SBen Langmuir         if (I == 0)
19084b8a9e95SBen Langmuir           TopLevelModule = Next;
1909e7ab3669SDouglas Gregor         ActiveModule = Next;
1910e7ab3669SDouglas Gregor         continue;
1911e7ab3669SDouglas Gregor       }
1912e7ab3669SDouglas Gregor 
19138839e278SVolodymyr Sapsai       Diags.Report(Id[I].second, diag::err_mmap_missing_parent_module)
19148839e278SVolodymyr Sapsai           << Id[I].first << (ActiveModule != nullptr)
19158839e278SVolodymyr Sapsai           << (ActiveModule
19168839e278SVolodymyr Sapsai                   ? ActiveModule->getTopLevelModule()->getFullModuleName()
19178839e278SVolodymyr Sapsai                   : "");
1918e7ab3669SDouglas Gregor       HadError = true;
1919e7ab3669SDouglas Gregor     }
19204b8a9e95SBen Langmuir 
19218839e278SVolodymyr Sapsai     if (TopLevelModule &&
19228839e278SVolodymyr Sapsai         ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
19234b8a9e95SBen Langmuir       assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
19244b8a9e95SBen Langmuir              "submodule defined in same file as 'module *' that allowed its "
19254b8a9e95SBen Langmuir              "top-level module");
19264b8a9e95SBen Langmuir       Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
19274b8a9e95SBen Langmuir     }
1928e7ab3669SDouglas Gregor   }
1929e7ab3669SDouglas Gregor 
1930e7ab3669SDouglas Gregor   StringRef ModuleName = Id.back().first;
1931e7ab3669SDouglas Gregor   SourceLocation ModuleNameLoc = Id.back().second;
1932718292f2SDouglas Gregor 
1933a686e1b0SDouglas Gregor   // Parse the optional attribute list.
19344442605fSBill Wendling   Attributes Attrs;
19355d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
19365d29dee0SDavide Italiano     return;
19375d29dee0SDavide Italiano 
1938718292f2SDouglas Gregor   // Parse the opening brace.
1939718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
1940718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1941718292f2SDouglas Gregor       << ModuleName;
1942718292f2SDouglas Gregor     HadError = true;
1943718292f2SDouglas Gregor     return;
1944718292f2SDouglas Gregor   }
1945718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
1946718292f2SDouglas Gregor 
1947718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
19488587dfd9SBruno Cardoso Lopes   Module *ShadowingModule = nullptr;
1949eb90e830SDouglas Gregor   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
19504a3751ffSRichard Smith     // We might see a (re)definition of a module that we already have a
19514a3751ffSRichard Smith     // definition for in two cases:
19524a3751ffSRichard Smith     //  - If we loaded one definition from an AST file and we've just found a
19534a3751ffSRichard Smith     //    corresponding definition in a module map file, or
19544a3751ffSRichard Smith     bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
19554a3751ffSRichard Smith     //  - If we're building a (preprocessed) module and we've just loaded the
19564a3751ffSRichard Smith     //    module map file from which it was created.
19574a3751ffSRichard Smith     bool ParsedAsMainInput =
19584a3751ffSRichard Smith         Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
19594a3751ffSRichard Smith         Map.LangOpts.CurrentModule == ModuleName &&
19604a3751ffSRichard Smith         SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
19614a3751ffSRichard Smith             SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
19624a3751ffSRichard Smith     if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
1963fcc54a3bSDouglas Gregor       // Skip the module definition.
1964fcc54a3bSDouglas Gregor       skipUntil(MMToken::RBrace);
1965fcc54a3bSDouglas Gregor       if (Tok.is(MMToken::RBrace))
1966fcc54a3bSDouglas Gregor         consumeToken();
1967fcc54a3bSDouglas Gregor       else {
1968fcc54a3bSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1969fcc54a3bSDouglas Gregor         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1970fcc54a3bSDouglas Gregor         HadError = true;
1971fcc54a3bSDouglas Gregor       }
1972fcc54a3bSDouglas Gregor       return;
1973fcc54a3bSDouglas Gregor     }
1974fcc54a3bSDouglas Gregor 
1975c192d194SBruno Cardoso Lopes     if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
19768587dfd9SBruno Cardoso Lopes       ShadowingModule = Existing;
19778587dfd9SBruno Cardoso Lopes     } else {
19788587dfd9SBruno Cardoso Lopes       // This is not a shawdowed module decl, it is an illegal redefinition.
1979718292f2SDouglas Gregor       Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1980718292f2SDouglas Gregor           << ModuleName;
1981eb90e830SDouglas Gregor       Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1982718292f2SDouglas Gregor 
1983718292f2SDouglas Gregor       // Skip the module definition.
1984718292f2SDouglas Gregor       skipUntil(MMToken::RBrace);
1985718292f2SDouglas Gregor       if (Tok.is(MMToken::RBrace))
1986718292f2SDouglas Gregor         consumeToken();
1987718292f2SDouglas Gregor 
1988718292f2SDouglas Gregor       HadError = true;
1989718292f2SDouglas Gregor       return;
1990718292f2SDouglas Gregor     }
19918587dfd9SBruno Cardoso Lopes   }
1992718292f2SDouglas Gregor 
1993718292f2SDouglas Gregor   // Start defining this module.
19948587dfd9SBruno Cardoso Lopes   if (ShadowingModule) {
19958587dfd9SBruno Cardoso Lopes     ActiveModule =
19968587dfd9SBruno Cardoso Lopes         Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
19978587dfd9SBruno Cardoso Lopes   } else {
1998c192d194SBruno Cardoso Lopes     ActiveModule =
1999c192d194SBruno Cardoso Lopes         Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
20008587dfd9SBruno Cardoso Lopes             .first;
20018587dfd9SBruno Cardoso Lopes   }
20028587dfd9SBruno Cardoso Lopes 
2003eb90e830SDouglas Gregor   ActiveModule->DefinitionLoc = ModuleNameLoc;
2004963c5535SDouglas Gregor   if (Attrs.IsSystem || IsSystem)
2005a686e1b0SDouglas Gregor     ActiveModule->IsSystem = true;
200677944868SRichard Smith   if (Attrs.IsExternC)
200777944868SRichard Smith     ActiveModule->IsExternC = true;
2008ed84df00SBruno Cardoso Lopes   if (Attrs.NoUndeclaredIncludes ||
2009ed84df00SBruno Cardoso Lopes       (!ActiveModule->Parent && ModuleName == "Darwin"))
2010ed84df00SBruno Cardoso Lopes     ActiveModule->NoUndeclaredIncludes = true;
20113c1a41adSRichard Smith   ActiveModule->Directory = Directory;
2012718292f2SDouglas Gregor 
201390b0a1fcSJordan Rose   StringRef MapFileName(ModuleMapFile->getName());
201490b0a1fcSJordan Rose   if (MapFileName.endswith("module.private.modulemap") ||
201590b0a1fcSJordan Rose       MapFileName.endswith("module_private.map")) {
201690b0a1fcSJordan Rose     ActiveModule->ModuleMapIsPrivate = true;
201790b0a1fcSJordan Rose   }
201829729919SBruno Cardoso Lopes 
201929729919SBruno Cardoso Lopes   // Private modules named as FooPrivate, Foo.Private or similar are likely a
202029729919SBruno Cardoso Lopes   // user error; provide warnings, notes and fixits to direct users to use
202129729919SBruno Cardoso Lopes   // Foo_Private instead.
202229729919SBruno Cardoso Lopes   SourceLocation StartLoc =
202329729919SBruno Cardoso Lopes       SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
202429729919SBruno Cardoso Lopes   if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
202529729919SBruno Cardoso Lopes       !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
202629729919SBruno Cardoso Lopes                        StartLoc) &&
202729729919SBruno Cardoso Lopes       !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
202829729919SBruno Cardoso Lopes                        StartLoc) &&
202990b0a1fcSJordan Rose       ActiveModule->ModuleMapIsPrivate)
20305f11e128SBruno Cardoso Lopes     diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
20314d867640SGraydon Hoare 
2032718292f2SDouglas Gregor   bool Done = false;
2033718292f2SDouglas Gregor   do {
2034718292f2SDouglas Gregor     switch (Tok.Kind) {
2035718292f2SDouglas Gregor     case MMToken::EndOfFile:
2036718292f2SDouglas Gregor     case MMToken::RBrace:
2037718292f2SDouglas Gregor       Done = true;
2038718292f2SDouglas Gregor       break;
2039718292f2SDouglas Gregor 
204035b13eceSDouglas Gregor     case MMToken::ConfigMacros:
204135b13eceSDouglas Gregor       parseConfigMacros();
204235b13eceSDouglas Gregor       break;
204335b13eceSDouglas Gregor 
2044fb912657SDouglas Gregor     case MMToken::Conflict:
2045fb912657SDouglas Gregor       parseConflict();
2046fb912657SDouglas Gregor       break;
2047fb912657SDouglas Gregor 
2048718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
204997292843SDaniel Jasper     case MMToken::ExternKeyword:
2050f2161a70SDouglas Gregor     case MMToken::FrameworkKeyword:
2051718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
2052718292f2SDouglas Gregor       parseModuleDecl();
2053718292f2SDouglas Gregor       break;
2054718292f2SDouglas Gregor 
20552b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
20562b82c2a5SDouglas Gregor       parseExportDecl();
20572b82c2a5SDouglas Gregor       break;
20582b82c2a5SDouglas Gregor 
2059f0b11de2SDouglas Gregor     case MMToken::ExportAsKeyword:
2060f0b11de2SDouglas Gregor       parseExportAsDecl();
2061f0b11de2SDouglas Gregor       break;
2062f0b11de2SDouglas Gregor 
2063ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
2064ba7f2f71SDaniel Jasper       parseUseDecl();
2065ba7f2f71SDaniel Jasper       break;
2066ba7f2f71SDaniel Jasper 
20671fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
20681fb5c3a6SDouglas Gregor       parseRequiresDecl();
20691fb5c3a6SDouglas Gregor       break;
20701fb5c3a6SDouglas Gregor 
2071202210b3SRichard Smith     case MMToken::TextualKeyword:
2072202210b3SRichard Smith       parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
2073306d8920SRichard Smith       break;
2074306d8920SRichard Smith 
2075524e33e1SDouglas Gregor     case MMToken::UmbrellaKeyword: {
2076524e33e1SDouglas Gregor       SourceLocation UmbrellaLoc = consumeToken();
2077524e33e1SDouglas Gregor       if (Tok.is(MMToken::HeaderKeyword))
2078b53e5483SLawrence Crowl         parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
2079524e33e1SDouglas Gregor       else
2080524e33e1SDouglas Gregor         parseUmbrellaDirDecl(UmbrellaLoc);
2081718292f2SDouglas Gregor       break;
2082524e33e1SDouglas Gregor     }
2083718292f2SDouglas Gregor 
2084202210b3SRichard Smith     case MMToken::ExcludeKeyword:
2085202210b3SRichard Smith       parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
208659527666SDouglas Gregor       break;
208759527666SDouglas Gregor 
2088202210b3SRichard Smith     case MMToken::PrivateKeyword:
2089202210b3SRichard Smith       parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
2090b53e5483SLawrence Crowl       break;
2091b53e5483SLawrence Crowl 
2092322f633cSDouglas Gregor     case MMToken::HeaderKeyword:
2093202210b3SRichard Smith       parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
2094718292f2SDouglas Gregor       break;
2095718292f2SDouglas Gregor 
20966ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
20976ddfca91SDouglas Gregor       parseLinkDecl();
20986ddfca91SDouglas Gregor       break;
20996ddfca91SDouglas Gregor 
2100718292f2SDouglas Gregor     default:
2101718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
2102718292f2SDouglas Gregor       consumeToken();
2103718292f2SDouglas Gregor       break;
2104718292f2SDouglas Gregor     }
2105718292f2SDouglas Gregor   } while (!Done);
2106718292f2SDouglas Gregor 
2107718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
2108718292f2SDouglas Gregor     consumeToken();
2109718292f2SDouglas Gregor   else {
2110718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2111718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2112718292f2SDouglas Gregor     HadError = true;
2113718292f2SDouglas Gregor   }
2114718292f2SDouglas Gregor 
211511dfe6feSDouglas Gregor   // If the active module is a top-level framework, and there are no link
211611dfe6feSDouglas Gregor   // libraries, automatically link against the framework.
211711dfe6feSDouglas Gregor   if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
211811dfe6feSDouglas Gregor       ActiveModule->LinkLibraries.empty()) {
211911dfe6feSDouglas Gregor     inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
212011dfe6feSDouglas Gregor   }
212111dfe6feSDouglas Gregor 
2122ec8c9752SBen Langmuir   // If the module meets all requirements but is still unavailable, mark the
2123ec8c9752SBen Langmuir   // whole tree as unavailable to prevent it from building.
2124fc76b4adSRichard Smith   if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
2125ec8c9752SBen Langmuir       ActiveModule->Parent) {
2126fc76b4adSRichard Smith     ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false);
2127ec8c9752SBen Langmuir     ActiveModule->getTopLevelModule()->MissingHeaders.append(
2128ec8c9752SBen Langmuir       ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
2129ec8c9752SBen Langmuir   }
2130ec8c9752SBen Langmuir 
2131e7ab3669SDouglas Gregor   // We're done parsing this module. Pop back to the previous module.
2132e7ab3669SDouglas Gregor   ActiveModule = PreviousActiveModule;
2133718292f2SDouglas Gregor }
2134718292f2SDouglas Gregor 
21359fc8faf9SAdrian Prantl /// Parse an extern module declaration.
213697292843SDaniel Jasper ///
213797292843SDaniel Jasper ///   extern module-declaration:
213897292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
213997292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() {
214097292843SDaniel Jasper   assert(Tok.is(MMToken::ExternKeyword));
2141ae6df27eSRichard Smith   SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
214297292843SDaniel Jasper 
214397292843SDaniel Jasper   // Parse 'module' keyword.
214497292843SDaniel Jasper   if (!Tok.is(MMToken::ModuleKeyword)) {
214597292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
214697292843SDaniel Jasper     consumeToken();
214797292843SDaniel Jasper     HadError = true;
214897292843SDaniel Jasper     return;
214997292843SDaniel Jasper   }
215097292843SDaniel Jasper   consumeToken(); // 'module' keyword
215197292843SDaniel Jasper 
215297292843SDaniel Jasper   // Parse the module name.
215397292843SDaniel Jasper   ModuleId Id;
215497292843SDaniel Jasper   if (parseModuleId(Id)) {
215597292843SDaniel Jasper     HadError = true;
215697292843SDaniel Jasper     return;
215797292843SDaniel Jasper   }
215897292843SDaniel Jasper 
215997292843SDaniel Jasper   // Parse the referenced module map file name.
216097292843SDaniel Jasper   if (!Tok.is(MMToken::StringLiteral)) {
216197292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
216297292843SDaniel Jasper     HadError = true;
216397292843SDaniel Jasper     return;
216497292843SDaniel Jasper   }
2165adcd0268SBenjamin Kramer   std::string FileName = std::string(Tok.getString());
216697292843SDaniel Jasper   consumeToken(); // filename
216797292843SDaniel Jasper 
216897292843SDaniel Jasper   StringRef FileNameRef = FileName;
216997292843SDaniel Jasper   SmallString<128> ModuleMapFileName;
217097292843SDaniel Jasper   if (llvm::sys::path::is_relative(FileNameRef)) {
217197292843SDaniel Jasper     ModuleMapFileName += Directory->getName();
217297292843SDaniel Jasper     llvm::sys::path::append(ModuleMapFileName, FileName);
217392e1b62dSYaron Keren     FileNameRef = ModuleMapFileName;
217497292843SDaniel Jasper   }
21757799ef71SNico Weber   if (auto File = SourceMgr.getFileManager().getFile(FileNameRef))
21769acb99e3SRichard Smith     Map.parseModuleMapFile(
21778d323d15SHarlan Haskins         *File, /*IsSystem=*/false,
21789acb99e3SRichard Smith         Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
21799acb99e3SRichard Smith             ? Directory
21807799ef71SNico Weber             : (*File)->getDir(),
2181c192d194SBruno Cardoso Lopes         FileID(), nullptr, ExternLoc);
218297292843SDaniel Jasper }
218397292843SDaniel Jasper 
21847ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M.
21857ff29148SBen Langmuir ///
21867ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system
21877ff29148SBen Langmuir /// module map files:
21887ff29148SBen Langmuir ///
21897ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which
21907ff29148SBen Langmuir ///    should really be mapped to 'textual' now that we have this feature.  We
21917ff29148SBen Langmuir ///    drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
21927ff29148SBen Langmuir ///    true.  Later, this bit will be used to map all the headers inside this
21937ff29148SBen Langmuir ///    module to 'textual'.
21947ff29148SBen Langmuir ///
21957ff29148SBen Langmuir ///    This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
21967ff29148SBen Langmuir ///
21977ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc.  This requirement
21987ff29148SBen Langmuir ///    was never correct and causes issues now that we check it, so drop it.
21997ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature,
22007ff29148SBen Langmuir                                  bool &IsRequiresExcludedHack) {
22018013e81dSBenjamin Kramer   if (Feature == "excluded" &&
22028013e81dSBenjamin Kramer       (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
22038013e81dSBenjamin Kramer        M->fullModuleNameIs({"Tcl", "Private"}))) {
22047ff29148SBen Langmuir     IsRequiresExcludedHack = true;
22057ff29148SBen Langmuir     return false;
22068013e81dSBenjamin Kramer   } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
22077ff29148SBen Langmuir     return false;
22087ff29148SBen Langmuir   }
22097ff29148SBen Langmuir 
22107ff29148SBen Langmuir   return true;
22117ff29148SBen Langmuir }
22127ff29148SBen Langmuir 
22139fc8faf9SAdrian Prantl /// Parse a requires declaration.
22141fb5c3a6SDouglas Gregor ///
22151fb5c3a6SDouglas Gregor ///   requires-declaration:
22161fb5c3a6SDouglas Gregor ///     'requires' feature-list
22171fb5c3a6SDouglas Gregor ///
22181fb5c3a6SDouglas Gregor ///   feature-list:
2219a3feee2aSRichard Smith ///     feature ',' feature-list
2220a3feee2aSRichard Smith ///     feature
2221a3feee2aSRichard Smith ///
2222a3feee2aSRichard Smith ///   feature:
2223a3feee2aSRichard Smith ///     '!'[opt] identifier
22241fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() {
22251fb5c3a6SDouglas Gregor   assert(Tok.is(MMToken::RequiresKeyword));
22261fb5c3a6SDouglas Gregor 
22271fb5c3a6SDouglas Gregor   // Parse 'requires' keyword.
22281fb5c3a6SDouglas Gregor   consumeToken();
22291fb5c3a6SDouglas Gregor 
22301fb5c3a6SDouglas Gregor   // Parse the feature-list.
22311fb5c3a6SDouglas Gregor   do {
2232a3feee2aSRichard Smith     bool RequiredState = true;
2233a3feee2aSRichard Smith     if (Tok.is(MMToken::Exclaim)) {
2234a3feee2aSRichard Smith       RequiredState = false;
2235a3feee2aSRichard Smith       consumeToken();
2236a3feee2aSRichard Smith     }
2237a3feee2aSRichard Smith 
22381fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
22391fb5c3a6SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
22401fb5c3a6SDouglas Gregor       HadError = true;
22411fb5c3a6SDouglas Gregor       return;
22421fb5c3a6SDouglas Gregor     }
22431fb5c3a6SDouglas Gregor 
22441fb5c3a6SDouglas Gregor     // Consume the feature name.
2245adcd0268SBenjamin Kramer     std::string Feature = std::string(Tok.getString());
22461fb5c3a6SDouglas Gregor     consumeToken();
22471fb5c3a6SDouglas Gregor 
22487ff29148SBen Langmuir     bool IsRequiresExcludedHack = false;
22497ff29148SBen Langmuir     bool ShouldAddRequirement =
22507ff29148SBen Langmuir         shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
22517ff29148SBen Langmuir 
22527ff29148SBen Langmuir     if (IsRequiresExcludedHack)
22537ff29148SBen Langmuir       UsesRequiresExcludedHack.insert(ActiveModule);
22547ff29148SBen Langmuir 
22557ff29148SBen Langmuir     if (ShouldAddRequirement) {
22561fb5c3a6SDouglas Gregor       // Add this feature.
22577ff29148SBen Langmuir       ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
22587ff29148SBen Langmuir                                    *Map.Target);
22597ff29148SBen Langmuir     }
22601fb5c3a6SDouglas Gregor 
22611fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Comma))
22621fb5c3a6SDouglas Gregor       break;
22631fb5c3a6SDouglas Gregor 
22641fb5c3a6SDouglas Gregor     // Consume the comma.
22651fb5c3a6SDouglas Gregor     consumeToken();
22661fb5c3a6SDouglas Gregor   } while (true);
22671fb5c3a6SDouglas Gregor }
22681fb5c3a6SDouglas Gregor 
22699fc8faf9SAdrian Prantl /// Parse a header declaration.
2270718292f2SDouglas Gregor ///
2271718292f2SDouglas Gregor ///   header-declaration:
2272306d8920SRichard Smith ///     'textual'[opt] 'header' string-literal
2273202210b3SRichard Smith ///     'private' 'textual'[opt] 'header' string-literal
2274202210b3SRichard Smith ///     'exclude' 'header' string-literal
2275202210b3SRichard Smith ///     'umbrella' 'header' string-literal
2276306d8920SRichard Smith ///
2277306d8920SRichard Smith /// FIXME: Support 'private textual header'.
2278b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
2279b53e5483SLawrence Crowl                                       SourceLocation LeadingLoc) {
2280202210b3SRichard Smith   // We've already consumed the first token.
2281202210b3SRichard Smith   ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
2282202210b3SRichard Smith   if (LeadingToken == MMToken::PrivateKeyword) {
2283202210b3SRichard Smith     Role = ModuleMap::PrivateHeader;
2284202210b3SRichard Smith     // 'private' may optionally be followed by 'textual'.
2285202210b3SRichard Smith     if (Tok.is(MMToken::TextualKeyword)) {
2286202210b3SRichard Smith       LeadingToken = Tok.Kind;
22871871ed3dSBenjamin Kramer       consumeToken();
2288202210b3SRichard Smith     }
2289202210b3SRichard Smith   }
22907ff29148SBen Langmuir 
2291202210b3SRichard Smith   if (LeadingToken == MMToken::TextualKeyword)
2292202210b3SRichard Smith     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
2293202210b3SRichard Smith 
22947ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
22957ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
22967ff29148SBen Langmuir     // Module::UsesRequiresExcludedHack).
22977ff29148SBen Langmuir     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
22987ff29148SBen Langmuir   }
22997ff29148SBen Langmuir 
2300202210b3SRichard Smith   if (LeadingToken != MMToken::HeaderKeyword) {
2301202210b3SRichard Smith     if (!Tok.is(MMToken::HeaderKeyword)) {
2302202210b3SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2303202210b3SRichard Smith           << (LeadingToken == MMToken::PrivateKeyword ? "private" :
2304202210b3SRichard Smith               LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
2305202210b3SRichard Smith               LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
2306202210b3SRichard Smith       return;
2307202210b3SRichard Smith     }
2308202210b3SRichard Smith     consumeToken();
2309202210b3SRichard Smith   }
2310718292f2SDouglas Gregor 
2311718292f2SDouglas Gregor   // Parse the header name.
2312718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2313718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2314718292f2SDouglas Gregor       << "header";
2315718292f2SDouglas Gregor     HadError = true;
2316718292f2SDouglas Gregor     return;
2317718292f2SDouglas Gregor   }
23183c1a41adSRichard Smith   Module::UnresolvedHeaderDirective Header;
2319adcd0268SBenjamin Kramer   Header.FileName = std::string(Tok.getString());
23200761a8a0SDaniel Jasper   Header.FileNameLoc = consumeToken();
23211d60987fSRichard Smith   Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
2322040e1266SRichard Smith   Header.Kind =
2323040e1266SRichard Smith       (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded
2324040e1266SRichard Smith                                                : Map.headerRoleToKind(Role));
2325718292f2SDouglas Gregor 
2326524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
23271d60987fSRichard Smith   if (Header.IsUmbrella && ActiveModule->Umbrella) {
23280761a8a0SDaniel Jasper     Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2329524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2330322f633cSDouglas Gregor     HadError = true;
2331322f633cSDouglas Gregor     return;
2332322f633cSDouglas Gregor   }
2333322f633cSDouglas Gregor 
2334040e1266SRichard Smith   // If we were given stat information, parse it so we can skip looking for
2335040e1266SRichard Smith   // the file.
2336040e1266SRichard Smith   if (Tok.is(MMToken::LBrace)) {
2337040e1266SRichard Smith     SourceLocation LBraceLoc = consumeToken();
23383ec6663bSDouglas Gregor 
2339040e1266SRichard Smith     while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
2340040e1266SRichard Smith       enum Attribute { Size, ModTime, Unknown };
2341040e1266SRichard Smith       StringRef Str = Tok.getString();
2342040e1266SRichard Smith       SourceLocation Loc = consumeToken();
2343040e1266SRichard Smith       switch (llvm::StringSwitch<Attribute>(Str)
2344040e1266SRichard Smith                   .Case("size", Size)
2345040e1266SRichard Smith                   .Case("mtime", ModTime)
2346040e1266SRichard Smith                   .Default(Unknown)) {
2347040e1266SRichard Smith       case Size:
2348040e1266SRichard Smith         if (Header.Size)
2349040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2350040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2351040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2352040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2353040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2354040e1266SRichard Smith           break;
2355040e1266SRichard Smith         }
2356040e1266SRichard Smith         Header.Size = Tok.getInteger();
2357040e1266SRichard Smith         consumeToken();
2358040e1266SRichard Smith         break;
2359040e1266SRichard Smith 
2360040e1266SRichard Smith       case ModTime:
2361040e1266SRichard Smith         if (Header.ModTime)
2362040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2363040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2364040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2365040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2366040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2367040e1266SRichard Smith           break;
2368040e1266SRichard Smith         }
2369040e1266SRichard Smith         Header.ModTime = Tok.getInteger();
2370040e1266SRichard Smith         consumeToken();
2371040e1266SRichard Smith         break;
2372040e1266SRichard Smith 
2373040e1266SRichard Smith       case Unknown:
2374040e1266SRichard Smith         Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
2375040e1266SRichard Smith         skipUntil(MMToken::RBrace);
2376040e1266SRichard Smith         break;
2377040e1266SRichard Smith       }
23783ec6663bSDouglas Gregor     }
23795257fc63SDouglas Gregor 
2380040e1266SRichard Smith     if (Tok.is(MMToken::RBrace))
2381040e1266SRichard Smith       consumeToken();
2382040e1266SRichard Smith     else {
2383040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2384040e1266SRichard Smith       Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2385322f633cSDouglas Gregor       HadError = true;
2386322f633cSDouglas Gregor     }
23870101b540SHans Wennborg   }
238825d50758SRichard Smith 
23899f6020bcSBruno Cardoso Lopes   bool NeedsFramework = false;
23909f6020bcSBruno Cardoso Lopes   Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
23919f6020bcSBruno Cardoso Lopes 
23929f6020bcSBruno Cardoso Lopes   if (NeedsFramework && ActiveModule)
23939f6020bcSBruno Cardoso Lopes     Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
23949f6020bcSBruno Cardoso Lopes       << ActiveModule->getFullModuleName()
23959f6020bcSBruno Cardoso Lopes       << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
2396718292f2SDouglas Gregor }
2397718292f2SDouglas Gregor 
239841f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A,
239941f81994SBen Langmuir                                 const Module::Header *B) {
240041f81994SBen Langmuir   return A->NameAsWritten.compare(B->NameAsWritten);
240141f81994SBen Langmuir }
240241f81994SBen Langmuir 
24039fc8faf9SAdrian Prantl /// Parse an umbrella directory declaration.
2404524e33e1SDouglas Gregor ///
2405524e33e1SDouglas Gregor ///   umbrella-dir-declaration:
2406524e33e1SDouglas Gregor ///     umbrella string-literal
2407524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
2408524e33e1SDouglas Gregor   // Parse the directory name.
2409524e33e1SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2410524e33e1SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2411524e33e1SDouglas Gregor       << "umbrella";
2412524e33e1SDouglas Gregor     HadError = true;
2413524e33e1SDouglas Gregor     return;
2414524e33e1SDouglas Gregor   }
2415524e33e1SDouglas Gregor 
2416adcd0268SBenjamin Kramer   std::string DirName = std::string(Tok.getString());
2417d3676d4bSMichael Spencer   std::string DirNameAsWritten = DirName;
2418524e33e1SDouglas Gregor   SourceLocation DirNameLoc = consumeToken();
2419524e33e1SDouglas Gregor 
2420524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
2421524e33e1SDouglas Gregor   if (ActiveModule->Umbrella) {
2422524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
2423524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2424524e33e1SDouglas Gregor     HadError = true;
2425524e33e1SDouglas Gregor     return;
2426524e33e1SDouglas Gregor   }
2427524e33e1SDouglas Gregor 
2428524e33e1SDouglas Gregor   // Look for this file.
242964d8c781SDuncan P. N. Exon Smith   const DirectoryEntry *Dir = nullptr;
24308d323d15SHarlan Haskins   if (llvm::sys::path::is_absolute(DirName)) {
243164d8c781SDuncan P. N. Exon Smith     if (auto D = SourceMgr.getFileManager().getDirectory(DirName))
24328d323d15SHarlan Haskins       Dir = *D;
24338d323d15SHarlan Haskins   } else {
24342c1dd271SDylan Noblesmith     SmallString<128> PathName;
2435524e33e1SDouglas Gregor     PathName = Directory->getName();
2436524e33e1SDouglas Gregor     llvm::sys::path::append(PathName, DirName);
243764d8c781SDuncan P. N. Exon Smith     if (auto D = SourceMgr.getFileManager().getDirectory(PathName))
24388d323d15SHarlan Haskins       Dir = *D;
2439524e33e1SDouglas Gregor   }
2440524e33e1SDouglas Gregor 
2441524e33e1SDouglas Gregor   if (!Dir) {
2442a0320b97SVassil Vassilev     Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
2443524e33e1SDouglas Gregor       << DirName;
2444524e33e1SDouglas Gregor     return;
2445524e33e1SDouglas Gregor   }
2446524e33e1SDouglas Gregor 
24477ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
24487ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
24497ff29148SBen Langmuir     // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
24507ff29148SBen Langmuir     // directory is relatively expensive, in practice this only applies to the
24517ff29148SBen Langmuir     // uncommonly used Tcl module on Darwin platforms.
24527ff29148SBen Langmuir     std::error_code EC;
24537ff29148SBen Langmuir     SmallVector<Module::Header, 6> Headers;
2454fc51490bSJonas Devlieghere     llvm::vfs::FileSystem &FS =
2455db8a7422SDuncan P. N. Exon Smith         SourceMgr.getFileManager().getVirtualFileSystem();
2456fc51490bSJonas Devlieghere     for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
24577ff29148SBen Langmuir          I != E && !EC; I.increment(EC)) {
245864d8c781SDuncan P. N. Exon Smith       if (auto FE = SourceMgr.getFileManager().getFile(I->path())) {
2459d3676d4bSMichael Spencer         Module::Header Header = {"", std::string(I->path()), *FE};
24607ff29148SBen Langmuir         Headers.push_back(std::move(Header));
24617ff29148SBen Langmuir       }
24627ff29148SBen Langmuir     }
24637ff29148SBen Langmuir 
24647ff29148SBen Langmuir     // Sort header paths so that the pcm doesn't depend on iteration order.
246541f81994SBen Langmuir     llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
246641f81994SBen Langmuir 
24677ff29148SBen Langmuir     for (auto &Header : Headers)
24687ff29148SBen Langmuir       Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
24697ff29148SBen Langmuir     return;
24707ff29148SBen Langmuir   }
24717ff29148SBen Langmuir 
247264d8c781SDuncan P. N. Exon Smith   if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
2473524e33e1SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
2474524e33e1SDouglas Gregor       << OwningModule->getFullModuleName();
2475524e33e1SDouglas Gregor     HadError = true;
2476524e33e1SDouglas Gregor     return;
2477524e33e1SDouglas Gregor   }
2478524e33e1SDouglas Gregor 
2479524e33e1SDouglas Gregor   // Record this umbrella directory.
2480d3676d4bSMichael Spencer   Map.setUmbrellaDir(ActiveModule, Dir, DirNameAsWritten, DirName);
2481524e33e1SDouglas Gregor }
2482524e33e1SDouglas Gregor 
24839fc8faf9SAdrian Prantl /// Parse a module export declaration.
24842b82c2a5SDouglas Gregor ///
24852b82c2a5SDouglas Gregor ///   export-declaration:
24862b82c2a5SDouglas Gregor ///     'export' wildcard-module-id
24872b82c2a5SDouglas Gregor ///
24882b82c2a5SDouglas Gregor ///   wildcard-module-id:
24892b82c2a5SDouglas Gregor ///     identifier
24902b82c2a5SDouglas Gregor ///     '*'
24912b82c2a5SDouglas Gregor ///     identifier '.' wildcard-module-id
24922b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() {
24932b82c2a5SDouglas Gregor   assert(Tok.is(MMToken::ExportKeyword));
24942b82c2a5SDouglas Gregor   SourceLocation ExportLoc = consumeToken();
24952b82c2a5SDouglas Gregor 
24962b82c2a5SDouglas Gregor   // Parse the module-id with an optional wildcard at the end.
24972b82c2a5SDouglas Gregor   ModuleId ParsedModuleId;
24982b82c2a5SDouglas Gregor   bool Wildcard = false;
24992b82c2a5SDouglas Gregor   do {
2500306d8920SRichard Smith     // FIXME: Support string-literal module names here.
25012b82c2a5SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
2502adcd0268SBenjamin Kramer       ParsedModuleId.push_back(
2503adcd0268SBenjamin Kramer           std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
25042b82c2a5SDouglas Gregor       consumeToken();
25052b82c2a5SDouglas Gregor 
25062b82c2a5SDouglas Gregor       if (Tok.is(MMToken::Period)) {
25072b82c2a5SDouglas Gregor         consumeToken();
25082b82c2a5SDouglas Gregor         continue;
25092b82c2a5SDouglas Gregor       }
25102b82c2a5SDouglas Gregor 
25112b82c2a5SDouglas Gregor       break;
25122b82c2a5SDouglas Gregor     }
25132b82c2a5SDouglas Gregor 
25142b82c2a5SDouglas Gregor     if(Tok.is(MMToken::Star)) {
25152b82c2a5SDouglas Gregor       Wildcard = true;
2516f5eedd05SDouglas Gregor       consumeToken();
25172b82c2a5SDouglas Gregor       break;
25182b82c2a5SDouglas Gregor     }
25192b82c2a5SDouglas Gregor 
2520ba7f2f71SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
25212b82c2a5SDouglas Gregor     HadError = true;
25222b82c2a5SDouglas Gregor     return;
25232b82c2a5SDouglas Gregor   } while (true);
25242b82c2a5SDouglas Gregor 
25252b82c2a5SDouglas Gregor   Module::UnresolvedExportDecl Unresolved = {
25262b82c2a5SDouglas Gregor     ExportLoc, ParsedModuleId, Wildcard
25272b82c2a5SDouglas Gregor   };
25282b82c2a5SDouglas Gregor   ActiveModule->UnresolvedExports.push_back(Unresolved);
25292b82c2a5SDouglas Gregor }
25302b82c2a5SDouglas Gregor 
25319fc8faf9SAdrian Prantl /// Parse a module export_as declaration.
2532f0b11de2SDouglas Gregor ///
2533f0b11de2SDouglas Gregor ///   export-as-declaration:
2534f0b11de2SDouglas Gregor ///     'export_as' identifier
2535f0b11de2SDouglas Gregor void ModuleMapParser::parseExportAsDecl() {
2536f0b11de2SDouglas Gregor   assert(Tok.is(MMToken::ExportAsKeyword));
2537f0b11de2SDouglas Gregor   consumeToken();
2538f0b11de2SDouglas Gregor 
2539f0b11de2SDouglas Gregor   if (!Tok.is(MMToken::Identifier)) {
2540f0b11de2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
2541f0b11de2SDouglas Gregor     HadError = true;
2542f0b11de2SDouglas Gregor     return;
2543f0b11de2SDouglas Gregor   }
2544f0b11de2SDouglas Gregor 
2545f0b11de2SDouglas Gregor   if (ActiveModule->Parent) {
2546f0b11de2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
2547f0b11de2SDouglas Gregor     consumeToken();
2548f0b11de2SDouglas Gregor     return;
2549f0b11de2SDouglas Gregor   }
2550f0b11de2SDouglas Gregor 
2551f0b11de2SDouglas Gregor   if (!ActiveModule->ExportAsModule.empty()) {
2552f0b11de2SDouglas Gregor     if (ActiveModule->ExportAsModule == Tok.getString()) {
2553f0b11de2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
2554f0b11de2SDouglas Gregor         << ActiveModule->Name << Tok.getString();
2555f0b11de2SDouglas Gregor     } else {
2556f0b11de2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
2557f0b11de2SDouglas Gregor         << ActiveModule->Name << ActiveModule->ExportAsModule
2558f0b11de2SDouglas Gregor         << Tok.getString();
2559f0b11de2SDouglas Gregor     }
2560f0b11de2SDouglas Gregor   }
2561f0b11de2SDouglas Gregor 
2562adcd0268SBenjamin Kramer   ActiveModule->ExportAsModule = std::string(Tok.getString());
2563a3b5f71eSBruno Cardoso Lopes   Map.addLinkAsDependency(ActiveModule);
2564a3b5f71eSBruno Cardoso Lopes 
2565f0b11de2SDouglas Gregor   consumeToken();
2566f0b11de2SDouglas Gregor }
2567f0b11de2SDouglas Gregor 
25689fc8faf9SAdrian Prantl /// Parse a module use declaration.
2569ba7f2f71SDaniel Jasper ///
25708f4d3ff1SRichard Smith ///   use-declaration:
25718f4d3ff1SRichard Smith ///     'use' wildcard-module-id
2572ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() {
2573ba7f2f71SDaniel Jasper   assert(Tok.is(MMToken::UseKeyword));
25748f4d3ff1SRichard Smith   auto KWLoc = consumeToken();
2575ba7f2f71SDaniel Jasper   // Parse the module-id.
2576ba7f2f71SDaniel Jasper   ModuleId ParsedModuleId;
25773cd34c76SDaniel Jasper   parseModuleId(ParsedModuleId);
2578ba7f2f71SDaniel Jasper 
25798f4d3ff1SRichard Smith   if (ActiveModule->Parent)
25808f4d3ff1SRichard Smith     Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
25818f4d3ff1SRichard Smith   else
2582ba7f2f71SDaniel Jasper     ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
2583ba7f2f71SDaniel Jasper }
2584ba7f2f71SDaniel Jasper 
25859fc8faf9SAdrian Prantl /// Parse a link declaration.
25866ddfca91SDouglas Gregor ///
25876ddfca91SDouglas Gregor ///   module-declaration:
25886ddfca91SDouglas Gregor ///     'link' 'framework'[opt] string-literal
25896ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() {
25906ddfca91SDouglas Gregor   assert(Tok.is(MMToken::LinkKeyword));
25916ddfca91SDouglas Gregor   SourceLocation LinkLoc = consumeToken();
25926ddfca91SDouglas Gregor 
25936ddfca91SDouglas Gregor   // Parse the optional 'framework' keyword.
25946ddfca91SDouglas Gregor   bool IsFramework = false;
25956ddfca91SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
25966ddfca91SDouglas Gregor     consumeToken();
25976ddfca91SDouglas Gregor     IsFramework = true;
25986ddfca91SDouglas Gregor   }
25996ddfca91SDouglas Gregor 
26006ddfca91SDouglas Gregor   // Parse the library name
26016ddfca91SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
26026ddfca91SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
26036ddfca91SDouglas Gregor       << IsFramework << SourceRange(LinkLoc);
26046ddfca91SDouglas Gregor     HadError = true;
26056ddfca91SDouglas Gregor     return;
26066ddfca91SDouglas Gregor   }
26076ddfca91SDouglas Gregor 
2608adcd0268SBenjamin Kramer   std::string LibraryName = std::string(Tok.getString());
26096ddfca91SDouglas Gregor   consumeToken();
26106ddfca91SDouglas Gregor   ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
26116ddfca91SDouglas Gregor                                                             IsFramework));
26126ddfca91SDouglas Gregor }
26136ddfca91SDouglas Gregor 
26149fc8faf9SAdrian Prantl /// Parse a configuration macro declaration.
261535b13eceSDouglas Gregor ///
261635b13eceSDouglas Gregor ///   module-declaration:
261735b13eceSDouglas Gregor ///     'config_macros' attributes[opt] config-macro-list?
261835b13eceSDouglas Gregor ///
261935b13eceSDouglas Gregor ///   config-macro-list:
262035b13eceSDouglas Gregor ///     identifier (',' identifier)?
262135b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() {
262235b13eceSDouglas Gregor   assert(Tok.is(MMToken::ConfigMacros));
262335b13eceSDouglas Gregor   SourceLocation ConfigMacrosLoc = consumeToken();
262435b13eceSDouglas Gregor 
262535b13eceSDouglas Gregor   // Only top-level modules can have configuration macros.
262635b13eceSDouglas Gregor   if (ActiveModule->Parent) {
262735b13eceSDouglas Gregor     Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
262835b13eceSDouglas Gregor   }
262935b13eceSDouglas Gregor 
263035b13eceSDouglas Gregor   // Parse the optional attributes.
263135b13eceSDouglas Gregor   Attributes Attrs;
26325d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
26335d29dee0SDavide Italiano     return;
26345d29dee0SDavide Italiano 
263535b13eceSDouglas Gregor   if (Attrs.IsExhaustive && !ActiveModule->Parent) {
263635b13eceSDouglas Gregor     ActiveModule->ConfigMacrosExhaustive = true;
263735b13eceSDouglas Gregor   }
263835b13eceSDouglas Gregor 
263935b13eceSDouglas Gregor   // If we don't have an identifier, we're done.
2640306d8920SRichard Smith   // FIXME: Support macros with the same name as a keyword here.
264135b13eceSDouglas Gregor   if (!Tok.is(MMToken::Identifier))
264235b13eceSDouglas Gregor     return;
264335b13eceSDouglas Gregor 
264435b13eceSDouglas Gregor   // Consume the first identifier.
264535b13eceSDouglas Gregor   if (!ActiveModule->Parent) {
264635b13eceSDouglas Gregor     ActiveModule->ConfigMacros.push_back(Tok.getString().str());
264735b13eceSDouglas Gregor   }
264835b13eceSDouglas Gregor   consumeToken();
264935b13eceSDouglas Gregor 
265035b13eceSDouglas Gregor   do {
265135b13eceSDouglas Gregor     // If there's a comma, consume it.
265235b13eceSDouglas Gregor     if (!Tok.is(MMToken::Comma))
265335b13eceSDouglas Gregor       break;
265435b13eceSDouglas Gregor     consumeToken();
265535b13eceSDouglas Gregor 
265635b13eceSDouglas Gregor     // We expect to see a macro name here.
2657306d8920SRichard Smith     // FIXME: Support macros with the same name as a keyword here.
265835b13eceSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
265935b13eceSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
266035b13eceSDouglas Gregor       break;
266135b13eceSDouglas Gregor     }
266235b13eceSDouglas Gregor 
266335b13eceSDouglas Gregor     // Consume the macro name.
266435b13eceSDouglas Gregor     if (!ActiveModule->Parent) {
266535b13eceSDouglas Gregor       ActiveModule->ConfigMacros.push_back(Tok.getString().str());
266635b13eceSDouglas Gregor     }
266735b13eceSDouglas Gregor     consumeToken();
266835b13eceSDouglas Gregor   } while (true);
266935b13eceSDouglas Gregor }
267035b13eceSDouglas Gregor 
26719fc8faf9SAdrian Prantl /// Format a module-id into a string.
2672fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) {
2673fb912657SDouglas Gregor   std::string result;
2674fb912657SDouglas Gregor   {
2675fb912657SDouglas Gregor     llvm::raw_string_ostream OS(result);
2676fb912657SDouglas Gregor 
2677fb912657SDouglas Gregor     for (unsigned I = 0, N = Id.size(); I != N; ++I) {
2678fb912657SDouglas Gregor       if (I)
2679fb912657SDouglas Gregor         OS << ".";
2680fb912657SDouglas Gregor       OS << Id[I].first;
2681fb912657SDouglas Gregor     }
2682fb912657SDouglas Gregor   }
2683fb912657SDouglas Gregor 
2684fb912657SDouglas Gregor   return result;
2685fb912657SDouglas Gregor }
2686fb912657SDouglas Gregor 
26879fc8faf9SAdrian Prantl /// Parse a conflict declaration.
2688fb912657SDouglas Gregor ///
2689fb912657SDouglas Gregor ///   module-declaration:
2690fb912657SDouglas Gregor ///     'conflict' module-id ',' string-literal
2691fb912657SDouglas Gregor void ModuleMapParser::parseConflict() {
2692fb912657SDouglas Gregor   assert(Tok.is(MMToken::Conflict));
2693fb912657SDouglas Gregor   SourceLocation ConflictLoc = consumeToken();
2694fb912657SDouglas Gregor   Module::UnresolvedConflict Conflict;
2695fb912657SDouglas Gregor 
2696fb912657SDouglas Gregor   // Parse the module-id.
2697fb912657SDouglas Gregor   if (parseModuleId(Conflict.Id))
2698fb912657SDouglas Gregor     return;
2699fb912657SDouglas Gregor 
2700fb912657SDouglas Gregor   // Parse the ','.
2701fb912657SDouglas Gregor   if (!Tok.is(MMToken::Comma)) {
2702fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
2703fb912657SDouglas Gregor       << SourceRange(ConflictLoc);
2704fb912657SDouglas Gregor     return;
2705fb912657SDouglas Gregor   }
2706fb912657SDouglas Gregor   consumeToken();
2707fb912657SDouglas Gregor 
2708fb912657SDouglas Gregor   // Parse the message.
2709fb912657SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2710fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
2711fb912657SDouglas Gregor       << formatModuleId(Conflict.Id);
2712fb912657SDouglas Gregor     return;
2713fb912657SDouglas Gregor   }
2714fb912657SDouglas Gregor   Conflict.Message = Tok.getString().str();
2715fb912657SDouglas Gregor   consumeToken();
2716fb912657SDouglas Gregor 
2717fb912657SDouglas Gregor   // Add this unresolved conflict.
2718fb912657SDouglas Gregor   ActiveModule->UnresolvedConflicts.push_back(Conflict);
2719fb912657SDouglas Gregor }
2720fb912657SDouglas Gregor 
27219fc8faf9SAdrian Prantl /// Parse an inferred module declaration (wildcard modules).
27229194a91dSDouglas Gregor ///
27239194a91dSDouglas Gregor ///   module-declaration:
27249194a91dSDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
27259194a91dSDouglas Gregor ///       { inferred-module-member* }
27269194a91dSDouglas Gregor ///
27279194a91dSDouglas Gregor ///   inferred-module-member:
27289194a91dSDouglas Gregor ///     'export' '*'
27299194a91dSDouglas Gregor ///     'exclude' identifier
27309194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
273173441091SDouglas Gregor   assert(Tok.is(MMToken::Star));
273273441091SDouglas Gregor   SourceLocation StarLoc = consumeToken();
273373441091SDouglas Gregor   bool Failed = false;
273473441091SDouglas Gregor 
273573441091SDouglas Gregor   // Inferred modules must be submodules.
27369194a91dSDouglas Gregor   if (!ActiveModule && !Framework) {
273773441091SDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
273873441091SDouglas Gregor     Failed = true;
273973441091SDouglas Gregor   }
274073441091SDouglas Gregor 
27419194a91dSDouglas Gregor   if (ActiveModule) {
2742524e33e1SDouglas Gregor     // Inferred modules must have umbrella directories.
27434898cde4SBen Langmuir     if (!Failed && ActiveModule->IsAvailable &&
27444898cde4SBen Langmuir         !ActiveModule->getUmbrellaDir()) {
274573441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
274673441091SDouglas Gregor       Failed = true;
274773441091SDouglas Gregor     }
274873441091SDouglas Gregor 
274973441091SDouglas Gregor     // Check for redefinition of an inferred module.
2750dd005f69SDouglas Gregor     if (!Failed && ActiveModule->InferSubmodules) {
275173441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2752dd005f69SDouglas Gregor       if (ActiveModule->InferredSubmoduleLoc.isValid())
2753dd005f69SDouglas Gregor         Diags.Report(ActiveModule->InferredSubmoduleLoc,
275473441091SDouglas Gregor                      diag::note_mmap_prev_definition);
275573441091SDouglas Gregor       Failed = true;
275673441091SDouglas Gregor     }
275773441091SDouglas Gregor 
27589194a91dSDouglas Gregor     // Check for the 'framework' keyword, which is not permitted here.
27599194a91dSDouglas Gregor     if (Framework) {
27609194a91dSDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
27619194a91dSDouglas Gregor       Framework = false;
27629194a91dSDouglas Gregor     }
27639194a91dSDouglas Gregor   } else if (Explicit) {
27649194a91dSDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
27659194a91dSDouglas Gregor     Explicit = false;
27669194a91dSDouglas Gregor   }
27679194a91dSDouglas Gregor 
276873441091SDouglas Gregor   // If there were any problems with this inferred submodule, skip its body.
276973441091SDouglas Gregor   if (Failed) {
277073441091SDouglas Gregor     if (Tok.is(MMToken::LBrace)) {
277173441091SDouglas Gregor       consumeToken();
277273441091SDouglas Gregor       skipUntil(MMToken::RBrace);
277373441091SDouglas Gregor       if (Tok.is(MMToken::RBrace))
277473441091SDouglas Gregor         consumeToken();
277573441091SDouglas Gregor     }
277673441091SDouglas Gregor     HadError = true;
277773441091SDouglas Gregor     return;
277873441091SDouglas Gregor   }
277973441091SDouglas Gregor 
27809194a91dSDouglas Gregor   // Parse optional attributes.
27814442605fSBill Wendling   Attributes Attrs;
27825d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
27835d29dee0SDavide Italiano     return;
27849194a91dSDouglas Gregor 
27859194a91dSDouglas Gregor   if (ActiveModule) {
278673441091SDouglas Gregor     // Note that we have an inferred submodule.
2787dd005f69SDouglas Gregor     ActiveModule->InferSubmodules = true;
2788dd005f69SDouglas Gregor     ActiveModule->InferredSubmoduleLoc = StarLoc;
2789dd005f69SDouglas Gregor     ActiveModule->InferExplicitSubmodules = Explicit;
27909194a91dSDouglas Gregor   } else {
27919194a91dSDouglas Gregor     // We'll be inferring framework modules for this directory.
27929194a91dSDouglas Gregor     Map.InferredDirectories[Directory].InferModules = true;
2793c1d88ea5SBen Langmuir     Map.InferredDirectories[Directory].Attrs = Attrs;
2794beee15e7SBen Langmuir     Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
2795131daca0SRichard Smith     // FIXME: Handle the 'framework' keyword.
27969194a91dSDouglas Gregor   }
279773441091SDouglas Gregor 
279873441091SDouglas Gregor   // Parse the opening brace.
279973441091SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
280073441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
280173441091SDouglas Gregor     HadError = true;
280273441091SDouglas Gregor     return;
280373441091SDouglas Gregor   }
280473441091SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
280573441091SDouglas Gregor 
280673441091SDouglas Gregor   // Parse the body of the inferred submodule.
280773441091SDouglas Gregor   bool Done = false;
280873441091SDouglas Gregor   do {
280973441091SDouglas Gregor     switch (Tok.Kind) {
281073441091SDouglas Gregor     case MMToken::EndOfFile:
281173441091SDouglas Gregor     case MMToken::RBrace:
281273441091SDouglas Gregor       Done = true;
281373441091SDouglas Gregor       break;
281473441091SDouglas Gregor 
2815afd1b1c9SEugene Zelenko     case MMToken::ExcludeKeyword:
28169194a91dSDouglas Gregor       if (ActiveModule) {
28179194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2818d2d442caSCraig Topper           << (ActiveModule != nullptr);
28199194a91dSDouglas Gregor         consumeToken();
28209194a91dSDouglas Gregor         break;
28219194a91dSDouglas Gregor       }
28229194a91dSDouglas Gregor 
28239194a91dSDouglas Gregor       consumeToken();
2824306d8920SRichard Smith       // FIXME: Support string-literal module names here.
28259194a91dSDouglas Gregor       if (!Tok.is(MMToken::Identifier)) {
28269194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
28279194a91dSDouglas Gregor         break;
28289194a91dSDouglas Gregor       }
28299194a91dSDouglas Gregor 
2830adcd0268SBenjamin Kramer       Map.InferredDirectories[Directory].ExcludedModules.push_back(
2831adcd0268SBenjamin Kramer           std::string(Tok.getString()));
28329194a91dSDouglas Gregor       consumeToken();
28339194a91dSDouglas Gregor       break;
28349194a91dSDouglas Gregor 
28359194a91dSDouglas Gregor     case MMToken::ExportKeyword:
28369194a91dSDouglas Gregor       if (!ActiveModule) {
28379194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2838d2d442caSCraig Topper           << (ActiveModule != nullptr);
28399194a91dSDouglas Gregor         consumeToken();
28409194a91dSDouglas Gregor         break;
28419194a91dSDouglas Gregor       }
28429194a91dSDouglas Gregor 
284373441091SDouglas Gregor       consumeToken();
284473441091SDouglas Gregor       if (Tok.is(MMToken::Star))
2845dd005f69SDouglas Gregor         ActiveModule->InferExportWildcard = true;
284673441091SDouglas Gregor       else
284773441091SDouglas Gregor         Diags.Report(Tok.getLocation(),
284873441091SDouglas Gregor                      diag::err_mmap_expected_export_wildcard);
284973441091SDouglas Gregor       consumeToken();
285073441091SDouglas Gregor       break;
285173441091SDouglas Gregor 
285273441091SDouglas Gregor     case MMToken::ExplicitKeyword:
285373441091SDouglas Gregor     case MMToken::ModuleKeyword:
285473441091SDouglas Gregor     case MMToken::HeaderKeyword:
2855b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
285673441091SDouglas Gregor     case MMToken::UmbrellaKeyword:
285773441091SDouglas Gregor     default:
28589194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2859d2d442caSCraig Topper           << (ActiveModule != nullptr);
286073441091SDouglas Gregor       consumeToken();
286173441091SDouglas Gregor       break;
286273441091SDouglas Gregor     }
286373441091SDouglas Gregor   } while (!Done);
286473441091SDouglas Gregor 
286573441091SDouglas Gregor   if (Tok.is(MMToken::RBrace))
286673441091SDouglas Gregor     consumeToken();
286773441091SDouglas Gregor   else {
286873441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
286973441091SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
287073441091SDouglas Gregor     HadError = true;
287173441091SDouglas Gregor   }
287273441091SDouglas Gregor }
287373441091SDouglas Gregor 
28749fc8faf9SAdrian Prantl /// Parse optional attributes.
28759194a91dSDouglas Gregor ///
28769194a91dSDouglas Gregor ///   attributes:
28779194a91dSDouglas Gregor ///     attribute attributes
28789194a91dSDouglas Gregor ///     attribute
28799194a91dSDouglas Gregor ///
28809194a91dSDouglas Gregor ///   attribute:
28819194a91dSDouglas Gregor ///     [ identifier ]
28829194a91dSDouglas Gregor ///
28839194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes.
28849194a91dSDouglas Gregor ///
28859194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise.
28864442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
28879194a91dSDouglas Gregor   bool HadError = false;
28889194a91dSDouglas Gregor 
28899194a91dSDouglas Gregor   while (Tok.is(MMToken::LSquare)) {
28909194a91dSDouglas Gregor     // Consume the '['.
28919194a91dSDouglas Gregor     SourceLocation LSquareLoc = consumeToken();
28929194a91dSDouglas Gregor 
28939194a91dSDouglas Gregor     // Check whether we have an attribute name here.
28949194a91dSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
28959194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
28969194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
28979194a91dSDouglas Gregor       if (Tok.is(MMToken::RSquare))
28989194a91dSDouglas Gregor         consumeToken();
28999194a91dSDouglas Gregor       HadError = true;
29009194a91dSDouglas Gregor     }
29019194a91dSDouglas Gregor 
29029194a91dSDouglas Gregor     // Decode the attribute name.
29039194a91dSDouglas Gregor     AttributeKind Attribute
29049194a91dSDouglas Gregor       = llvm::StringSwitch<AttributeKind>(Tok.getString())
290535b13eceSDouglas Gregor           .Case("exhaustive", AT_exhaustive)
290677944868SRichard Smith           .Case("extern_c", AT_extern_c)
2907ed84df00SBruno Cardoso Lopes           .Case("no_undeclared_includes", AT_no_undeclared_includes)
29089194a91dSDouglas Gregor           .Case("system", AT_system)
29099194a91dSDouglas Gregor           .Default(AT_unknown);
29109194a91dSDouglas Gregor     switch (Attribute) {
29119194a91dSDouglas Gregor     case AT_unknown:
29129194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
29139194a91dSDouglas Gregor         << Tok.getString();
29149194a91dSDouglas Gregor       break;
29159194a91dSDouglas Gregor 
29169194a91dSDouglas Gregor     case AT_system:
29179194a91dSDouglas Gregor       Attrs.IsSystem = true;
29189194a91dSDouglas Gregor       break;
291935b13eceSDouglas Gregor 
292077944868SRichard Smith     case AT_extern_c:
292177944868SRichard Smith       Attrs.IsExternC = true;
292277944868SRichard Smith       break;
292377944868SRichard Smith 
292435b13eceSDouglas Gregor     case AT_exhaustive:
292535b13eceSDouglas Gregor       Attrs.IsExhaustive = true;
292635b13eceSDouglas Gregor       break;
2927ed84df00SBruno Cardoso Lopes 
2928ed84df00SBruno Cardoso Lopes     case AT_no_undeclared_includes:
2929ed84df00SBruno Cardoso Lopes       Attrs.NoUndeclaredIncludes = true;
2930ed84df00SBruno Cardoso Lopes       break;
29319194a91dSDouglas Gregor     }
29329194a91dSDouglas Gregor     consumeToken();
29339194a91dSDouglas Gregor 
29349194a91dSDouglas Gregor     // Consume the ']'.
29359194a91dSDouglas Gregor     if (!Tok.is(MMToken::RSquare)) {
29369194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
29379194a91dSDouglas Gregor       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
29389194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
29399194a91dSDouglas Gregor       HadError = true;
29409194a91dSDouglas Gregor     }
29419194a91dSDouglas Gregor 
29429194a91dSDouglas Gregor     if (Tok.is(MMToken::RSquare))
29439194a91dSDouglas Gregor       consumeToken();
29449194a91dSDouglas Gregor   }
29459194a91dSDouglas Gregor 
29469194a91dSDouglas Gregor   return HadError;
29479194a91dSDouglas Gregor }
29489194a91dSDouglas Gregor 
29499fc8faf9SAdrian Prantl /// Parse a module map file.
2950718292f2SDouglas Gregor ///
2951718292f2SDouglas Gregor ///   module-map-file:
2952718292f2SDouglas Gregor ///     module-declaration*
2953718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
2954718292f2SDouglas Gregor   do {
2955718292f2SDouglas Gregor     switch (Tok.Kind) {
2956718292f2SDouglas Gregor     case MMToken::EndOfFile:
2957718292f2SDouglas Gregor       return HadError;
2958718292f2SDouglas Gregor 
2959e7ab3669SDouglas Gregor     case MMToken::ExplicitKeyword:
296097292843SDaniel Jasper     case MMToken::ExternKeyword:
2961718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
2962755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
2963718292f2SDouglas Gregor       parseModuleDecl();
2964718292f2SDouglas Gregor       break;
2965718292f2SDouglas Gregor 
29661fb5c3a6SDouglas Gregor     case MMToken::Comma:
296735b13eceSDouglas Gregor     case MMToken::ConfigMacros:
2968fb912657SDouglas Gregor     case MMToken::Conflict:
2969a3feee2aSRichard Smith     case MMToken::Exclaim:
297059527666SDouglas Gregor     case MMToken::ExcludeKeyword:
29712b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
2972f0b11de2SDouglas Gregor     case MMToken::ExportAsKeyword:
2973718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
2974718292f2SDouglas Gregor     case MMToken::Identifier:
2975718292f2SDouglas Gregor     case MMToken::LBrace:
29766ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
2977a686e1b0SDouglas Gregor     case MMToken::LSquare:
29782b82c2a5SDouglas Gregor     case MMToken::Period:
2979b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
2980718292f2SDouglas Gregor     case MMToken::RBrace:
2981a686e1b0SDouglas Gregor     case MMToken::RSquare:
29821fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
29832b82c2a5SDouglas Gregor     case MMToken::Star:
2984718292f2SDouglas Gregor     case MMToken::StringLiteral:
2985040e1266SRichard Smith     case MMToken::IntegerLiteral:
2986b8afebe2SRichard Smith     case MMToken::TextualKeyword:
2987718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
2988ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
2989718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
2990718292f2SDouglas Gregor       HadError = true;
2991718292f2SDouglas Gregor       consumeToken();
2992718292f2SDouglas Gregor       break;
2993718292f2SDouglas Gregor     }
2994718292f2SDouglas Gregor   } while (true);
2995718292f2SDouglas Gregor }
2996718292f2SDouglas Gregor 
29977799ef71SNico Weber bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
2998c192d194SBruno Cardoso Lopes                                    const DirectoryEntry *Dir, FileID ID,
29998128f332SRichard Smith                                    unsigned *Offset,
3000ae6df27eSRichard Smith                                    SourceLocation ExternModuleLoc) {
30018128f332SRichard Smith   assert(Target && "Missing target information");
30024ddf2221SDouglas Gregor   llvm::DenseMap<const FileEntry *, bool>::iterator Known
30034ddf2221SDouglas Gregor     = ParsedModuleMap.find(File);
30044ddf2221SDouglas Gregor   if (Known != ParsedModuleMap.end())
30054ddf2221SDouglas Gregor     return Known->second;
30064ddf2221SDouglas Gregor 
30078128f332SRichard Smith   // If the module map file wasn't already entered, do so now.
30088128f332SRichard Smith   if (ID.isInvalid()) {
3009f3f84616SRichard Smith     auto FileCharacter =
3010f3f84616SRichard Smith         IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
30118128f332SRichard Smith     ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
30128128f332SRichard Smith   }
30138128f332SRichard Smith 
30148128f332SRichard Smith   assert(Target && "Missing target information");
3015b03ae743SDuncan P. N. Exon Smith   llvm::Optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
3016718292f2SDouglas Gregor   if (!Buffer)
30174ddf2221SDouglas Gregor     return ParsedModuleMap[File] = true;
30188128f332SRichard Smith   assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
30198128f332SRichard Smith          "invalid buffer offset");
3020718292f2SDouglas Gregor 
3021718292f2SDouglas Gregor   // Parse this module map file.
30228128f332SRichard Smith   Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
30238128f332SRichard Smith           Buffer->getBufferStart(),
30248128f332SRichard Smith           Buffer->getBufferStart() + (Offset ? *Offset : 0),
30258128f332SRichard Smith           Buffer->getBufferEnd());
30262a6edb30SRichard Smith   SourceLocation Start = L.getSourceLocation();
3027beee15e7SBen Langmuir   ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
3028c192d194SBruno Cardoso Lopes                          IsSystem);
3029718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
30304ddf2221SDouglas Gregor   ParsedModuleMap[File] = Result;
30312a6edb30SRichard Smith 
30328128f332SRichard Smith   if (Offset) {
30338128f332SRichard Smith     auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
30348128f332SRichard Smith     assert(Loc.first == ID && "stopped in a different file?");
30358128f332SRichard Smith     *Offset = Loc.second;
30368128f332SRichard Smith   }
30378128f332SRichard Smith 
30382a6edb30SRichard Smith   // Notify callbacks that we parsed it.
30392a6edb30SRichard Smith   for (const auto &Cb : Callbacks)
30402a6edb30SRichard Smith     Cb->moduleMapFileRead(Start, *File, IsSystem);
30418587dfd9SBruno Cardoso Lopes 
3042718292f2SDouglas Gregor   return Result;
3043718292f2SDouglas Gregor }
3044