1afd1b1c9SEugene Zelenko //===- ModuleMap.cpp - Describe the layout of modules ---------------------===//
2718292f2SDouglas Gregor //
3718292f2SDouglas Gregor //                     The LLVM Compiler Infrastructure
4718292f2SDouglas Gregor //
5718292f2SDouglas Gregor // This file is distributed under the University of Illinois Open Source
6718292f2SDouglas Gregor // License. See LICENSE.TXT for details.
7718292f2SDouglas Gregor //
8718292f2SDouglas Gregor //===----------------------------------------------------------------------===//
9718292f2SDouglas Gregor //
10718292f2SDouglas Gregor // This file defines the ModuleMap implementation, which describes the layout
11718292f2SDouglas Gregor // of a module as it relates to headers.
12718292f2SDouglas Gregor //
13718292f2SDouglas Gregor //===----------------------------------------------------------------------===//
14afd1b1c9SEugene Zelenko 
15718292f2SDouglas Gregor #include "clang/Lex/ModuleMap.h"
16a7d03840SJordan Rose #include "clang/Basic/CharInfo.h"
17718292f2SDouglas Gregor #include "clang/Basic/Diagnostic.h"
18718292f2SDouglas Gregor #include "clang/Basic/FileManager.h"
19afd1b1c9SEugene Zelenko #include "clang/Basic/LLVM.h"
20afd1b1c9SEugene Zelenko #include "clang/Basic/LangOptions.h"
21afd1b1c9SEugene Zelenko #include "clang/Basic/Module.h"
22afd1b1c9SEugene Zelenko #include "clang/Basic/SourceLocation.h"
23afd1b1c9SEugene Zelenko #include "clang/Basic/SourceManager.h"
24718292f2SDouglas Gregor #include "clang/Basic/TargetInfo.h"
25b146baabSArgyrios Kyrtzidis #include "clang/Lex/HeaderSearch.h"
269acb99e3SRichard Smith #include "clang/Lex/HeaderSearchOptions.h"
273a02247dSChandler Carruth #include "clang/Lex/LexDiagnostic.h"
283a02247dSChandler Carruth #include "clang/Lex/Lexer.h"
293a02247dSChandler Carruth #include "clang/Lex/LiteralSupport.h"
30afd1b1c9SEugene Zelenko #include "clang/Lex/Token.h"
31afd1b1c9SEugene Zelenko #include "llvm/ADT/DenseMap.h"
32afd1b1c9SEugene Zelenko #include "llvm/ADT/None.h"
33afd1b1c9SEugene Zelenko #include "llvm/ADT/STLExtras.h"
34afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallPtrSet.h"
35afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallString.h"
36afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallVector.h"
37afd1b1c9SEugene Zelenko #include "llvm/ADT/StringMap.h"
383a02247dSChandler Carruth #include "llvm/ADT/StringRef.h"
393a02247dSChandler Carruth #include "llvm/ADT/StringSwitch.h"
40718292f2SDouglas Gregor #include "llvm/Support/Allocator.h"
41afd1b1c9SEugene Zelenko #include "llvm/Support/Compiler.h"
42afd1b1c9SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
43afd1b1c9SEugene Zelenko #include "llvm/Support/MemoryBuffer.h"
44552c169eSRafael Espindola #include "llvm/Support/Path.h"
45*fc51490bSJonas Devlieghere #include "llvm/Support/VirtualFileSystem.h"
46718292f2SDouglas Gregor #include "llvm/Support/raw_ostream.h"
47afd1b1c9SEugene Zelenko #include <algorithm>
48afd1b1c9SEugene Zelenko #include <cassert>
49afd1b1c9SEugene Zelenko #include <cstdint>
50afd1b1c9SEugene Zelenko #include <cstring>
51afd1b1c9SEugene Zelenko #include <string>
52afd1b1c9SEugene Zelenko #include <system_error>
53afd1b1c9SEugene Zelenko #include <utility>
54afd1b1c9SEugene Zelenko 
55718292f2SDouglas Gregor using namespace clang;
56718292f2SDouglas Gregor 
57a3b5f71eSBruno Cardoso Lopes void ModuleMap::resolveLinkAsDependencies(Module *Mod) {
58a3b5f71eSBruno Cardoso Lopes   auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name);
59a3b5f71eSBruno Cardoso Lopes   if (PendingLinkAs != PendingLinkAsModule.end()) {
60a3b5f71eSBruno Cardoso Lopes     for (auto &Name : PendingLinkAs->second) {
61a3b5f71eSBruno Cardoso Lopes       auto *M = findModule(Name.getKey());
62a3b5f71eSBruno Cardoso Lopes       if (M)
63a3b5f71eSBruno Cardoso Lopes         M->UseExportAsModuleLinkName = true;
64a3b5f71eSBruno Cardoso Lopes     }
65a3b5f71eSBruno Cardoso Lopes   }
66a3b5f71eSBruno Cardoso Lopes }
67a3b5f71eSBruno Cardoso Lopes 
68a3b5f71eSBruno Cardoso Lopes void ModuleMap::addLinkAsDependency(Module *Mod) {
69a3b5f71eSBruno Cardoso Lopes   if (findModule(Mod->ExportAsModule))
70a3b5f71eSBruno Cardoso Lopes     Mod->UseExportAsModuleLinkName = true;
71a3b5f71eSBruno Cardoso Lopes   else
72a3b5f71eSBruno Cardoso Lopes     PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name);
73a3b5f71eSBruno Cardoso Lopes }
74a3b5f71eSBruno Cardoso Lopes 
75040e1266SRichard Smith Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
76040e1266SRichard Smith   switch ((int)Role) {
77040e1266SRichard Smith   default: llvm_unreachable("unknown header role");
78040e1266SRichard Smith   case NormalHeader:
79040e1266SRichard Smith     return Module::HK_Normal;
80040e1266SRichard Smith   case PrivateHeader:
81040e1266SRichard Smith     return Module::HK_Private;
82040e1266SRichard Smith   case TextualHeader:
83040e1266SRichard Smith     return Module::HK_Textual;
84040e1266SRichard Smith   case PrivateHeader | TextualHeader:
85040e1266SRichard Smith     return Module::HK_PrivateTextual;
86040e1266SRichard Smith   }
87040e1266SRichard Smith }
88040e1266SRichard Smith 
89040e1266SRichard Smith ModuleMap::ModuleHeaderRole
90040e1266SRichard Smith ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
91040e1266SRichard Smith   switch ((int)Kind) {
92040e1266SRichard Smith   case Module::HK_Normal:
93040e1266SRichard Smith     return NormalHeader;
94040e1266SRichard Smith   case Module::HK_Private:
95040e1266SRichard Smith     return PrivateHeader;
96040e1266SRichard Smith   case Module::HK_Textual:
97040e1266SRichard Smith     return TextualHeader;
98040e1266SRichard Smith   case Module::HK_PrivateTextual:
99040e1266SRichard Smith     return ModuleHeaderRole(PrivateHeader | TextualHeader);
100040e1266SRichard Smith   case Module::HK_Excluded:
101040e1266SRichard Smith     llvm_unreachable("unexpected header kind");
102040e1266SRichard Smith   }
103040e1266SRichard Smith   llvm_unreachable("unknown header kind");
104040e1266SRichard Smith }
105040e1266SRichard Smith 
1062b82c2a5SDouglas Gregor Module::ExportDecl
1072b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod,
1082b82c2a5SDouglas Gregor                          const Module::UnresolvedExportDecl &Unresolved,
109e4412640SArgyrios Kyrtzidis                          bool Complain) const {
110f5eedd05SDouglas Gregor   // We may have just a wildcard.
111f5eedd05SDouglas Gregor   if (Unresolved.Id.empty()) {
112f5eedd05SDouglas Gregor     assert(Unresolved.Wildcard && "Invalid unresolved export");
113d2d442caSCraig Topper     return Module::ExportDecl(nullptr, true);
114f5eedd05SDouglas Gregor   }
115f5eedd05SDouglas Gregor 
116fb912657SDouglas Gregor   // Resolve the module-id.
117fb912657SDouglas Gregor   Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
118fb912657SDouglas Gregor   if (!Context)
119afd1b1c9SEugene Zelenko     return {};
120fb912657SDouglas Gregor 
121fb912657SDouglas Gregor   return Module::ExportDecl(Context, Unresolved.Wildcard);
122fb912657SDouglas Gregor }
123fb912657SDouglas Gregor 
124fb912657SDouglas Gregor Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
125fb912657SDouglas Gregor                                    bool Complain) const {
1262b82c2a5SDouglas Gregor   // Find the starting module.
127fb912657SDouglas Gregor   Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
1282b82c2a5SDouglas Gregor   if (!Context) {
1292b82c2a5SDouglas Gregor     if (Complain)
1300761a8a0SDaniel Jasper       Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
131fb912657SDouglas Gregor       << Id[0].first << Mod->getFullModuleName();
1322b82c2a5SDouglas Gregor 
133d2d442caSCraig Topper     return nullptr;
1342b82c2a5SDouglas Gregor   }
1352b82c2a5SDouglas Gregor 
1362b82c2a5SDouglas Gregor   // Dig into the module path.
137fb912657SDouglas Gregor   for (unsigned I = 1, N = Id.size(); I != N; ++I) {
138fb912657SDouglas Gregor     Module *Sub = lookupModuleQualified(Id[I].first, Context);
1392b82c2a5SDouglas Gregor     if (!Sub) {
1402b82c2a5SDouglas Gregor       if (Complain)
1410761a8a0SDaniel Jasper         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
142fb912657SDouglas Gregor         << Id[I].first << Context->getFullModuleName()
143fb912657SDouglas Gregor         << SourceRange(Id[0].second, Id[I-1].second);
1442b82c2a5SDouglas Gregor 
145d2d442caSCraig Topper       return nullptr;
1462b82c2a5SDouglas Gregor     }
1472b82c2a5SDouglas Gregor 
1482b82c2a5SDouglas Gregor     Context = Sub;
1492b82c2a5SDouglas Gregor   }
1502b82c2a5SDouglas Gregor 
151fb912657SDouglas Gregor   return Context;
1522b82c2a5SDouglas Gregor }
1532b82c2a5SDouglas Gregor 
1549fc8faf9SAdrian Prantl /// Append to \p Paths the set of paths needed to get to the
1551d60987fSRichard Smith /// subframework in which the given module lives.
1561d60987fSRichard Smith static void appendSubframeworkPaths(Module *Mod,
1571d60987fSRichard Smith                                     SmallVectorImpl<char> &Path) {
1581d60987fSRichard Smith   // Collect the framework names from the given module to the top-level module.
1591d60987fSRichard Smith   SmallVector<StringRef, 2> Paths;
1601d60987fSRichard Smith   for (; Mod; Mod = Mod->Parent) {
1611d60987fSRichard Smith     if (Mod->IsFramework)
1621d60987fSRichard Smith       Paths.push_back(Mod->Name);
1631d60987fSRichard Smith   }
1641d60987fSRichard Smith 
1651d60987fSRichard Smith   if (Paths.empty())
1661d60987fSRichard Smith     return;
1671d60987fSRichard Smith 
1681d60987fSRichard Smith   // Add Frameworks/Name.framework for each subframework.
1691d60987fSRichard Smith   for (unsigned I = Paths.size() - 1; I != 0; --I)
1701d60987fSRichard Smith     llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework");
1711d60987fSRichard Smith }
1721d60987fSRichard Smith 
1739f6020bcSBruno Cardoso Lopes const FileEntry *ModuleMap::findHeader(
1749f6020bcSBruno Cardoso Lopes     Module *M, const Module::UnresolvedHeaderDirective &Header,
1759f6020bcSBruno Cardoso Lopes     SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) {
1769f6020bcSBruno Cardoso Lopes   // Search for the header file within the module's home directory.
1779f6020bcSBruno Cardoso Lopes   auto *Directory = M->Directory;
1789f6020bcSBruno Cardoso Lopes   SmallString<128> FullPathName(Directory->getName());
1799f6020bcSBruno Cardoso Lopes 
180040e1266SRichard Smith   auto GetFile = [&](StringRef Filename) -> const FileEntry * {
181040e1266SRichard Smith     auto *File = SourceMgr.getFileManager().getFile(Filename);
182040e1266SRichard Smith     if (!File ||
183040e1266SRichard Smith         (Header.Size && File->getSize() != *Header.Size) ||
184040e1266SRichard Smith         (Header.ModTime && File->getModificationTime() != *Header.ModTime))
185040e1266SRichard Smith       return nullptr;
186040e1266SRichard Smith     return File;
187040e1266SRichard Smith   };
188040e1266SRichard Smith 
1899f6020bcSBruno Cardoso Lopes   auto GetFrameworkFile = [&]() -> const FileEntry * {
1901d60987fSRichard Smith     unsigned FullPathLength = FullPathName.size();
1911d60987fSRichard Smith     appendSubframeworkPaths(M, RelativePathName);
1921d60987fSRichard Smith     unsigned RelativePathLength = RelativePathName.size();
1931d60987fSRichard Smith 
1941d60987fSRichard Smith     // Check whether this file is in the public headers.
1951d60987fSRichard Smith     llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
1961d60987fSRichard Smith     llvm::sys::path::append(FullPathName, RelativePathName);
197040e1266SRichard Smith     if (auto *File = GetFile(FullPathName))
1981d60987fSRichard Smith       return File;
1991d60987fSRichard Smith 
2001d60987fSRichard Smith     // Check whether this file is in the private headers.
2011d60987fSRichard Smith     // Ideally, private modules in the form 'FrameworkName.Private' should
2021d60987fSRichard Smith     // be defined as 'module FrameworkName.Private', and not as
2031d60987fSRichard Smith     // 'framework module FrameworkName.Private', since a 'Private.Framework'
2041d60987fSRichard Smith     // does not usually exist. However, since both are currently widely used
2051d60987fSRichard Smith     // for private modules, make sure we find the right path in both cases.
2061d60987fSRichard Smith     if (M->IsFramework && M->Name == "Private")
2071d60987fSRichard Smith       RelativePathName.clear();
2081d60987fSRichard Smith     else
2091d60987fSRichard Smith       RelativePathName.resize(RelativePathLength);
2101d60987fSRichard Smith     FullPathName.resize(FullPathLength);
2111d60987fSRichard Smith     llvm::sys::path::append(RelativePathName, "PrivateHeaders",
2121d60987fSRichard Smith                             Header.FileName);
2131d60987fSRichard Smith     llvm::sys::path::append(FullPathName, RelativePathName);
214040e1266SRichard Smith     return GetFile(FullPathName);
2159f6020bcSBruno Cardoso Lopes   };
2169f6020bcSBruno Cardoso Lopes 
2179f6020bcSBruno Cardoso Lopes   if (llvm::sys::path::is_absolute(Header.FileName)) {
2189f6020bcSBruno Cardoso Lopes     RelativePathName.clear();
2199f6020bcSBruno Cardoso Lopes     RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
2209f6020bcSBruno Cardoso Lopes     return GetFile(Header.FileName);
2211d60987fSRichard Smith   }
2221d60987fSRichard Smith 
2239f6020bcSBruno Cardoso Lopes   if (M->isPartOfFramework())
2249f6020bcSBruno Cardoso Lopes     return GetFrameworkFile();
2259f6020bcSBruno Cardoso Lopes 
2261d60987fSRichard Smith   // Lookup for normal headers.
2271d60987fSRichard Smith   llvm::sys::path::append(RelativePathName, Header.FileName);
2281d60987fSRichard Smith   llvm::sys::path::append(FullPathName, RelativePathName);
2299f6020bcSBruno Cardoso Lopes   auto *NormalHdrFile = GetFile(FullPathName);
2309f6020bcSBruno Cardoso Lopes 
2319f6020bcSBruno Cardoso Lopes   if (M && !NormalHdrFile && Directory->getName().endswith(".framework")) {
2329f6020bcSBruno Cardoso Lopes     // The lack of 'framework' keyword in a module declaration it's a simple
2339f6020bcSBruno Cardoso Lopes     // mistake we can diagnose when the header exists within the proper
2349f6020bcSBruno Cardoso Lopes     // framework style path.
2359f6020bcSBruno Cardoso Lopes     FullPathName.assign(Directory->getName());
2369f6020bcSBruno Cardoso Lopes     RelativePathName.clear();
237d101b5d7SErich Keane     if (GetFrameworkFile()) {
2389f6020bcSBruno Cardoso Lopes       Diags.Report(Header.FileNameLoc,
2399f6020bcSBruno Cardoso Lopes                    diag::warn_mmap_incomplete_framework_module_declaration)
2409f6020bcSBruno Cardoso Lopes           << Header.FileName << M->getFullModuleName();
2419f6020bcSBruno Cardoso Lopes       NeedsFramework = true;
2429f6020bcSBruno Cardoso Lopes     }
2439f6020bcSBruno Cardoso Lopes     return nullptr;
2449f6020bcSBruno Cardoso Lopes   }
2459f6020bcSBruno Cardoso Lopes 
2469f6020bcSBruno Cardoso Lopes   return NormalHdrFile;
2471d60987fSRichard Smith }
2481d60987fSRichard Smith 
249040e1266SRichard Smith void ModuleMap::resolveHeader(Module *Mod,
2509f6020bcSBruno Cardoso Lopes                               const Module::UnresolvedHeaderDirective &Header,
2519f6020bcSBruno Cardoso Lopes                               bool &NeedsFramework) {
252040e1266SRichard Smith   SmallString<128> RelativePathName;
2539f6020bcSBruno Cardoso Lopes   if (const FileEntry *File =
2549f6020bcSBruno Cardoso Lopes           findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
255040e1266SRichard Smith     if (Header.IsUmbrella) {
256040e1266SRichard Smith       const DirectoryEntry *UmbrellaDir = File->getDir();
257040e1266SRichard Smith       if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
258040e1266SRichard Smith         Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
259040e1266SRichard Smith           << UmbrellaMod->getFullModuleName();
260040e1266SRichard Smith       else
261040e1266SRichard Smith         // Record this umbrella header.
262040e1266SRichard Smith         setUmbrellaHeader(Mod, File, RelativePathName.str());
263040e1266SRichard Smith     } else {
264040e1266SRichard Smith       Module::Header H = {RelativePathName.str(), File};
265040e1266SRichard Smith       if (Header.Kind == Module::HK_Excluded)
266040e1266SRichard Smith         excludeHeader(Mod, H);
267040e1266SRichard Smith       else
268040e1266SRichard Smith         addHeader(Mod, H, headerKindToRole(Header.Kind));
269040e1266SRichard Smith     }
270040e1266SRichard Smith   } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
271040e1266SRichard Smith     // There's a builtin header but no corresponding on-disk header. Assume
272040e1266SRichard Smith     // this was supposed to modularize the builtin header alone.
273040e1266SRichard Smith   } else if (Header.Kind == Module::HK_Excluded) {
274040e1266SRichard Smith     // Ignore missing excluded header files. They're optional anyway.
275040e1266SRichard Smith   } else {
276040e1266SRichard Smith     // If we find a module that has a missing header, we mark this module as
277040e1266SRichard Smith     // unavailable and store the header directive for displaying diagnostics.
278040e1266SRichard Smith     Mod->MissingHeaders.push_back(Header);
279040e1266SRichard Smith     // A missing header with stat information doesn't make the module
280040e1266SRichard Smith     // unavailable; this keeps our behavior consistent as headers are lazily
281040e1266SRichard Smith     // resolved. (Such a module still can't be built though, except from
282040e1266SRichard Smith     // preprocessed source.)
283040e1266SRichard Smith     if (!Header.Size && !Header.ModTime)
284040e1266SRichard Smith       Mod->markUnavailable();
285040e1266SRichard Smith   }
286040e1266SRichard Smith }
287040e1266SRichard Smith 
288040e1266SRichard Smith bool ModuleMap::resolveAsBuiltinHeader(
289040e1266SRichard Smith     Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
290040e1266SRichard Smith   if (Header.Kind == Module::HK_Excluded ||
291040e1266SRichard Smith       llvm::sys::path::is_absolute(Header.FileName) ||
292040e1266SRichard Smith       Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
293040e1266SRichard Smith       !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
294040e1266SRichard Smith       !isBuiltinHeader(Header.FileName))
295040e1266SRichard Smith     return false;
2961d60987fSRichard Smith 
2971d60987fSRichard Smith   // This is a system module with a top-level header. This header
2981d60987fSRichard Smith   // may have a counterpart (or replacement) in the set of headers
2991d60987fSRichard Smith   // supplied by Clang. Find that builtin header.
300040e1266SRichard Smith   SmallString<128> Path;
301040e1266SRichard Smith   llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
302040e1266SRichard Smith   auto *File = SourceMgr.getFileManager().getFile(Path);
303040e1266SRichard Smith   if (!File)
304040e1266SRichard Smith     return false;
305040e1266SRichard Smith 
306040e1266SRichard Smith   auto Role = headerKindToRole(Header.Kind);
307040e1266SRichard Smith   Module::Header H = {Path.str(), File};
308040e1266SRichard Smith   addHeader(Mod, H, Role);
309040e1266SRichard Smith   return true;
3101d60987fSRichard Smith }
3111d60987fSRichard Smith 
3120761a8a0SDaniel Jasper ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
313b146baabSArgyrios Kyrtzidis                      const LangOptions &LangOpts, const TargetInfo *Target,
314b146baabSArgyrios Kyrtzidis                      HeaderSearch &HeaderInfo)
3150761a8a0SDaniel Jasper     : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
316056bf77fSRichard Smith       HeaderInfo(HeaderInfo) {
3170414b857SRichard Smith   MMapLangOpts.LineComment = true;
3180414b857SRichard Smith }
319718292f2SDouglas Gregor 
320718292f2SDouglas Gregor ModuleMap::~ModuleMap() {
32121668754SDavide Italiano   for (auto &M : Modules)
32221668754SDavide Italiano     delete M.getValue();
3238587dfd9SBruno Cardoso Lopes   for (auto *M : ShadowModules)
3248587dfd9SBruno Cardoso Lopes     delete M;
325718292f2SDouglas Gregor }
326718292f2SDouglas Gregor 
32789929282SDouglas Gregor void ModuleMap::setTarget(const TargetInfo &Target) {
32889929282SDouglas Gregor   assert((!this->Target || this->Target == &Target) &&
32989929282SDouglas Gregor          "Improper target override");
33089929282SDouglas Gregor   this->Target = &Target;
33189929282SDouglas Gregor }
33289929282SDouglas Gregor 
3339fc8faf9SAdrian Prantl /// "Sanitize" a filename so that it can be used as an identifier.
334056396aeSDouglas Gregor static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
335056396aeSDouglas Gregor                                               SmallVectorImpl<char> &Buffer) {
336056396aeSDouglas Gregor   if (Name.empty())
337056396aeSDouglas Gregor     return Name;
338056396aeSDouglas Gregor 
339a7d03840SJordan Rose   if (!isValidIdentifier(Name)) {
340056396aeSDouglas Gregor     // If we don't already have something with the form of an identifier,
341056396aeSDouglas Gregor     // create a buffer with the sanitized name.
342056396aeSDouglas Gregor     Buffer.clear();
343a7d03840SJordan Rose     if (isDigit(Name[0]))
344056396aeSDouglas Gregor       Buffer.push_back('_');
345056396aeSDouglas Gregor     Buffer.reserve(Buffer.size() + Name.size());
346056396aeSDouglas Gregor     for (unsigned I = 0, N = Name.size(); I != N; ++I) {
347a7d03840SJordan Rose       if (isIdentifierBody(Name[I]))
348056396aeSDouglas Gregor         Buffer.push_back(Name[I]);
349056396aeSDouglas Gregor       else
350056396aeSDouglas Gregor         Buffer.push_back('_');
351056396aeSDouglas Gregor     }
352056396aeSDouglas Gregor 
353056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
354056396aeSDouglas Gregor   }
355056396aeSDouglas Gregor 
356056396aeSDouglas Gregor   while (llvm::StringSwitch<bool>(Name)
357056396aeSDouglas Gregor #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
358056396aeSDouglas Gregor #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
359056396aeSDouglas Gregor #include "clang/Basic/TokenKinds.def"
360056396aeSDouglas Gregor            .Default(false)) {
361056396aeSDouglas Gregor     if (Name.data() != Buffer.data())
362056396aeSDouglas Gregor       Buffer.append(Name.begin(), Name.end());
363056396aeSDouglas Gregor     Buffer.push_back('_');
364056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
365056396aeSDouglas Gregor   }
366056396aeSDouglas Gregor 
367056396aeSDouglas Gregor   return Name;
368056396aeSDouglas Gregor }
369056396aeSDouglas Gregor 
3709fc8faf9SAdrian Prantl /// Determine whether the given file name is the name of a builtin
37134d52749SDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system
37234d52749SDouglas Gregor /// headers.
373ba1b5c98SBruno Cardoso Lopes bool ModuleMap::isBuiltinHeader(StringRef FileName) {
37434d52749SDouglas Gregor   return llvm::StringSwitch<bool>(FileName)
37534d52749SDouglas Gregor            .Case("float.h", true)
37634d52749SDouglas Gregor            .Case("iso646.h", true)
37734d52749SDouglas Gregor            .Case("limits.h", true)
37834d52749SDouglas Gregor            .Case("stdalign.h", true)
37934d52749SDouglas Gregor            .Case("stdarg.h", true)
3803c4b1290SBen Langmuir            .Case("stdatomic.h", true)
38134d52749SDouglas Gregor            .Case("stdbool.h", true)
38234d52749SDouglas Gregor            .Case("stddef.h", true)
38334d52749SDouglas Gregor            .Case("stdint.h", true)
38434d52749SDouglas Gregor            .Case("tgmath.h", true)
38534d52749SDouglas Gregor            .Case("unwind.h", true)
38634d52749SDouglas Gregor            .Default(false);
38734d52749SDouglas Gregor }
38834d52749SDouglas Gregor 
38992669ee4SDaniel Jasper ModuleMap::HeadersMap::iterator
39092669ee4SDaniel Jasper ModuleMap::findKnownHeader(const FileEntry *File) {
391040e1266SRichard Smith   resolveHeaderDirectives(File);
39259527666SDouglas Gregor   HeadersMap::iterator Known = Headers.find(File);
39347972afdSRichard Smith   if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
39447972afdSRichard Smith       Known == Headers.end() && File->getDir() == BuiltinIncludeDir &&
395ba1b5c98SBruno Cardoso Lopes       ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()))) {
3964eaf0a6cSDaniel Jasper     HeaderInfo.loadTopLevelSystemModules();
39792669ee4SDaniel Jasper     return Headers.find(File);
3984eaf0a6cSDaniel Jasper   }
39992669ee4SDaniel Jasper   return Known;
40092669ee4SDaniel Jasper }
40192669ee4SDaniel Jasper 
4024469138eSBen Langmuir ModuleMap::KnownHeader
4034469138eSBen Langmuir ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
4044469138eSBen Langmuir                     SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
40547972afdSRichard Smith   if (UmbrellaDirs.empty())
406afd1b1c9SEugene Zelenko     return {};
40747972afdSRichard Smith 
4084469138eSBen Langmuir   const DirectoryEntry *Dir = File->getDir();
4094469138eSBen Langmuir   assert(Dir && "file in no directory");
4104469138eSBen Langmuir 
4114469138eSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
4124469138eSBen Langmuir   // frameworks moving from top-level frameworks to embedded frameworks tend
4134469138eSBen Langmuir   // to be symlinked from the top-level location to the embedded location,
4144469138eSBen Langmuir   // and we need to resolve lookups as if we had found the embedded location.
4154469138eSBen Langmuir   StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
4164469138eSBen Langmuir 
4174469138eSBen Langmuir   // Keep walking up the directory hierarchy, looking for a directory with
4184469138eSBen Langmuir   // an umbrella header.
4194469138eSBen Langmuir   do {
4204469138eSBen Langmuir     auto KnownDir = UmbrellaDirs.find(Dir);
4214469138eSBen Langmuir     if (KnownDir != UmbrellaDirs.end())
4224469138eSBen Langmuir       return KnownHeader(KnownDir->second, NormalHeader);
4234469138eSBen Langmuir 
4244469138eSBen Langmuir     IntermediateDirs.push_back(Dir);
4254469138eSBen Langmuir 
4264469138eSBen Langmuir     // Retrieve our parent path.
4274469138eSBen Langmuir     DirName = llvm::sys::path::parent_path(DirName);
4284469138eSBen Langmuir     if (DirName.empty())
4294469138eSBen Langmuir       break;
4304469138eSBen Langmuir 
4314469138eSBen Langmuir     // Resolve the parent path to a directory entry.
4324469138eSBen Langmuir     Dir = SourceMgr.getFileManager().getDirectory(DirName);
4334469138eSBen Langmuir   } while (Dir);
434afd1b1c9SEugene Zelenko   return {};
4354469138eSBen Langmuir }
4364469138eSBen Langmuir 
43792669ee4SDaniel Jasper static bool violatesPrivateInclude(Module *RequestingModule,
43892669ee4SDaniel Jasper                                    const FileEntry *IncFileEnt,
4394eb8393cSRichard Smith                                    ModuleMap::KnownHeader Header) {
44092669ee4SDaniel Jasper #ifndef NDEBUG
4414eb8393cSRichard Smith   if (Header.getRole() & ModuleMap::PrivateHeader) {
44292669ee4SDaniel Jasper     // Check for consistency between the module header role
44392669ee4SDaniel Jasper     // as obtained from the lookup and as obtained from the module.
44492669ee4SDaniel Jasper     // This check is not cheap, so enable it only for debugging.
4452708e520SRichard Smith     bool IsPrivate = false;
4462708e520SRichard Smith     SmallVectorImpl<Module::Header> *HeaderList[] = {
4474eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_Private],
4484eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_PrivateTextual]};
4492708e520SRichard Smith     for (auto *Hs : HeaderList)
4502708e520SRichard Smith       IsPrivate |=
4512708e520SRichard Smith           std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) {
4523c1a41adSRichard Smith             return H.Entry == IncFileEnt;
4532708e520SRichard Smith           }) != Hs->end();
4544eb8393cSRichard Smith     assert(IsPrivate && "inconsistent headers and roles");
45500bc95ecSRichard Smith   }
45692669ee4SDaniel Jasper #endif
4574eb8393cSRichard Smith   return !Header.isAccessibleFrom(RequestingModule);
45892669ee4SDaniel Jasper }
45992669ee4SDaniel Jasper 
46071e1a64fSBen Langmuir static Module *getTopLevelOrNull(Module *M) {
46171e1a64fSBen Langmuir   return M ? M->getTopLevelModule() : nullptr;
46271e1a64fSBen Langmuir }
46371e1a64fSBen Langmuir 
46492669ee4SDaniel Jasper void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
4658d4e90b3SRichard Smith                                         bool RequestingModuleIsModuleInterface,
46692669ee4SDaniel Jasper                                         SourceLocation FilenameLoc,
46792669ee4SDaniel Jasper                                         StringRef Filename,
46892669ee4SDaniel Jasper                                         const FileEntry *File) {
46992669ee4SDaniel Jasper   // No errors for indirect modules. This may be a bit of a problem for modules
47092669ee4SDaniel Jasper   // with no source files.
47171e1a64fSBen Langmuir   if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
47292669ee4SDaniel Jasper     return;
47392669ee4SDaniel Jasper 
474040e1266SRichard Smith   if (RequestingModule) {
47592669ee4SDaniel Jasper     resolveUses(RequestingModule, /*Complain=*/false);
476040e1266SRichard Smith     resolveHeaderDirectives(RequestingModule);
477040e1266SRichard Smith   }
47892669ee4SDaniel Jasper 
47971e1a64fSBen Langmuir   bool Excluded = false;
480d2d442caSCraig Topper   Module *Private = nullptr;
481d2d442caSCraig Topper   Module *NotUsed = nullptr;
48271e1a64fSBen Langmuir 
48371e1a64fSBen Langmuir   HeadersMap::iterator Known = findKnownHeader(File);
48471e1a64fSBen Langmuir   if (Known != Headers.end()) {
48571e1a64fSBen Langmuir     for (const KnownHeader &Header : Known->second) {
48692669ee4SDaniel Jasper       // Remember private headers for later printing of a diagnostic.
4874eb8393cSRichard Smith       if (violatesPrivateInclude(RequestingModule, File, Header)) {
48871e1a64fSBen Langmuir         Private = Header.getModule();
48992669ee4SDaniel Jasper         continue;
49092669ee4SDaniel Jasper       }
49192669ee4SDaniel Jasper 
49292669ee4SDaniel Jasper       // If uses need to be specified explicitly, we are only allowed to return
49392669ee4SDaniel Jasper       // modules that are explicitly used by the requesting module.
49492669ee4SDaniel Jasper       if (RequestingModule && LangOpts.ModulesDeclUse &&
4958f4d3ff1SRichard Smith           !RequestingModule->directlyUses(Header.getModule())) {
49671e1a64fSBen Langmuir         NotUsed = Header.getModule();
49792669ee4SDaniel Jasper         continue;
49892669ee4SDaniel Jasper       }
49992669ee4SDaniel Jasper 
50092669ee4SDaniel Jasper       // We have found a module that we can happily use.
50192669ee4SDaniel Jasper       return;
50292669ee4SDaniel Jasper     }
503feb54b6dSRichard Smith 
504feb54b6dSRichard Smith     Excluded = true;
50571e1a64fSBen Langmuir   }
50692669ee4SDaniel Jasper 
50792669ee4SDaniel Jasper   // We have found a header, but it is private.
508d2d442caSCraig Topper   if (Private) {
50911152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
51092669ee4SDaniel Jasper         << Filename;
51192669ee4SDaniel Jasper     return;
51292669ee4SDaniel Jasper   }
51392669ee4SDaniel Jasper 
51492669ee4SDaniel Jasper   // We have found a module, but we don't use it.
515d2d442caSCraig Topper   if (NotUsed) {
51611152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5174ea330c8SDaniel Jasper         << RequestingModule->getTopLevelModule()->Name << Filename;
51892669ee4SDaniel Jasper     return;
51992669ee4SDaniel Jasper   }
52092669ee4SDaniel Jasper 
52171e1a64fSBen Langmuir   if (Excluded || isHeaderInUmbrellaDirs(File))
52271e1a64fSBen Langmuir     return;
52371e1a64fSBen Langmuir 
52471e1a64fSBen Langmuir   // At this point, only non-modular includes remain.
52571e1a64fSBen Langmuir 
52671e1a64fSBen Langmuir   if (LangOpts.ModulesStrictDeclUse) {
52711152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5284ea330c8SDaniel Jasper         << RequestingModule->getTopLevelModule()->Name << Filename;
529a67e4d32SManman Ren   } else if (RequestingModule && RequestingModuleIsModuleInterface &&
530a67e4d32SManman Ren              LangOpts.isCompilingModule()) {
531a67e4d32SManman Ren     // Do not diagnose when we are not compiling a module.
53271e1a64fSBen Langmuir     diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
53371e1a64fSBen Langmuir         diag::warn_non_modular_include_in_framework_module :
53471e1a64fSBen Langmuir         diag::warn_non_modular_include_in_module;
53570a7738fSManman Ren     Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
53670a7738fSManman Ren         << File->getName();
53771e1a64fSBen Langmuir   }
53892669ee4SDaniel Jasper }
53992669ee4SDaniel Jasper 
540ec87a50aSRichard Smith static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
541ec87a50aSRichard Smith                                 const ModuleMap::KnownHeader &Old) {
5428b7c0398SSean Silva   // Prefer available modules.
5438b7c0398SSean Silva   if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
5448b7c0398SSean Silva     return true;
5458b7c0398SSean Silva 
546ec87a50aSRichard Smith   // Prefer a public header over a private header.
547ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::PrivateHeader) !=
548ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::PrivateHeader))
549ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::PrivateHeader);
550ec87a50aSRichard Smith 
551ec87a50aSRichard Smith   // Prefer a non-textual header over a textual header.
552ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::TextualHeader) !=
553ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::TextualHeader))
554ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::TextualHeader);
555ec87a50aSRichard Smith 
556ec87a50aSRichard Smith   // Don't have a reason to choose between these. Just keep the first one.
557ec87a50aSRichard Smith   return false;
558ec87a50aSRichard Smith }
559ec87a50aSRichard Smith 
560ed84df00SBruno Cardoso Lopes ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
561ed84df00SBruno Cardoso Lopes                                                       bool AllowTextual) {
562306d8920SRichard Smith   auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
563ed84df00SBruno Cardoso Lopes     if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
564afd1b1c9SEugene Zelenko       return {};
565306d8920SRichard Smith     return R;
566306d8920SRichard Smith   };
567306d8920SRichard Smith 
5684881e8b2SSean Silva   HeadersMap::iterator Known = findKnownHeader(File);
5691fb5c3a6SDouglas Gregor   if (Known != Headers.end()) {
570202210b3SRichard Smith     ModuleMap::KnownHeader Result;
57197da9178SDaniel Jasper     // Iterate over all modules that 'File' is part of to find the best fit.
5724881e8b2SSean Silva     for (KnownHeader &H : Known->second) {
5737e82e019SRichard Smith       // Prefer a header from the source module over all others.
5747e82e019SRichard Smith       if (H.getModule()->getTopLevelModule() == SourceModule)
5752f633e7cSRichard Smith         return MakeResult(H);
5764881e8b2SSean Silva       if (!Result || isBetterKnownHeader(H, Result))
5774881e8b2SSean Silva         Result = H;
57897da9178SDaniel Jasper     }
579306d8920SRichard Smith     return MakeResult(Result);
5801fb5c3a6SDouglas Gregor   }
581ab0c8a84SDouglas Gregor 
582386bb073SRichard Smith   return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
583386bb073SRichard Smith }
584386bb073SRichard Smith 
585386bb073SRichard Smith ModuleMap::KnownHeader
586386bb073SRichard Smith ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
587386bb073SRichard Smith   assert(!Headers.count(File) && "already have a module for this header");
588386bb073SRichard Smith 
589f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
5904469138eSBen Langmuir   KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
5914469138eSBen Langmuir   if (H) {
5924469138eSBen Langmuir     Module *Result = H.getModule();
593930a85ccSDouglas Gregor 
594930a85ccSDouglas Gregor     // Search up the module stack until we find a module with an umbrella
59573141fa9SDouglas Gregor     // directory.
596930a85ccSDouglas Gregor     Module *UmbrellaModule = Result;
59773141fa9SDouglas Gregor     while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
598930a85ccSDouglas Gregor       UmbrellaModule = UmbrellaModule->Parent;
599930a85ccSDouglas Gregor 
600930a85ccSDouglas Gregor     if (UmbrellaModule->InferSubmodules) {
6019d6448b1SBen Langmuir       const FileEntry *UmbrellaModuleMap =
6029d6448b1SBen Langmuir           getModuleMapFileForUniquing(UmbrellaModule);
6039d6448b1SBen Langmuir 
604a89c5ac4SDouglas Gregor       // Infer submodules for each of the directories we found between
605a89c5ac4SDouglas Gregor       // the directory of the umbrella header and the directory where
606a89c5ac4SDouglas Gregor       // the actual header is located.
6079458f82dSDouglas Gregor       bool Explicit = UmbrellaModule->InferExplicitSubmodules;
6089458f82dSDouglas Gregor 
6097033127bSDouglas Gregor       for (unsigned I = SkippedDirs.size(); I != 0; --I) {
610a89c5ac4SDouglas Gregor         // Find or create the module that corresponds to this directory name.
611056396aeSDouglas Gregor         SmallString<32> NameBuf;
612056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
6134469138eSBen Langmuir             llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
6149d6448b1SBen Langmuir         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6159d6448b1SBen Langmuir                                     Explicit).first;
6169d6448b1SBen Langmuir         InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
617ffbafa2aSBen Langmuir         Result->IsInferred = true;
618a89c5ac4SDouglas Gregor 
619a89c5ac4SDouglas Gregor         // Associate the module and the directory.
620a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I-1]] = Result;
621a89c5ac4SDouglas Gregor 
622a89c5ac4SDouglas Gregor         // If inferred submodules export everything they import, add a
623a89c5ac4SDouglas Gregor         // wildcard to the set of exports.
624930a85ccSDouglas Gregor         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
625d2d442caSCraig Topper           Result->Exports.push_back(Module::ExportDecl(nullptr, true));
626a89c5ac4SDouglas Gregor       }
627a89c5ac4SDouglas Gregor 
628a89c5ac4SDouglas Gregor       // Infer a submodule with the same name as this header file.
629056396aeSDouglas Gregor       SmallString<32> NameBuf;
630056396aeSDouglas Gregor       StringRef Name = sanitizeFilenameAsIdentifier(
631056396aeSDouglas Gregor                          llvm::sys::path::stem(File->getName()), NameBuf);
6329d6448b1SBen Langmuir       Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6339d6448b1SBen Langmuir                                   Explicit).first;
6349d6448b1SBen Langmuir       InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
635ffbafa2aSBen Langmuir       Result->IsInferred = true;
6363c5305c1SArgyrios Kyrtzidis       Result->addTopHeader(File);
637a89c5ac4SDouglas Gregor 
638a89c5ac4SDouglas Gregor       // If inferred submodules export everything they import, add a
639a89c5ac4SDouglas Gregor       // wildcard to the set of exports.
640930a85ccSDouglas Gregor       if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
641d2d442caSCraig Topper         Result->Exports.push_back(Module::ExportDecl(nullptr, true));
642a89c5ac4SDouglas Gregor     } else {
643a89c5ac4SDouglas Gregor       // Record each of the directories we stepped through as being part of
644a89c5ac4SDouglas Gregor       // the module we found, since the umbrella header covers them all.
645a89c5ac4SDouglas Gregor       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
646a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I]] = Result;
647a89c5ac4SDouglas Gregor     }
648a89c5ac4SDouglas Gregor 
649386bb073SRichard Smith     KnownHeader Header(Result, NormalHeader);
650386bb073SRichard Smith     Headers[File].push_back(Header);
651386bb073SRichard Smith     return Header;
652a89c5ac4SDouglas Gregor   }
653a89c5ac4SDouglas Gregor 
654afd1b1c9SEugene Zelenko   return {};
655ab0c8a84SDouglas Gregor }
656ab0c8a84SDouglas Gregor 
657386bb073SRichard Smith ArrayRef<ModuleMap::KnownHeader>
658386bb073SRichard Smith ModuleMap::findAllModulesForHeader(const FileEntry *File) const {
659040e1266SRichard Smith   resolveHeaderDirectives(File);
660386bb073SRichard Smith   auto It = Headers.find(File);
661386bb073SRichard Smith   if (It == Headers.end())
662386bb073SRichard Smith     return None;
663386bb073SRichard Smith   return It->second;
664386bb073SRichard Smith }
665386bb073SRichard Smith 
666e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
667d2d442caSCraig Topper   return isHeaderUnavailableInModule(Header, nullptr);
66850996ce1SRichard Smith }
66950996ce1SRichard Smith 
67062bcd925SDmitri Gribenko bool
67162bcd925SDmitri Gribenko ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
67262bcd925SDmitri Gribenko                                        const Module *RequestingModule) const {
673040e1266SRichard Smith   resolveHeaderDirectives(Header);
674e4412640SArgyrios Kyrtzidis   HeadersMap::const_iterator Known = Headers.find(Header);
67597da9178SDaniel Jasper   if (Known != Headers.end()) {
67697da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator
67797da9178SDaniel Jasper              I = Known->second.begin(),
67897da9178SDaniel Jasper              E = Known->second.end();
67997da9178SDaniel Jasper          I != E; ++I) {
680052d95a6SBruno Cardoso Lopes 
681052d95a6SBruno Cardoso Lopes       if (I->isAvailable() &&
682052d95a6SBruno Cardoso Lopes           (!RequestingModule ||
683052d95a6SBruno Cardoso Lopes            I->getModule()->isSubModuleOf(RequestingModule))) {
684052d95a6SBruno Cardoso Lopes         // When no requesting module is available, the caller is looking if a
685052d95a6SBruno Cardoso Lopes         // header is part a module by only looking into the module map. This is
686052d95a6SBruno Cardoso Lopes         // done by warn_uncovered_module_header checks; don't consider textual
687052d95a6SBruno Cardoso Lopes         // headers part of it in this mode, otherwise we get misleading warnings
688052d95a6SBruno Cardoso Lopes         // that a umbrella header is not including a textual header.
689052d95a6SBruno Cardoso Lopes         if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
690052d95a6SBruno Cardoso Lopes           continue;
69197da9178SDaniel Jasper         return false;
69297da9178SDaniel Jasper       }
693052d95a6SBruno Cardoso Lopes     }
69497da9178SDaniel Jasper     return true;
69597da9178SDaniel Jasper   }
6961fb5c3a6SDouglas Gregor 
6971fb5c3a6SDouglas Gregor   const DirectoryEntry *Dir = Header->getDir();
698f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
6991fb5c3a6SDouglas Gregor   StringRef DirName = Dir->getName();
7001fb5c3a6SDouglas Gregor 
70150996ce1SRichard Smith   auto IsUnavailable = [&](const Module *M) {
70250996ce1SRichard Smith     return !M->isAvailable() && (!RequestingModule ||
70350996ce1SRichard Smith                                  M->isSubModuleOf(RequestingModule));
70450996ce1SRichard Smith   };
70550996ce1SRichard Smith 
7061fb5c3a6SDouglas Gregor   // Keep walking up the directory hierarchy, looking for a directory with
7071fb5c3a6SDouglas Gregor   // an umbrella header.
7081fb5c3a6SDouglas Gregor   do {
709e4412640SArgyrios Kyrtzidis     llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
7101fb5c3a6SDouglas Gregor       = UmbrellaDirs.find(Dir);
7111fb5c3a6SDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
7121fb5c3a6SDouglas Gregor       Module *Found = KnownDir->second;
71350996ce1SRichard Smith       if (IsUnavailable(Found))
7141fb5c3a6SDouglas Gregor         return true;
7151fb5c3a6SDouglas Gregor 
7161fb5c3a6SDouglas Gregor       // Search up the module stack until we find a module with an umbrella
7171fb5c3a6SDouglas Gregor       // directory.
7181fb5c3a6SDouglas Gregor       Module *UmbrellaModule = Found;
7191fb5c3a6SDouglas Gregor       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
7201fb5c3a6SDouglas Gregor         UmbrellaModule = UmbrellaModule->Parent;
7211fb5c3a6SDouglas Gregor 
7221fb5c3a6SDouglas Gregor       if (UmbrellaModule->InferSubmodules) {
7231fb5c3a6SDouglas Gregor         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
7241fb5c3a6SDouglas Gregor           // Find or create the module that corresponds to this directory name.
725056396aeSDouglas Gregor           SmallString<32> NameBuf;
726056396aeSDouglas Gregor           StringRef Name = sanitizeFilenameAsIdentifier(
727056396aeSDouglas Gregor                              llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
728056396aeSDouglas Gregor                              NameBuf);
7291fb5c3a6SDouglas Gregor           Found = lookupModuleQualified(Name, Found);
7301fb5c3a6SDouglas Gregor           if (!Found)
7311fb5c3a6SDouglas Gregor             return false;
73250996ce1SRichard Smith           if (IsUnavailable(Found))
7331fb5c3a6SDouglas Gregor             return true;
7341fb5c3a6SDouglas Gregor         }
7351fb5c3a6SDouglas Gregor 
7361fb5c3a6SDouglas Gregor         // Infer a submodule with the same name as this header file.
737056396aeSDouglas Gregor         SmallString<32> NameBuf;
738056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
739056396aeSDouglas Gregor                            llvm::sys::path::stem(Header->getName()),
740056396aeSDouglas Gregor                            NameBuf);
7411fb5c3a6SDouglas Gregor         Found = lookupModuleQualified(Name, Found);
7421fb5c3a6SDouglas Gregor         if (!Found)
7431fb5c3a6SDouglas Gregor           return false;
7441fb5c3a6SDouglas Gregor       }
7451fb5c3a6SDouglas Gregor 
74650996ce1SRichard Smith       return IsUnavailable(Found);
7471fb5c3a6SDouglas Gregor     }
7481fb5c3a6SDouglas Gregor 
7491fb5c3a6SDouglas Gregor     SkippedDirs.push_back(Dir);
7501fb5c3a6SDouglas Gregor 
7511fb5c3a6SDouglas Gregor     // Retrieve our parent path.
7521fb5c3a6SDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
7531fb5c3a6SDouglas Gregor     if (DirName.empty())
7541fb5c3a6SDouglas Gregor       break;
7551fb5c3a6SDouglas Gregor 
7561fb5c3a6SDouglas Gregor     // Resolve the parent path to a directory entry.
7571f76c4e8SManuel Klimek     Dir = SourceMgr.getFileManager().getDirectory(DirName);
7581fb5c3a6SDouglas Gregor   } while (Dir);
7591fb5c3a6SDouglas Gregor 
7601fb5c3a6SDouglas Gregor   return false;
7611fb5c3a6SDouglas Gregor }
7621fb5c3a6SDouglas Gregor 
763e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const {
764e4412640SArgyrios Kyrtzidis   llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
76588bdfb0eSDouglas Gregor   if (Known != Modules.end())
76688bdfb0eSDouglas Gregor     return Known->getValue();
76788bdfb0eSDouglas Gregor 
768d2d442caSCraig Topper   return nullptr;
76988bdfb0eSDouglas Gregor }
77088bdfb0eSDouglas Gregor 
771e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
772e4412640SArgyrios Kyrtzidis                                            Module *Context) const {
7732b82c2a5SDouglas Gregor   for(; Context; Context = Context->Parent) {
7742b82c2a5SDouglas Gregor     if (Module *Sub = lookupModuleQualified(Name, Context))
7752b82c2a5SDouglas Gregor       return Sub;
7762b82c2a5SDouglas Gregor   }
7772b82c2a5SDouglas Gregor 
7782b82c2a5SDouglas Gregor   return findModule(Name);
7792b82c2a5SDouglas Gregor }
7802b82c2a5SDouglas Gregor 
781e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
7822b82c2a5SDouglas Gregor   if (!Context)
7832b82c2a5SDouglas Gregor     return findModule(Name);
7842b82c2a5SDouglas Gregor 
785eb90e830SDouglas Gregor   return Context->findSubmodule(Name);
7862b82c2a5SDouglas Gregor }
7872b82c2a5SDouglas Gregor 
788c192d194SBruno Cardoso Lopes std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
789c192d194SBruno Cardoso Lopes                                                         Module *Parent,
790c192d194SBruno Cardoso Lopes                                                         bool IsFramework,
791c192d194SBruno Cardoso Lopes                                                         bool IsExplicit) {
79269021974SDouglas Gregor   // Try to find an existing module with this name.
793eb90e830SDouglas Gregor   if (Module *Sub = lookupModuleQualified(Name, Parent))
794eb90e830SDouglas Gregor     return std::make_pair(Sub, false);
79569021974SDouglas Gregor 
79669021974SDouglas Gregor   // Create a new module with this name.
7979ffe5a35SDavid Blaikie   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
7989ffe5a35SDavid Blaikie                               IsExplicit, NumCreatedModules++);
7996f722b4eSArgyrios Kyrtzidis   if (!Parent) {
8007e82e019SRichard Smith     if (LangOpts.CurrentModule == Name)
8017e82e019SRichard Smith       SourceModule = Result;
80269021974SDouglas Gregor     Modules[Name] = Result;
803c192d194SBruno Cardoso Lopes     ModuleScopeIDs[Result] = CurrentModuleScopeID;
8046f722b4eSArgyrios Kyrtzidis   }
80569021974SDouglas Gregor   return std::make_pair(Result, true);
80669021974SDouglas Gregor }
80769021974SDouglas Gregor 
808dd8b5337SRichard Smith Module *ModuleMap::createGlobalModuleForInterfaceUnit(SourceLocation Loc) {
809d6509cf2SRichard Smith   PendingSubmodules.emplace_back(
810056bf77fSRichard Smith       new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
811056bf77fSRichard Smith                  /*IsExplicit*/ true, NumCreatedModules++));
812d6509cf2SRichard Smith   PendingSubmodules.back()->Kind = Module::GlobalModuleFragment;
813d6509cf2SRichard Smith   return PendingSubmodules.back().get();
814dd8b5337SRichard Smith }
815dd8b5337SRichard Smith 
816bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
817dd8b5337SRichard Smith                                                 StringRef Name,
818dd8b5337SRichard Smith                                                 Module *GlobalModule) {
819bbcc9f04SRichard Smith   assert(LangOpts.CurrentModule == Name && "module name mismatch");
820bbcc9f04SRichard Smith   assert(!Modules[Name] && "redefining existing module");
821bbcc9f04SRichard Smith 
822bbcc9f04SRichard Smith   auto *Result =
823bbcc9f04SRichard Smith       new Module(Name, Loc, nullptr, /*IsFramework*/ false,
824bbcc9f04SRichard Smith                  /*IsExplicit*/ false, NumCreatedModules++);
825145e15a3SRichard Smith   Result->Kind = Module::ModuleInterfaceUnit;
826bbcc9f04SRichard Smith   Modules[Name] = SourceModule = Result;
827bbcc9f04SRichard Smith 
828dd8b5337SRichard Smith   // Reparent the current global module fragment as a submodule of this module.
829d6509cf2SRichard Smith   for (auto &Submodule : PendingSubmodules) {
830d6509cf2SRichard Smith     Submodule->setParent(Result);
831d6509cf2SRichard Smith     Submodule.release(); // now owned by parent
832d6509cf2SRichard Smith   }
833d6509cf2SRichard Smith   PendingSubmodules.clear();
834dd8b5337SRichard Smith 
835bbcc9f04SRichard Smith   // Mark the main source file as being within the newly-created module so that
836bbcc9f04SRichard Smith   // declarations and macros are properly visibility-restricted to it.
837bbcc9f04SRichard Smith   auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
838bbcc9f04SRichard Smith   assert(MainFile && "no input file for module interface");
839bbcc9f04SRichard Smith   Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader));
840bbcc9f04SRichard Smith 
841bbcc9f04SRichard Smith   return Result;
842bbcc9f04SRichard Smith }
843bbcc9f04SRichard Smith 
844d6509cf2SRichard Smith Module *ModuleMap::createHeaderModule(StringRef Name,
845d6509cf2SRichard Smith                                       ArrayRef<Module::Header> Headers) {
846d6509cf2SRichard Smith   assert(LangOpts.CurrentModule == Name && "module name mismatch");
847d6509cf2SRichard Smith   assert(!Modules[Name] && "redefining existing module");
848d6509cf2SRichard Smith 
849d6509cf2SRichard Smith   auto *Result =
850d6509cf2SRichard Smith       new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false,
851d6509cf2SRichard Smith                  /*IsExplicit*/ false, NumCreatedModules++);
852d6509cf2SRichard Smith   Result->Kind = Module::ModuleInterfaceUnit;
853d6509cf2SRichard Smith   Modules[Name] = SourceModule = Result;
854d6509cf2SRichard Smith 
855d6509cf2SRichard Smith   for (const Module::Header &H : Headers) {
856d6509cf2SRichard Smith     auto *M = new Module(H.NameAsWritten, SourceLocation(), Result,
857d6509cf2SRichard Smith                          /*IsFramework*/ false,
858d6509cf2SRichard Smith                          /*IsExplicit*/ true, NumCreatedModules++);
859d6509cf2SRichard Smith     // Header modules are implicitly 'export *'.
860d6509cf2SRichard Smith     M->Exports.push_back(Module::ExportDecl(nullptr, true));
861d6509cf2SRichard Smith     addHeader(M, H, NormalHeader);
862d6509cf2SRichard Smith   }
863d6509cf2SRichard Smith 
864d6509cf2SRichard Smith   return Result;
865d6509cf2SRichard Smith }
866d6509cf2SRichard Smith 
8679fc8faf9SAdrian Prantl /// For a framework module, infer the framework against which we
86811dfe6feSDouglas Gregor /// should link.
86911dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
87011dfe6feSDouglas Gregor                                FileManager &FileMgr) {
87111dfe6feSDouglas Gregor   assert(Mod->IsFramework && "Can only infer linking for framework modules");
87211dfe6feSDouglas Gregor   assert(!Mod->isSubFramework() &&
87311dfe6feSDouglas Gregor          "Can only infer linking for top-level frameworks");
87411dfe6feSDouglas Gregor 
87511dfe6feSDouglas Gregor   SmallString<128> LibName;
87611dfe6feSDouglas Gregor   LibName += FrameworkDir->getName();
87711dfe6feSDouglas Gregor   llvm::sys::path::append(LibName, Mod->Name);
8788aaae5a9SJuergen Ributzka 
8798aaae5a9SJuergen Ributzka   // The library name of a framework has more than one possible extension since
8808aaae5a9SJuergen Ributzka   // the introduction of the text-based dynamic library format. We need to check
8818aaae5a9SJuergen Ributzka   // for both before we give up.
8828013e81dSBenjamin Kramer   for (const char *extension : {"", ".tbd"}) {
8838aaae5a9SJuergen Ributzka     llvm::sys::path::replace_extension(LibName, extension);
88411dfe6feSDouglas Gregor     if (FileMgr.getFile(LibName)) {
88511dfe6feSDouglas Gregor       Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
88611dfe6feSDouglas Gregor                                                        /*IsFramework=*/true));
8878aaae5a9SJuergen Ributzka       return;
8888aaae5a9SJuergen Ributzka     }
88911dfe6feSDouglas Gregor   }
89011dfe6feSDouglas Gregor }
89111dfe6feSDouglas Gregor 
892a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
893a525400dSBen Langmuir                                         bool IsSystem, Module *Parent) {
894c1d88ea5SBen Langmuir   Attributes Attrs;
895c1d88ea5SBen Langmuir   Attrs.IsSystem = IsSystem;
896a525400dSBen Langmuir   return inferFrameworkModule(FrameworkDir, Attrs, Parent);
897c1d88ea5SBen Langmuir }
898c1d88ea5SBen Langmuir 
899a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
900c1d88ea5SBen Langmuir                                         Attributes Attrs, Module *Parent) {
901a525400dSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
902a525400dSBen Langmuir   // we might be looking at an embedded framework that symlinks out to a
903a525400dSBen Langmuir   // top-level framework, and we need to infer as if we were naming the
904a525400dSBen Langmuir   // top-level framework.
905a525400dSBen Langmuir   StringRef FrameworkDirName =
906a525400dSBen Langmuir       SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
907a525400dSBen Langmuir 
908a525400dSBen Langmuir   // In case this is a case-insensitive filesystem, use the canonical
909a525400dSBen Langmuir   // directory name as the ModuleName, since modules are case-sensitive.
910a525400dSBen Langmuir   // FIXME: we should be able to give a fix-it hint for the correct spelling.
911a525400dSBen Langmuir   SmallString<32> ModuleNameStorage;
912a525400dSBen Langmuir   StringRef ModuleName = sanitizeFilenameAsIdentifier(
913a525400dSBen Langmuir       llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
914c1d88ea5SBen Langmuir 
91556c64013SDouglas Gregor   // Check whether we've already found this module.
916e89dbc1dSDouglas Gregor   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
917e89dbc1dSDouglas Gregor     return Mod;
918e89dbc1dSDouglas Gregor 
9191f76c4e8SManuel Klimek   FileManager &FileMgr = SourceMgr.getFileManager();
92056c64013SDouglas Gregor 
9219194a91dSDouglas Gregor   // If the framework has a parent path from which we're allowed to infer
9229194a91dSDouglas Gregor   // a framework module, do so.
923beee15e7SBen Langmuir   const FileEntry *ModuleMapFile = nullptr;
9249194a91dSDouglas Gregor   if (!Parent) {
9254ddf2221SDouglas Gregor     // Determine whether we're allowed to infer a module map.
9269194a91dSDouglas Gregor     bool canInfer = false;
9274ddf2221SDouglas Gregor     if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
9289194a91dSDouglas Gregor       // Figure out the parent path.
9294ddf2221SDouglas Gregor       StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
9309194a91dSDouglas Gregor       if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) {
9319194a91dSDouglas Gregor         // Check whether we have already looked into the parent directory
9329194a91dSDouglas Gregor         // for a module map.
933e4412640SArgyrios Kyrtzidis         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
9349194a91dSDouglas Gregor           inferred = InferredDirectories.find(ParentDir);
9359194a91dSDouglas Gregor         if (inferred == InferredDirectories.end()) {
9369194a91dSDouglas Gregor           // We haven't looked here before. Load a module map, if there is
9379194a91dSDouglas Gregor           // one.
938984e1df7SBen Langmuir           bool IsFrameworkDir = Parent.endswith(".framework");
939984e1df7SBen Langmuir           if (const FileEntry *ModMapFile =
940984e1df7SBen Langmuir                 HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) {
941c1d88ea5SBen Langmuir             parseModuleMapFile(ModMapFile, Attrs.IsSystem, ParentDir);
9429194a91dSDouglas Gregor             inferred = InferredDirectories.find(ParentDir);
9439194a91dSDouglas Gregor           }
9449194a91dSDouglas Gregor 
9459194a91dSDouglas Gregor           if (inferred == InferredDirectories.end())
9469194a91dSDouglas Gregor             inferred = InferredDirectories.insert(
9479194a91dSDouglas Gregor                          std::make_pair(ParentDir, InferredDirectory())).first;
9489194a91dSDouglas Gregor         }
9499194a91dSDouglas Gregor 
9509194a91dSDouglas Gregor         if (inferred->second.InferModules) {
9519194a91dSDouglas Gregor           // We're allowed to infer for this directory, but make sure it's okay
9529194a91dSDouglas Gregor           // to infer this particular module.
9534ddf2221SDouglas Gregor           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
9549194a91dSDouglas Gregor           canInfer = std::find(inferred->second.ExcludedModules.begin(),
9559194a91dSDouglas Gregor                                inferred->second.ExcludedModules.end(),
9569194a91dSDouglas Gregor                                Name) == inferred->second.ExcludedModules.end();
9579194a91dSDouglas Gregor 
958c1d88ea5SBen Langmuir           Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
959c1d88ea5SBen Langmuir           Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
960c1d88ea5SBen Langmuir           Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
961ed84df00SBruno Cardoso Lopes           Attrs.NoUndeclaredIncludes |=
962ed84df00SBruno Cardoso Lopes               inferred->second.Attrs.NoUndeclaredIncludes;
963beee15e7SBen Langmuir           ModuleMapFile = inferred->second.ModuleMapFile;
9649194a91dSDouglas Gregor         }
9659194a91dSDouglas Gregor       }
9669194a91dSDouglas Gregor     }
9679194a91dSDouglas Gregor 
9689194a91dSDouglas Gregor     // If we're not allowed to infer a framework module, don't.
9699194a91dSDouglas Gregor     if (!canInfer)
970d2d442caSCraig Topper       return nullptr;
971beee15e7SBen Langmuir   } else
9729d6448b1SBen Langmuir     ModuleMapFile = getModuleMapFileForUniquing(Parent);
9739194a91dSDouglas Gregor 
9749194a91dSDouglas Gregor 
97556c64013SDouglas Gregor   // Look for an umbrella header.
9762c1dd271SDylan Noblesmith   SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
97717381a06SBenjamin Kramer   llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
978e89dbc1dSDouglas Gregor   const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
97956c64013SDouglas Gregor 
98056c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
98156c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
98256c64013SDouglas Gregor   // idea.
98356c64013SDouglas Gregor   if (!UmbrellaHeader)
984d2d442caSCraig Topper     return nullptr;
98556c64013SDouglas Gregor 
9869d6448b1SBen Langmuir   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
987a7e2cc68SRichard Smith                               /*IsFramework=*/true, /*IsExplicit=*/false,
988a7e2cc68SRichard Smith                               NumCreatedModules++);
9899d6448b1SBen Langmuir   InferredModuleAllowedBy[Result] = ModuleMapFile;
9909d6448b1SBen Langmuir   Result->IsInferred = true;
9917e82e019SRichard Smith   if (!Parent) {
9927e82e019SRichard Smith     if (LangOpts.CurrentModule == ModuleName)
993ba7f2f71SDaniel Jasper       SourceModule = Result;
9947e82e019SRichard Smith     Modules[ModuleName] = Result;
995c192d194SBruno Cardoso Lopes     ModuleScopeIDs[Result] = CurrentModuleScopeID;
996ba7f2f71SDaniel Jasper   }
997c1d88ea5SBen Langmuir 
998c1d88ea5SBen Langmuir   Result->IsSystem |= Attrs.IsSystem;
999c1d88ea5SBen Langmuir   Result->IsExternC |= Attrs.IsExternC;
1000c1d88ea5SBen Langmuir   Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
1001ed84df00SBruno Cardoso Lopes   Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
10022b63d15fSRichard Smith   Result->Directory = FrameworkDir;
1003a686e1b0SDouglas Gregor 
1004322f633cSDouglas Gregor   // umbrella header "umbrella-header-name"
10052b63d15fSRichard Smith   //
10062b63d15fSRichard Smith   // The "Headers/" component of the name is implied because this is
10072b63d15fSRichard Smith   // a framework module.
10082b63d15fSRichard Smith   setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h");
1009d8bd7537SDouglas Gregor 
1010d8bd7537SDouglas Gregor   // export *
1011d2d442caSCraig Topper   Result->Exports.push_back(Module::ExportDecl(nullptr, true));
1012d8bd7537SDouglas Gregor 
1013a89c5ac4SDouglas Gregor   // module * { export * }
1014a89c5ac4SDouglas Gregor   Result->InferSubmodules = true;
1015a89c5ac4SDouglas Gregor   Result->InferExportWildcard = true;
1016a89c5ac4SDouglas Gregor 
1017e89dbc1dSDouglas Gregor   // Look for subframeworks.
1018c080917eSRafael Espindola   std::error_code EC;
10192c1dd271SDylan Noblesmith   SmallString<128> SubframeworksDirName
1020ddaa69cbSDouglas Gregor     = StringRef(FrameworkDir->getName());
1021e89dbc1dSDouglas Gregor   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
10222d4d8cb3SBenjamin Kramer   llvm::sys::path::native(SubframeworksDirName);
1023*fc51490bSJonas Devlieghere   llvm::vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
1024*fc51490bSJonas Devlieghere   for (llvm::vfs::directory_iterator
1025*fc51490bSJonas Devlieghere            Dir = FS.dir_begin(SubframeworksDirName, EC),
1026b171a59bSBruno Cardoso Lopes            DirEnd;
1027e89dbc1dSDouglas Gregor        Dir != DirEnd && !EC; Dir.increment(EC)) {
10280ae00567SSam McCall     if (!StringRef(Dir->path()).endswith(".framework"))
1029e89dbc1dSDouglas Gregor       continue;
1030f2161a70SDouglas Gregor 
1031b171a59bSBruno Cardoso Lopes     if (const DirectoryEntry *SubframeworkDir =
10320ae00567SSam McCall             FileMgr.getDirectory(Dir->path())) {
103307c22b78SDouglas Gregor       // Note: as an egregious but useful hack, we use the real path here and
103407c22b78SDouglas Gregor       // check whether it is actually a subdirectory of the parent directory.
103507c22b78SDouglas Gregor       // This will not be the case if the 'subframework' is actually a symlink
103607c22b78SDouglas Gregor       // out to a top-level framework.
1037e00c8b20SDouglas Gregor       StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir);
103807c22b78SDouglas Gregor       bool FoundParent = false;
103907c22b78SDouglas Gregor       do {
104007c22b78SDouglas Gregor         // Get the parent directory name.
104107c22b78SDouglas Gregor         SubframeworkDirName
104207c22b78SDouglas Gregor           = llvm::sys::path::parent_path(SubframeworkDirName);
104307c22b78SDouglas Gregor         if (SubframeworkDirName.empty())
104407c22b78SDouglas Gregor           break;
104507c22b78SDouglas Gregor 
104607c22b78SDouglas Gregor         if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) {
104707c22b78SDouglas Gregor           FoundParent = true;
104807c22b78SDouglas Gregor           break;
104907c22b78SDouglas Gregor         }
105007c22b78SDouglas Gregor       } while (true);
105107c22b78SDouglas Gregor 
105207c22b78SDouglas Gregor       if (!FoundParent)
105307c22b78SDouglas Gregor         continue;
105407c22b78SDouglas Gregor 
1055e89dbc1dSDouglas Gregor       // FIXME: Do we want to warn about subframeworks without umbrella headers?
1056a525400dSBen Langmuir       inferFrameworkModule(SubframeworkDir, Attrs, Result);
1057e89dbc1dSDouglas Gregor     }
1058e89dbc1dSDouglas Gregor   }
1059e89dbc1dSDouglas Gregor 
106011dfe6feSDouglas Gregor   // If the module is a top-level framework, automatically link against the
106111dfe6feSDouglas Gregor   // framework.
106211dfe6feSDouglas Gregor   if (!Result->isSubFramework()) {
106311dfe6feSDouglas Gregor     inferFrameworkLink(Result, FrameworkDir, FileMgr);
106411dfe6feSDouglas Gregor   }
106511dfe6feSDouglas Gregor 
106656c64013SDouglas Gregor   return Result;
106756c64013SDouglas Gregor }
106856c64013SDouglas Gregor 
10698587dfd9SBruno Cardoso Lopes Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
10708587dfd9SBruno Cardoso Lopes                                         Module *ShadowingModule) {
10718587dfd9SBruno Cardoso Lopes 
10728587dfd9SBruno Cardoso Lopes   // Create a new module with this name.
10738587dfd9SBruno Cardoso Lopes   Module *Result =
10748587dfd9SBruno Cardoso Lopes       new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
10758587dfd9SBruno Cardoso Lopes                  /*IsExplicit=*/false, NumCreatedModules++);
10768587dfd9SBruno Cardoso Lopes   Result->ShadowingModule = ShadowingModule;
10778587dfd9SBruno Cardoso Lopes   Result->IsAvailable = false;
1078c192d194SBruno Cardoso Lopes   ModuleScopeIDs[Result] = CurrentModuleScopeID;
10798587dfd9SBruno Cardoso Lopes   ShadowModules.push_back(Result);
10808587dfd9SBruno Cardoso Lopes 
10818587dfd9SBruno Cardoso Lopes   return Result;
10828587dfd9SBruno Cardoso Lopes }
10838587dfd9SBruno Cardoso Lopes 
10842b63d15fSRichard Smith void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
10852b63d15fSRichard Smith                                   Twine NameAsWritten) {
108697da9178SDaniel Jasper   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
108773141fa9SDouglas Gregor   Mod->Umbrella = UmbrellaHeader;
10882b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
10897033127bSDouglas Gregor   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
1090b3a0fa48SBruno Cardoso Lopes 
1091b3a0fa48SBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1092b3a0fa48SBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1093b3a0fa48SBruno Cardoso Lopes     Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
1094a89c5ac4SDouglas Gregor }
1095a89c5ac4SDouglas Gregor 
10962b63d15fSRichard Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
10972b63d15fSRichard Smith                                Twine NameAsWritten) {
1098524e33e1SDouglas Gregor   Mod->Umbrella = UmbrellaDir;
10992b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
1100524e33e1SDouglas Gregor   UmbrellaDirs[UmbrellaDir] = Mod;
1101524e33e1SDouglas Gregor }
1102524e33e1SDouglas Gregor 
1103040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod,
11049f6020bcSBruno Cardoso Lopes                                     Module::UnresolvedHeaderDirective Header,
11059f6020bcSBruno Cardoso Lopes                                     bool &NeedsFramework) {
1106040e1266SRichard Smith   // If there is a builtin counterpart to this file, add it now so it can
1107040e1266SRichard Smith   // wrap the system header.
1108040e1266SRichard Smith   if (resolveAsBuiltinHeader(Mod, Header)) {
1109040e1266SRichard Smith     // If we have both a builtin and system version of the file, the
1110040e1266SRichard Smith     // builtin version may want to inject macros into the system header, so
1111040e1266SRichard Smith     // force the system header to be treated as a textual header in this
1112040e1266SRichard Smith     // case.
1113040e1266SRichard Smith     Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
1114040e1266SRichard Smith         headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
1115040e1266SRichard Smith     Header.HasBuiltinHeader = true;
11163c1a41adSRichard Smith   }
1117040e1266SRichard Smith 
1118040e1266SRichard Smith   // If possible, don't stat the header until we need to. This requires the
1119040e1266SRichard Smith   // user to have provided us with some stat information about the file.
1120040e1266SRichard Smith   // FIXME: Add support for lazily stat'ing umbrella headers and excluded
1121040e1266SRichard Smith   // headers.
1122040e1266SRichard Smith   if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
1123040e1266SRichard Smith       Header.Kind != Module::HK_Excluded) {
1124040e1266SRichard Smith     // We expect more variation in mtime than size, so if we're given both,
1125040e1266SRichard Smith     // use the mtime as the key.
1126040e1266SRichard Smith     if (Header.ModTime)
1127040e1266SRichard Smith       LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
1128040e1266SRichard Smith     else
1129040e1266SRichard Smith       LazyHeadersBySize[*Header.Size].push_back(Mod);
1130040e1266SRichard Smith     Mod->UnresolvedHeaders.push_back(Header);
1131040e1266SRichard Smith     return;
1132040e1266SRichard Smith   }
1133040e1266SRichard Smith 
1134040e1266SRichard Smith   // We don't have stat information or can't defer looking this file up.
1135040e1266SRichard Smith   // Perform the lookup now.
11369f6020bcSBruno Cardoso Lopes   resolveHeader(Mod, Header, NeedsFramework);
1137040e1266SRichard Smith }
1138040e1266SRichard Smith 
1139040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
1140040e1266SRichard Smith   auto BySize = LazyHeadersBySize.find(File->getSize());
1141040e1266SRichard Smith   if (BySize != LazyHeadersBySize.end()) {
1142040e1266SRichard Smith     for (auto *M : BySize->second)
1143040e1266SRichard Smith       resolveHeaderDirectives(M);
1144040e1266SRichard Smith     LazyHeadersBySize.erase(BySize);
1145040e1266SRichard Smith   }
1146040e1266SRichard Smith 
1147040e1266SRichard Smith   auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
1148040e1266SRichard Smith   if (ByModTime != LazyHeadersByModTime.end()) {
1149040e1266SRichard Smith     for (auto *M : ByModTime->second)
1150040e1266SRichard Smith       resolveHeaderDirectives(M);
1151040e1266SRichard Smith     LazyHeadersByModTime.erase(ByModTime);
1152040e1266SRichard Smith   }
1153040e1266SRichard Smith }
1154040e1266SRichard Smith 
1155040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(Module *Mod) const {
11569f6020bcSBruno Cardoso Lopes   bool NeedsFramework = false;
1157040e1266SRichard Smith   for (auto &Header : Mod->UnresolvedHeaders)
1158040e1266SRichard Smith     // This operation is logically const; we're just changing how we represent
1159040e1266SRichard Smith     // the header information for this file.
11609f6020bcSBruno Cardoso Lopes     const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework);
1161040e1266SRichard Smith   Mod->UnresolvedHeaders.clear();
11620e98d938SNAKAMURA Takumi }
1163202210b3SRichard Smith 
11643c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header,
1165d8879c85SRichard Smith                           ModuleHeaderRole Role, bool Imported) {
1166386bb073SRichard Smith   KnownHeader KH(Mod, Role);
11673c1a41adSRichard Smith 
1168386bb073SRichard Smith   // Only add each header to the headers list once.
1169386bb073SRichard Smith   // FIXME: Should we diagnose if a header is listed twice in the
1170386bb073SRichard Smith   // same module definition?
1171386bb073SRichard Smith   auto &HeaderList = Headers[Header.Entry];
1172386bb073SRichard Smith   for (auto H : HeaderList)
1173386bb073SRichard Smith     if (H == KH)
1174386bb073SRichard Smith       return;
1175386bb073SRichard Smith 
1176386bb073SRichard Smith   HeaderList.push_back(KH);
11771ec383c7SPiotr Padlewski   Mod->Headers[headerRoleToKind(Role)].push_back(Header);
1178386bb073SRichard Smith 
11797e82e019SRichard Smith   bool isCompilingModuleHeader =
1180bbcc9f04SRichard Smith       LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
1181d8879c85SRichard Smith   if (!Imported || isCompilingModuleHeader) {
1182d8879c85SRichard Smith     // When we import HeaderFileInfo, the external source is expected to
1183d8879c85SRichard Smith     // set the isModuleHeader flag itself.
1184d8879c85SRichard Smith     HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
1185d8879c85SRichard Smith                                     isCompilingModuleHeader);
1186d8879c85SRichard Smith   }
1187e62cfd7cSBruno Cardoso Lopes 
1188e62cfd7cSBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1189e62cfd7cSBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1190f0841790SBruno Cardoso Lopes     Cb->moduleMapAddHeader(Header.Entry->getName());
1191a89c5ac4SDouglas Gregor }
1192a89c5ac4SDouglas Gregor 
11933c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
1194feb54b6dSRichard Smith   // Add this as a known header so we won't implicitly add it to any
1195feb54b6dSRichard Smith   // umbrella directory module.
1196feb54b6dSRichard Smith   // FIXME: Should we only exclude it from umbrella modules within the
1197feb54b6dSRichard Smith   // specified module?
11983c1a41adSRichard Smith   (void) Headers[Header.Entry];
11993c1a41adSRichard Smith 
12003c1a41adSRichard Smith   Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
1201feb54b6dSRichard Smith }
1202feb54b6dSRichard Smith 
1203514b636aSDouglas Gregor const FileEntry *
12044b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const {
12051f76c4e8SManuel Klimek   if (Module->DefinitionLoc.isInvalid())
1206d2d442caSCraig Topper     return nullptr;
1207514b636aSDouglas Gregor 
12081f76c4e8SManuel Klimek   return SourceMgr.getFileEntryForID(
12091f76c4e8SManuel Klimek            SourceMgr.getFileID(Module->DefinitionLoc));
1210514b636aSDouglas Gregor }
1211514b636aSDouglas Gregor 
12124b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
12139d6448b1SBen Langmuir   if (M->IsInferred) {
12149d6448b1SBen Langmuir     assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
12159d6448b1SBen Langmuir     return InferredModuleAllowedBy.find(M)->second;
12169d6448b1SBen Langmuir   }
12179d6448b1SBen Langmuir   return getContainingModuleMapFile(M);
12189d6448b1SBen Langmuir }
12199d6448b1SBen Langmuir 
12209d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
12219d6448b1SBen Langmuir   assert(M->IsInferred && "module not inferred");
12229d6448b1SBen Langmuir   InferredModuleAllowedBy[M] = ModMap;
12239d6448b1SBen Langmuir }
12249d6448b1SBen Langmuir 
1225cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() {
1226718292f2SDouglas Gregor   llvm::errs() << "Modules:";
1227718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1228718292f2SDouglas Gregor                                         MEnd = Modules.end();
1229718292f2SDouglas Gregor        M != MEnd; ++M)
1230d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
1231718292f2SDouglas Gregor 
1232718292f2SDouglas Gregor   llvm::errs() << "Headers:";
123359527666SDouglas Gregor   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1234718292f2SDouglas Gregor        H != HEnd; ++H) {
123597da9178SDaniel Jasper     llvm::errs() << "  \"" << H->first->getName() << "\" -> ";
123697da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
123797da9178SDaniel Jasper                                                       E = H->second.end();
123897da9178SDaniel Jasper          I != E; ++I) {
123997da9178SDaniel Jasper       if (I != H->second.begin())
124097da9178SDaniel Jasper         llvm::errs() << ",";
124197da9178SDaniel Jasper       llvm::errs() << I->getModule()->getFullModuleName();
124297da9178SDaniel Jasper     }
124397da9178SDaniel Jasper     llvm::errs() << "\n";
1244718292f2SDouglas Gregor   }
1245718292f2SDouglas Gregor }
1246718292f2SDouglas Gregor 
12472b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
124842413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedExports);
124942413141SRichard Smith   Mod->UnresolvedExports.clear();
125042413141SRichard Smith   for (auto &UE : Unresolved) {
125142413141SRichard Smith     Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
1252f5eedd05SDouglas Gregor     if (Export.getPointer() || Export.getInt())
12532b82c2a5SDouglas Gregor       Mod->Exports.push_back(Export);
12542b82c2a5SDouglas Gregor     else
125542413141SRichard Smith       Mod->UnresolvedExports.push_back(UE);
12562b82c2a5SDouglas Gregor   }
125742413141SRichard Smith   return !Mod->UnresolvedExports.empty();
12582b82c2a5SDouglas Gregor }
12592b82c2a5SDouglas Gregor 
1260ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
126142413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedDirectUses);
126242413141SRichard Smith   Mod->UnresolvedDirectUses.clear();
126342413141SRichard Smith   for (auto &UDU : Unresolved) {
126442413141SRichard Smith     Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
1265ba7f2f71SDaniel Jasper     if (DirectUse)
1266ba7f2f71SDaniel Jasper       Mod->DirectUses.push_back(DirectUse);
1267ba7f2f71SDaniel Jasper     else
126842413141SRichard Smith       Mod->UnresolvedDirectUses.push_back(UDU);
1269ba7f2f71SDaniel Jasper   }
127042413141SRichard Smith   return !Mod->UnresolvedDirectUses.empty();
1271ba7f2f71SDaniel Jasper }
1272ba7f2f71SDaniel Jasper 
1273fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
127442413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedConflicts);
127542413141SRichard Smith   Mod->UnresolvedConflicts.clear();
127642413141SRichard Smith   for (auto &UC : Unresolved) {
127742413141SRichard Smith     if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1278fb912657SDouglas Gregor       Module::Conflict Conflict;
1279fb912657SDouglas Gregor       Conflict.Other = OtherMod;
128042413141SRichard Smith       Conflict.Message = UC.Message;
1281fb912657SDouglas Gregor       Mod->Conflicts.push_back(Conflict);
128242413141SRichard Smith     } else
128342413141SRichard Smith       Mod->UnresolvedConflicts.push_back(UC);
1284fb912657SDouglas Gregor   }
128542413141SRichard Smith   return !Mod->UnresolvedConflicts.empty();
1286fb912657SDouglas Gregor }
1287fb912657SDouglas Gregor 
1288718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1289718292f2SDouglas Gregor // Module map file parser
1290718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1291718292f2SDouglas Gregor 
1292718292f2SDouglas Gregor namespace clang {
1293afd1b1c9SEugene Zelenko 
12949fc8faf9SAdrian Prantl   /// A token in a module map file.
1295718292f2SDouglas Gregor   struct MMToken {
1296718292f2SDouglas Gregor     enum TokenKind {
12971fb5c3a6SDouglas Gregor       Comma,
129835b13eceSDouglas Gregor       ConfigMacros,
1299fb912657SDouglas Gregor       Conflict,
1300718292f2SDouglas Gregor       EndOfFile,
1301718292f2SDouglas Gregor       HeaderKeyword,
1302718292f2SDouglas Gregor       Identifier,
1303a3feee2aSRichard Smith       Exclaim,
130459527666SDouglas Gregor       ExcludeKeyword,
1305718292f2SDouglas Gregor       ExplicitKeyword,
13062b82c2a5SDouglas Gregor       ExportKeyword,
1307f0b11de2SDouglas Gregor       ExportAsKeyword,
130897292843SDaniel Jasper       ExternKeyword,
1309755b2055SDouglas Gregor       FrameworkKeyword,
13106ddfca91SDouglas Gregor       LinkKeyword,
1311718292f2SDouglas Gregor       ModuleKeyword,
13122b82c2a5SDouglas Gregor       Period,
1313b53e5483SLawrence Crowl       PrivateKeyword,
1314718292f2SDouglas Gregor       UmbrellaKeyword,
1315ba7f2f71SDaniel Jasper       UseKeyword,
13161fb5c3a6SDouglas Gregor       RequiresKeyword,
13172b82c2a5SDouglas Gregor       Star,
1318718292f2SDouglas Gregor       StringLiteral,
1319040e1266SRichard Smith       IntegerLiteral,
1320306d8920SRichard Smith       TextualKeyword,
1321718292f2SDouglas Gregor       LBrace,
1322a686e1b0SDouglas Gregor       RBrace,
1323a686e1b0SDouglas Gregor       LSquare,
1324a686e1b0SDouglas Gregor       RSquare
1325718292f2SDouglas Gregor     } Kind;
1326718292f2SDouglas Gregor 
1327718292f2SDouglas Gregor     unsigned Location;
1328718292f2SDouglas Gregor     unsigned StringLength;
1329040e1266SRichard Smith     union {
1330040e1266SRichard Smith       // If Kind != IntegerLiteral.
1331718292f2SDouglas Gregor       const char *StringData;
1332afd1b1c9SEugene Zelenko 
1333040e1266SRichard Smith       // If Kind == IntegerLiteral.
1334040e1266SRichard Smith       uint64_t IntegerValue;
1335040e1266SRichard Smith     };
1336718292f2SDouglas Gregor 
1337718292f2SDouglas Gregor     void clear() {
1338718292f2SDouglas Gregor       Kind = EndOfFile;
1339718292f2SDouglas Gregor       Location = 0;
1340718292f2SDouglas Gregor       StringLength = 0;
1341d2d442caSCraig Topper       StringData = nullptr;
1342718292f2SDouglas Gregor     }
1343718292f2SDouglas Gregor 
1344718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
1345718292f2SDouglas Gregor 
1346718292f2SDouglas Gregor     SourceLocation getLocation() const {
1347718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
1348718292f2SDouglas Gregor     }
1349718292f2SDouglas Gregor 
1350040e1266SRichard Smith     uint64_t getInteger() const {
1351040e1266SRichard Smith       return Kind == IntegerLiteral ? IntegerValue : 0;
1352040e1266SRichard Smith     }
1353040e1266SRichard Smith 
1354718292f2SDouglas Gregor     StringRef getString() const {
1355040e1266SRichard Smith       return Kind == IntegerLiteral ? StringRef()
1356040e1266SRichard Smith                                     : StringRef(StringData, StringLength);
1357718292f2SDouglas Gregor     }
1358718292f2SDouglas Gregor   };
1359718292f2SDouglas Gregor 
1360718292f2SDouglas Gregor   class ModuleMapParser {
1361718292f2SDouglas Gregor     Lexer &L;
1362718292f2SDouglas Gregor     SourceManager &SourceMgr;
1363bc10b9fbSDouglas Gregor 
13649fc8faf9SAdrian Prantl     /// Default target information, used only for string literal
1365bc10b9fbSDouglas Gregor     /// parsing.
1366bc10b9fbSDouglas Gregor     const TargetInfo *Target;
1367bc10b9fbSDouglas Gregor 
1368718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
1369718292f2SDouglas Gregor     ModuleMap &Map;
1370718292f2SDouglas Gregor 
13719fc8faf9SAdrian Prantl     /// The current module map file.
1372beee15e7SBen Langmuir     const FileEntry *ModuleMapFile;
1373beee15e7SBen Langmuir 
13749f6020bcSBruno Cardoso Lopes     /// Source location of most recent parsed module declaration
13759f6020bcSBruno Cardoso Lopes     SourceLocation CurrModuleDeclLoc;
13769f6020bcSBruno Cardoso Lopes 
13779fc8faf9SAdrian Prantl     /// The directory that file names in this module map file should
13789acb99e3SRichard Smith     /// be resolved relative to.
13795257fc63SDouglas Gregor     const DirectoryEntry *Directory;
13805257fc63SDouglas Gregor 
13819fc8faf9SAdrian Prantl     /// Whether this module map is in a system header directory.
1382963c5535SDouglas Gregor     bool IsSystem;
1383963c5535SDouglas Gregor 
13849fc8faf9SAdrian Prantl     /// Whether an error occurred.
1385afd1b1c9SEugene Zelenko     bool HadError = false;
1386718292f2SDouglas Gregor 
13879fc8faf9SAdrian Prantl     /// Stores string data for the various string literals referenced
1388718292f2SDouglas Gregor     /// during parsing.
1389718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
1390718292f2SDouglas Gregor 
13919fc8faf9SAdrian Prantl     /// The current token.
1392718292f2SDouglas Gregor     MMToken Tok;
1393718292f2SDouglas Gregor 
13949fc8faf9SAdrian Prantl     /// The active module.
1395afd1b1c9SEugene Zelenko     Module *ActiveModule = nullptr;
1396718292f2SDouglas Gregor 
13979fc8faf9SAdrian Prantl     /// Whether a module uses the 'requires excluded' hack to mark its
13987ff29148SBen Langmuir     /// contents as 'textual'.
13997ff29148SBen Langmuir     ///
14007ff29148SBen Langmuir     /// On older Darwin SDK versions, 'requires excluded' is used to mark the
14017ff29148SBen Langmuir     /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
14027ff29148SBen Langmuir     /// non-modular headers.  For backwards compatibility, we continue to
14037ff29148SBen Langmuir     /// support this idiom for just these modules, and map the headers to
14047ff29148SBen Langmuir     /// 'textual' to match the original intent.
14057ff29148SBen Langmuir     llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
14067ff29148SBen Langmuir 
14079fc8faf9SAdrian Prantl     /// Consume the current token and return its location.
1408718292f2SDouglas Gregor     SourceLocation consumeToken();
1409718292f2SDouglas Gregor 
14109fc8faf9SAdrian Prantl     /// Skip tokens until we reach the a token with the given kind
1411718292f2SDouglas Gregor     /// (or the end of the file).
1412718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
1413718292f2SDouglas Gregor 
1414afd1b1c9SEugene Zelenko     using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
1415afd1b1c9SEugene Zelenko 
1416e7ab3669SDouglas Gregor     bool parseModuleId(ModuleId &Id);
1417718292f2SDouglas Gregor     void parseModuleDecl();
141897292843SDaniel Jasper     void parseExternModuleDecl();
14191fb5c3a6SDouglas Gregor     void parseRequiresDecl();
1420afd1b1c9SEugene Zelenko     void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
1421524e33e1SDouglas Gregor     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
14222b82c2a5SDouglas Gregor     void parseExportDecl();
1423f0b11de2SDouglas Gregor     void parseExportAsDecl();
1424ba7f2f71SDaniel Jasper     void parseUseDecl();
14256ddfca91SDouglas Gregor     void parseLinkDecl();
142635b13eceSDouglas Gregor     void parseConfigMacros();
1427fb912657SDouglas Gregor     void parseConflict();
14289194a91dSDouglas Gregor     void parseInferredModuleDecl(bool Framework, bool Explicit);
1429c1d88ea5SBen Langmuir 
14305f11e128SBruno Cardoso Lopes     /// Private modules are canonicalized as Foo_Private. Clang provides extra
14315f11e128SBruno Cardoso Lopes     /// module map search logic to find the appropriate private module when PCH
14325f11e128SBruno Cardoso Lopes     /// is used with implicit module maps. Warn when private modules are written
14335f11e128SBruno Cardoso Lopes     /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
14345f11e128SBruno Cardoso Lopes     void diagnosePrivateModules(SourceLocation ExplicitLoc,
14355f11e128SBruno Cardoso Lopes                                 SourceLocation FrameworkLoc);
14365f11e128SBruno Cardoso Lopes 
1437afd1b1c9SEugene Zelenko     using Attributes = ModuleMap::Attributes;
1438afd1b1c9SEugene Zelenko 
14394442605fSBill Wendling     bool parseOptionalAttributes(Attributes &Attrs);
1440718292f2SDouglas Gregor 
1441718292f2SDouglas Gregor   public:
1442718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
14438587dfd9SBruno Cardoso Lopes                              const TargetInfo *Target, DiagnosticsEngine &Diags,
14448587dfd9SBruno Cardoso Lopes                              ModuleMap &Map, const FileEntry *ModuleMapFile,
1445c192d194SBruno Cardoso Lopes                              const DirectoryEntry *Directory, bool IsSystem)
1446bc10b9fbSDouglas Gregor         : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
1447beee15e7SBen Langmuir           ModuleMapFile(ModuleMapFile), Directory(Directory),
1448c192d194SBruno Cardoso Lopes           IsSystem(IsSystem) {
1449718292f2SDouglas Gregor       Tok.clear();
1450718292f2SDouglas Gregor       consumeToken();
1451718292f2SDouglas Gregor     }
1452718292f2SDouglas Gregor 
1453718292f2SDouglas Gregor     bool parseModuleMapFile();
14548128f332SRichard Smith 
14558128f332SRichard Smith     bool terminatedByDirective() { return false; }
14568128f332SRichard Smith     SourceLocation getLocation() { return Tok.getLocation(); }
1457718292f2SDouglas Gregor   };
1458afd1b1c9SEugene Zelenko 
1459afd1b1c9SEugene Zelenko } // namespace clang
1460718292f2SDouglas Gregor 
1461718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
1462718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
1463718292f2SDouglas Gregor 
14648128f332SRichard Smith retry:
14658128f332SRichard Smith   Tok.clear();
1466718292f2SDouglas Gregor   Token LToken;
1467718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
1468718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
1469718292f2SDouglas Gregor   switch (LToken.getKind()) {
14702d57cea2SAlp Toker   case tok::raw_identifier: {
14712d57cea2SAlp Toker     StringRef RI = LToken.getRawIdentifier();
14722d57cea2SAlp Toker     Tok.StringData = RI.data();
14732d57cea2SAlp Toker     Tok.StringLength = RI.size();
14742d57cea2SAlp Toker     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
147535b13eceSDouglas Gregor                  .Case("config_macros", MMToken::ConfigMacros)
1476fb912657SDouglas Gregor                  .Case("conflict", MMToken::Conflict)
147759527666SDouglas Gregor                  .Case("exclude", MMToken::ExcludeKeyword)
1478718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
14792b82c2a5SDouglas Gregor                  .Case("export", MMToken::ExportKeyword)
1480f0b11de2SDouglas Gregor                  .Case("export_as", MMToken::ExportAsKeyword)
148197292843SDaniel Jasper                  .Case("extern", MMToken::ExternKeyword)
1482755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
148335b13eceSDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
14846ddfca91SDouglas Gregor                  .Case("link", MMToken::LinkKeyword)
1485718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
1486b53e5483SLawrence Crowl                  .Case("private", MMToken::PrivateKeyword)
14871fb5c3a6SDouglas Gregor                  .Case("requires", MMToken::RequiresKeyword)
1488306d8920SRichard Smith                  .Case("textual", MMToken::TextualKeyword)
1489718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
1490ba7f2f71SDaniel Jasper                  .Case("use", MMToken::UseKeyword)
1491718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
1492718292f2SDouglas Gregor     break;
14932d57cea2SAlp Toker   }
1494718292f2SDouglas Gregor 
14951fb5c3a6SDouglas Gregor   case tok::comma:
14961fb5c3a6SDouglas Gregor     Tok.Kind = MMToken::Comma;
14971fb5c3a6SDouglas Gregor     break;
14981fb5c3a6SDouglas Gregor 
1499718292f2SDouglas Gregor   case tok::eof:
1500718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
1501718292f2SDouglas Gregor     break;
1502718292f2SDouglas Gregor 
1503718292f2SDouglas Gregor   case tok::l_brace:
1504718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
1505718292f2SDouglas Gregor     break;
1506718292f2SDouglas Gregor 
1507a686e1b0SDouglas Gregor   case tok::l_square:
1508a686e1b0SDouglas Gregor     Tok.Kind = MMToken::LSquare;
1509a686e1b0SDouglas Gregor     break;
1510a686e1b0SDouglas Gregor 
15112b82c2a5SDouglas Gregor   case tok::period:
15122b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Period;
15132b82c2a5SDouglas Gregor     break;
15142b82c2a5SDouglas Gregor 
1515718292f2SDouglas Gregor   case tok::r_brace:
1516718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
1517718292f2SDouglas Gregor     break;
1518718292f2SDouglas Gregor 
1519a686e1b0SDouglas Gregor   case tok::r_square:
1520a686e1b0SDouglas Gregor     Tok.Kind = MMToken::RSquare;
1521a686e1b0SDouglas Gregor     break;
1522a686e1b0SDouglas Gregor 
15232b82c2a5SDouglas Gregor   case tok::star:
15242b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Star;
15252b82c2a5SDouglas Gregor     break;
15262b82c2a5SDouglas Gregor 
1527a3feee2aSRichard Smith   case tok::exclaim:
1528a3feee2aSRichard Smith     Tok.Kind = MMToken::Exclaim;
1529a3feee2aSRichard Smith     break;
1530a3feee2aSRichard Smith 
1531718292f2SDouglas Gregor   case tok::string_literal: {
1532d67aea28SRichard Smith     if (LToken.hasUDSuffix()) {
1533d67aea28SRichard Smith       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
1534d67aea28SRichard Smith       HadError = true;
1535d67aea28SRichard Smith       goto retry;
1536d67aea28SRichard Smith     }
1537d67aea28SRichard Smith 
1538718292f2SDouglas Gregor     // Parse the string literal.
1539718292f2SDouglas Gregor     LangOptions LangOpts;
15409d5583efSCraig Topper     StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
1541718292f2SDouglas Gregor     if (StringLiteral.hadError)
1542718292f2SDouglas Gregor       goto retry;
1543718292f2SDouglas Gregor 
1544718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
1545718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
1546718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
1547718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
1548718292f2SDouglas Gregor     Saved[Length] = 0;
1549718292f2SDouglas Gregor 
1550718292f2SDouglas Gregor     // Form the token.
1551718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
1552718292f2SDouglas Gregor     Tok.StringData = Saved;
1553718292f2SDouglas Gregor     Tok.StringLength = Length;
1554718292f2SDouglas Gregor     break;
1555718292f2SDouglas Gregor   }
1556718292f2SDouglas Gregor 
1557040e1266SRichard Smith   case tok::numeric_constant: {
1558040e1266SRichard Smith     // We don't support any suffixes or other complications.
1559040e1266SRichard Smith     SmallString<32> SpellingBuffer;
1560040e1266SRichard Smith     SpellingBuffer.resize(LToken.getLength() + 1);
1561040e1266SRichard Smith     const char *Start = SpellingBuffer.data();
1562040e1266SRichard Smith     unsigned Length =
1563040e1266SRichard Smith         Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts());
1564040e1266SRichard Smith     uint64_t Value;
1565040e1266SRichard Smith     if (StringRef(Start, Length).getAsInteger(0, Value)) {
1566040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1567040e1266SRichard Smith       HadError = true;
1568040e1266SRichard Smith       goto retry;
1569040e1266SRichard Smith     }
1570040e1266SRichard Smith 
1571040e1266SRichard Smith     Tok.Kind = MMToken::IntegerLiteral;
1572040e1266SRichard Smith     Tok.IntegerValue = Value;
1573040e1266SRichard Smith     break;
1574040e1266SRichard Smith   }
1575040e1266SRichard Smith 
1576718292f2SDouglas Gregor   case tok::comment:
1577718292f2SDouglas Gregor     goto retry;
1578718292f2SDouglas Gregor 
15798128f332SRichard Smith   case tok::hash:
15808128f332SRichard Smith     // A module map can be terminated prematurely by
15818128f332SRichard Smith     //   #pragma clang module contents
15828128f332SRichard Smith     // When building the module, we'll treat the rest of the file as the
15838128f332SRichard Smith     // contents of the module.
15848128f332SRichard Smith     {
15858128f332SRichard Smith       auto NextIsIdent = [&](StringRef Str) -> bool {
15868128f332SRichard Smith         L.LexFromRawLexer(LToken);
15878128f332SRichard Smith         return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
15888128f332SRichard Smith                LToken.getRawIdentifier() == Str;
15898128f332SRichard Smith       };
15908128f332SRichard Smith       if (NextIsIdent("pragma") && NextIsIdent("clang") &&
15918128f332SRichard Smith           NextIsIdent("module") && NextIsIdent("contents")) {
15928128f332SRichard Smith         Tok.Kind = MMToken::EndOfFile;
15938128f332SRichard Smith         break;
15948128f332SRichard Smith       }
15958128f332SRichard Smith     }
15968128f332SRichard Smith     LLVM_FALLTHROUGH;
15978128f332SRichard Smith 
1598718292f2SDouglas Gregor   default:
15998128f332SRichard Smith     Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1600718292f2SDouglas Gregor     HadError = true;
1601718292f2SDouglas Gregor     goto retry;
1602718292f2SDouglas Gregor   }
1603718292f2SDouglas Gregor 
1604718292f2SDouglas Gregor   return Result;
1605718292f2SDouglas Gregor }
1606718292f2SDouglas Gregor 
1607718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
1608718292f2SDouglas Gregor   unsigned braceDepth = 0;
1609a686e1b0SDouglas Gregor   unsigned squareDepth = 0;
1610718292f2SDouglas Gregor   do {
1611718292f2SDouglas Gregor     switch (Tok.Kind) {
1612718292f2SDouglas Gregor     case MMToken::EndOfFile:
1613718292f2SDouglas Gregor       return;
1614718292f2SDouglas Gregor 
1615718292f2SDouglas Gregor     case MMToken::LBrace:
1616a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1617718292f2SDouglas Gregor         return;
1618718292f2SDouglas Gregor 
1619718292f2SDouglas Gregor       ++braceDepth;
1620718292f2SDouglas Gregor       break;
1621718292f2SDouglas Gregor 
1622a686e1b0SDouglas Gregor     case MMToken::LSquare:
1623a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1624a686e1b0SDouglas Gregor         return;
1625a686e1b0SDouglas Gregor 
1626a686e1b0SDouglas Gregor       ++squareDepth;
1627a686e1b0SDouglas Gregor       break;
1628a686e1b0SDouglas Gregor 
1629718292f2SDouglas Gregor     case MMToken::RBrace:
1630718292f2SDouglas Gregor       if (braceDepth > 0)
1631718292f2SDouglas Gregor         --braceDepth;
1632718292f2SDouglas Gregor       else if (Tok.is(K))
1633718292f2SDouglas Gregor         return;
1634718292f2SDouglas Gregor       break;
1635718292f2SDouglas Gregor 
1636a686e1b0SDouglas Gregor     case MMToken::RSquare:
1637a686e1b0SDouglas Gregor       if (squareDepth > 0)
1638a686e1b0SDouglas Gregor         --squareDepth;
1639a686e1b0SDouglas Gregor       else if (Tok.is(K))
1640a686e1b0SDouglas Gregor         return;
1641a686e1b0SDouglas Gregor       break;
1642a686e1b0SDouglas Gregor 
1643718292f2SDouglas Gregor     default:
1644a686e1b0SDouglas Gregor       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
1645718292f2SDouglas Gregor         return;
1646718292f2SDouglas Gregor       break;
1647718292f2SDouglas Gregor     }
1648718292f2SDouglas Gregor 
1649718292f2SDouglas Gregor    consumeToken();
1650718292f2SDouglas Gregor   } while (true);
1651718292f2SDouglas Gregor }
1652718292f2SDouglas Gregor 
16539fc8faf9SAdrian Prantl /// Parse a module-id.
1654e7ab3669SDouglas Gregor ///
1655e7ab3669SDouglas Gregor ///   module-id:
1656e7ab3669SDouglas Gregor ///     identifier
1657e7ab3669SDouglas Gregor ///     identifier '.' module-id
1658e7ab3669SDouglas Gregor ///
1659e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise.
1660e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) {
1661e7ab3669SDouglas Gregor   Id.clear();
1662e7ab3669SDouglas Gregor   do {
16633cd34c76SDaniel Jasper     if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1664e7ab3669SDouglas Gregor       Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
1665e7ab3669SDouglas Gregor       consumeToken();
1666e7ab3669SDouglas Gregor     } else {
1667e7ab3669SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1668e7ab3669SDouglas Gregor       return true;
1669e7ab3669SDouglas Gregor     }
1670e7ab3669SDouglas Gregor 
1671e7ab3669SDouglas Gregor     if (!Tok.is(MMToken::Period))
1672e7ab3669SDouglas Gregor       break;
1673e7ab3669SDouglas Gregor 
1674e7ab3669SDouglas Gregor     consumeToken();
1675e7ab3669SDouglas Gregor   } while (true);
1676e7ab3669SDouglas Gregor 
1677e7ab3669SDouglas Gregor   return false;
1678e7ab3669SDouglas Gregor }
1679e7ab3669SDouglas Gregor 
1680a686e1b0SDouglas Gregor namespace {
1681afd1b1c9SEugene Zelenko 
16829fc8faf9SAdrian Prantl   /// Enumerates the known attributes.
1683a686e1b0SDouglas Gregor   enum AttributeKind {
16849fc8faf9SAdrian Prantl     /// An unknown attribute.
1685a686e1b0SDouglas Gregor     AT_unknown,
1686afd1b1c9SEugene Zelenko 
16879fc8faf9SAdrian Prantl     /// The 'system' attribute.
168835b13eceSDouglas Gregor     AT_system,
1689afd1b1c9SEugene Zelenko 
16909fc8faf9SAdrian Prantl     /// The 'extern_c' attribute.
169177944868SRichard Smith     AT_extern_c,
1692afd1b1c9SEugene Zelenko 
16939fc8faf9SAdrian Prantl     /// The 'exhaustive' attribute.
1694ed84df00SBruno Cardoso Lopes     AT_exhaustive,
1695afd1b1c9SEugene Zelenko 
16969fc8faf9SAdrian Prantl     /// The 'no_undeclared_includes' attribute.
1697ed84df00SBruno Cardoso Lopes     AT_no_undeclared_includes
1698a686e1b0SDouglas Gregor   };
1699afd1b1c9SEugene Zelenko 
1700afd1b1c9SEugene Zelenko } // namespace
1701a686e1b0SDouglas Gregor 
170229729919SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra
170329729919SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH
170429729919SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written
170529729919SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
17065f11e128SBruno Cardoso Lopes void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
17075f11e128SBruno Cardoso Lopes                                              SourceLocation FrameworkLoc) {
170829729919SBruno Cardoso Lopes   auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
17097d29486dSBruno Cardoso Lopes                              const Module *M, SourceRange ReplLoc) {
171029729919SBruno Cardoso Lopes     auto D = Diags.Report(ActiveModule->DefinitionLoc,
171129729919SBruno Cardoso Lopes                           diag::note_mmap_rename_top_level_private_module);
171229729919SBruno Cardoso Lopes     D << BadName << M->Name;
17137d29486dSBruno Cardoso Lopes     D << FixItHint::CreateReplacement(ReplLoc, Canonical);
171429729919SBruno Cardoso Lopes   };
171529729919SBruno Cardoso Lopes 
171629729919SBruno Cardoso Lopes   for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
171729729919SBruno Cardoso Lopes     auto const *M = E->getValue();
171829729919SBruno Cardoso Lopes     if (M->Directory != ActiveModule->Directory)
171929729919SBruno Cardoso Lopes       continue;
172029729919SBruno Cardoso Lopes 
172129729919SBruno Cardoso Lopes     SmallString<128> FullName(ActiveModule->getFullModuleName());
172229729919SBruno Cardoso Lopes     if (!FullName.startswith(M->Name) && !FullName.endswith("Private"))
172329729919SBruno Cardoso Lopes       continue;
17245f11e128SBruno Cardoso Lopes     SmallString<128> FixedPrivModDecl;
172529729919SBruno Cardoso Lopes     SmallString<128> Canonical(M->Name);
172629729919SBruno Cardoso Lopes     Canonical.append("_Private");
172729729919SBruno Cardoso Lopes 
172829729919SBruno Cardoso Lopes     // Foo.Private -> Foo_Private
172929729919SBruno Cardoso Lopes     if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
173029729919SBruno Cardoso Lopes         M->Name == ActiveModule->Parent->Name) {
173129729919SBruno Cardoso Lopes       Diags.Report(ActiveModule->DefinitionLoc,
173229729919SBruno Cardoso Lopes                    diag::warn_mmap_mismatched_private_submodule)
173329729919SBruno Cardoso Lopes           << FullName;
17345f11e128SBruno Cardoso Lopes 
17355f11e128SBruno Cardoso Lopes       SourceLocation FixItInitBegin = CurrModuleDeclLoc;
17365f11e128SBruno Cardoso Lopes       if (FrameworkLoc.isValid())
17375f11e128SBruno Cardoso Lopes         FixItInitBegin = FrameworkLoc;
17385f11e128SBruno Cardoso Lopes       if (ExplicitLoc.isValid())
17395f11e128SBruno Cardoso Lopes         FixItInitBegin = ExplicitLoc;
17405f11e128SBruno Cardoso Lopes 
17415f11e128SBruno Cardoso Lopes       if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
17425f11e128SBruno Cardoso Lopes         FixedPrivModDecl.append("framework ");
17435f11e128SBruno Cardoso Lopes       FixedPrivModDecl.append("module ");
17445f11e128SBruno Cardoso Lopes       FixedPrivModDecl.append(Canonical);
17455f11e128SBruno Cardoso Lopes 
17465f11e128SBruno Cardoso Lopes       GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
17475f11e128SBruno Cardoso Lopes                       SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
174829729919SBruno Cardoso Lopes       continue;
174929729919SBruno Cardoso Lopes     }
175029729919SBruno Cardoso Lopes 
175129729919SBruno Cardoso Lopes     // FooPrivate and whatnots -> Foo_Private
175229729919SBruno Cardoso Lopes     if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
175329729919SBruno Cardoso Lopes         ActiveModule->Name != Canonical) {
175429729919SBruno Cardoso Lopes       Diags.Report(ActiveModule->DefinitionLoc,
175529729919SBruno Cardoso Lopes                    diag::warn_mmap_mismatched_private_module_name)
175629729919SBruno Cardoso Lopes           << ActiveModule->Name;
17577d29486dSBruno Cardoso Lopes       GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
17587d29486dSBruno Cardoso Lopes                       SourceRange(ActiveModule->DefinitionLoc));
175929729919SBruno Cardoso Lopes     }
176029729919SBruno Cardoso Lopes   }
176129729919SBruno Cardoso Lopes }
176229729919SBruno Cardoso Lopes 
17639fc8faf9SAdrian Prantl /// Parse a module declaration.
1764718292f2SDouglas Gregor ///
1765718292f2SDouglas Gregor ///   module-declaration:
176697292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
1767a686e1b0SDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1768a686e1b0SDouglas Gregor ///       { module-member* }
1769a686e1b0SDouglas Gregor ///
1770718292f2SDouglas Gregor ///   module-member:
17711fb5c3a6SDouglas Gregor ///     requires-declaration
1772718292f2SDouglas Gregor ///     header-declaration
1773e7ab3669SDouglas Gregor ///     submodule-declaration
17742b82c2a5SDouglas Gregor ///     export-declaration
1775f0b11de2SDouglas Gregor ///     export-as-declaration
17766ddfca91SDouglas Gregor ///     link-declaration
177773441091SDouglas Gregor ///
177873441091SDouglas Gregor ///   submodule-declaration:
177973441091SDouglas Gregor ///     module-declaration
178073441091SDouglas Gregor ///     inferred-submodule-declaration
1781718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
1782755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
178397292843SDaniel Jasper          Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
178497292843SDaniel Jasper   if (Tok.is(MMToken::ExternKeyword)) {
178597292843SDaniel Jasper     parseExternModuleDecl();
178697292843SDaniel Jasper     return;
178797292843SDaniel Jasper   }
178897292843SDaniel Jasper 
1789f2161a70SDouglas Gregor   // Parse 'explicit' or 'framework' keyword, if present.
1790e7ab3669SDouglas Gregor   SourceLocation ExplicitLoc;
17915f11e128SBruno Cardoso Lopes   SourceLocation FrameworkLoc;
1792718292f2SDouglas Gregor   bool Explicit = false;
1793f2161a70SDouglas Gregor   bool Framework = false;
1794755b2055SDouglas Gregor 
1795f2161a70SDouglas Gregor   // Parse 'explicit' keyword, if present.
1796f2161a70SDouglas Gregor   if (Tok.is(MMToken::ExplicitKeyword)) {
1797e7ab3669SDouglas Gregor     ExplicitLoc = consumeToken();
1798f2161a70SDouglas Gregor     Explicit = true;
1799f2161a70SDouglas Gregor   }
1800f2161a70SDouglas Gregor 
1801f2161a70SDouglas Gregor   // Parse 'framework' keyword, if present.
1802755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
18035f11e128SBruno Cardoso Lopes     FrameworkLoc = consumeToken();
1804755b2055SDouglas Gregor     Framework = true;
1805755b2055SDouglas Gregor   }
1806718292f2SDouglas Gregor 
1807718292f2SDouglas Gregor   // Parse 'module' keyword.
1808718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
1809d6343c99SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1810718292f2SDouglas Gregor     consumeToken();
1811718292f2SDouglas Gregor     HadError = true;
1812718292f2SDouglas Gregor     return;
1813718292f2SDouglas Gregor   }
18149f6020bcSBruno Cardoso Lopes   CurrModuleDeclLoc = consumeToken(); // 'module' keyword
1815718292f2SDouglas Gregor 
181673441091SDouglas Gregor   // If we have a wildcard for the module name, this is an inferred submodule.
181773441091SDouglas Gregor   // Parse it.
181873441091SDouglas Gregor   if (Tok.is(MMToken::Star))
18199194a91dSDouglas Gregor     return parseInferredModuleDecl(Framework, Explicit);
182073441091SDouglas Gregor 
1821718292f2SDouglas Gregor   // Parse the module name.
1822e7ab3669SDouglas Gregor   ModuleId Id;
1823e7ab3669SDouglas Gregor   if (parseModuleId(Id)) {
1824718292f2SDouglas Gregor     HadError = true;
1825718292f2SDouglas Gregor     return;
1826718292f2SDouglas Gregor   }
1827e7ab3669SDouglas Gregor 
1828e7ab3669SDouglas Gregor   if (ActiveModule) {
1829e7ab3669SDouglas Gregor     if (Id.size() > 1) {
1830e7ab3669SDouglas Gregor       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1831e7ab3669SDouglas Gregor         << SourceRange(Id.front().second, Id.back().second);
1832e7ab3669SDouglas Gregor 
1833e7ab3669SDouglas Gregor       HadError = true;
1834e7ab3669SDouglas Gregor       return;
1835e7ab3669SDouglas Gregor     }
1836e7ab3669SDouglas Gregor   } else if (Id.size() == 1 && Explicit) {
1837e7ab3669SDouglas Gregor     // Top-level modules can't be explicit.
1838e7ab3669SDouglas Gregor     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1839e7ab3669SDouglas Gregor     Explicit = false;
1840e7ab3669SDouglas Gregor     ExplicitLoc = SourceLocation();
1841e7ab3669SDouglas Gregor     HadError = true;
1842e7ab3669SDouglas Gregor   }
1843e7ab3669SDouglas Gregor 
1844e7ab3669SDouglas Gregor   Module *PreviousActiveModule = ActiveModule;
1845e7ab3669SDouglas Gregor   if (Id.size() > 1) {
1846e7ab3669SDouglas Gregor     // This module map defines a submodule. Go find the module of which it
1847e7ab3669SDouglas Gregor     // is a submodule.
1848d2d442caSCraig Topper     ActiveModule = nullptr;
18494b8a9e95SBen Langmuir     const Module *TopLevelModule = nullptr;
1850e7ab3669SDouglas Gregor     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1851e7ab3669SDouglas Gregor       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
18524b8a9e95SBen Langmuir         if (I == 0)
18534b8a9e95SBen Langmuir           TopLevelModule = Next;
1854e7ab3669SDouglas Gregor         ActiveModule = Next;
1855e7ab3669SDouglas Gregor         continue;
1856e7ab3669SDouglas Gregor       }
1857e7ab3669SDouglas Gregor 
1858e7ab3669SDouglas Gregor       if (ActiveModule) {
1859e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
18605b5d21eaSRichard Smith           << Id[I].first
18615b5d21eaSRichard Smith           << ActiveModule->getTopLevelModule()->getFullModuleName();
1862e7ab3669SDouglas Gregor       } else {
1863e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1864e7ab3669SDouglas Gregor       }
1865e7ab3669SDouglas Gregor       HadError = true;
1866e7ab3669SDouglas Gregor       return;
1867e7ab3669SDouglas Gregor     }
18684b8a9e95SBen Langmuir 
18694b8a9e95SBen Langmuir     if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
18704b8a9e95SBen Langmuir       assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
18714b8a9e95SBen Langmuir              "submodule defined in same file as 'module *' that allowed its "
18724b8a9e95SBen Langmuir              "top-level module");
18734b8a9e95SBen Langmuir       Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
18744b8a9e95SBen Langmuir     }
1875e7ab3669SDouglas Gregor   }
1876e7ab3669SDouglas Gregor 
1877e7ab3669SDouglas Gregor   StringRef ModuleName = Id.back().first;
1878e7ab3669SDouglas Gregor   SourceLocation ModuleNameLoc = Id.back().second;
1879718292f2SDouglas Gregor 
1880a686e1b0SDouglas Gregor   // Parse the optional attribute list.
18814442605fSBill Wendling   Attributes Attrs;
18825d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
18835d29dee0SDavide Italiano     return;
18845d29dee0SDavide Italiano 
1885718292f2SDouglas Gregor   // Parse the opening brace.
1886718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
1887718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1888718292f2SDouglas Gregor       << ModuleName;
1889718292f2SDouglas Gregor     HadError = true;
1890718292f2SDouglas Gregor     return;
1891718292f2SDouglas Gregor   }
1892718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
1893718292f2SDouglas Gregor 
1894718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
18958587dfd9SBruno Cardoso Lopes   Module *ShadowingModule = nullptr;
1896eb90e830SDouglas Gregor   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
18974a3751ffSRichard Smith     // We might see a (re)definition of a module that we already have a
18984a3751ffSRichard Smith     // definition for in two cases:
18994a3751ffSRichard Smith     //  - If we loaded one definition from an AST file and we've just found a
19004a3751ffSRichard Smith     //    corresponding definition in a module map file, or
19014a3751ffSRichard Smith     bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
19024a3751ffSRichard Smith     //  - If we're building a (preprocessed) module and we've just loaded the
19034a3751ffSRichard Smith     //    module map file from which it was created.
19044a3751ffSRichard Smith     bool ParsedAsMainInput =
19054a3751ffSRichard Smith         Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
19064a3751ffSRichard Smith         Map.LangOpts.CurrentModule == ModuleName &&
19074a3751ffSRichard Smith         SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
19084a3751ffSRichard Smith             SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
19094a3751ffSRichard Smith     if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
1910fcc54a3bSDouglas Gregor       // Skip the module definition.
1911fcc54a3bSDouglas Gregor       skipUntil(MMToken::RBrace);
1912fcc54a3bSDouglas Gregor       if (Tok.is(MMToken::RBrace))
1913fcc54a3bSDouglas Gregor         consumeToken();
1914fcc54a3bSDouglas Gregor       else {
1915fcc54a3bSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1916fcc54a3bSDouglas Gregor         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1917fcc54a3bSDouglas Gregor         HadError = true;
1918fcc54a3bSDouglas Gregor       }
1919fcc54a3bSDouglas Gregor       return;
1920fcc54a3bSDouglas Gregor     }
1921fcc54a3bSDouglas Gregor 
1922c192d194SBruno Cardoso Lopes     if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
19238587dfd9SBruno Cardoso Lopes       ShadowingModule = Existing;
19248587dfd9SBruno Cardoso Lopes     } else {
19258587dfd9SBruno Cardoso Lopes       // This is not a shawdowed module decl, it is an illegal redefinition.
1926718292f2SDouglas Gregor       Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1927718292f2SDouglas Gregor           << ModuleName;
1928eb90e830SDouglas Gregor       Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1929718292f2SDouglas Gregor 
1930718292f2SDouglas Gregor       // Skip the module definition.
1931718292f2SDouglas Gregor       skipUntil(MMToken::RBrace);
1932718292f2SDouglas Gregor       if (Tok.is(MMToken::RBrace))
1933718292f2SDouglas Gregor         consumeToken();
1934718292f2SDouglas Gregor 
1935718292f2SDouglas Gregor       HadError = true;
1936718292f2SDouglas Gregor       return;
1937718292f2SDouglas Gregor     }
19388587dfd9SBruno Cardoso Lopes   }
1939718292f2SDouglas Gregor 
1940718292f2SDouglas Gregor   // Start defining this module.
19418587dfd9SBruno Cardoso Lopes   if (ShadowingModule) {
19428587dfd9SBruno Cardoso Lopes     ActiveModule =
19438587dfd9SBruno Cardoso Lopes         Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
19448587dfd9SBruno Cardoso Lopes   } else {
1945c192d194SBruno Cardoso Lopes     ActiveModule =
1946c192d194SBruno Cardoso Lopes         Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
19478587dfd9SBruno Cardoso Lopes             .first;
19488587dfd9SBruno Cardoso Lopes   }
19498587dfd9SBruno Cardoso Lopes 
1950eb90e830SDouglas Gregor   ActiveModule->DefinitionLoc = ModuleNameLoc;
1951963c5535SDouglas Gregor   if (Attrs.IsSystem || IsSystem)
1952a686e1b0SDouglas Gregor     ActiveModule->IsSystem = true;
195377944868SRichard Smith   if (Attrs.IsExternC)
195477944868SRichard Smith     ActiveModule->IsExternC = true;
1955ed84df00SBruno Cardoso Lopes   if (Attrs.NoUndeclaredIncludes ||
1956ed84df00SBruno Cardoso Lopes       (!ActiveModule->Parent && ModuleName == "Darwin"))
1957ed84df00SBruno Cardoso Lopes     ActiveModule->NoUndeclaredIncludes = true;
19583c1a41adSRichard Smith   ActiveModule->Directory = Directory;
1959718292f2SDouglas Gregor 
196090b0a1fcSJordan Rose   StringRef MapFileName(ModuleMapFile->getName());
196190b0a1fcSJordan Rose   if (MapFileName.endswith("module.private.modulemap") ||
196290b0a1fcSJordan Rose       MapFileName.endswith("module_private.map")) {
196390b0a1fcSJordan Rose     ActiveModule->ModuleMapIsPrivate = true;
196490b0a1fcSJordan Rose   }
196529729919SBruno Cardoso Lopes 
196629729919SBruno Cardoso Lopes   // Private modules named as FooPrivate, Foo.Private or similar are likely a
196729729919SBruno Cardoso Lopes   // user error; provide warnings, notes and fixits to direct users to use
196829729919SBruno Cardoso Lopes   // Foo_Private instead.
196929729919SBruno Cardoso Lopes   SourceLocation StartLoc =
197029729919SBruno Cardoso Lopes       SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
197129729919SBruno Cardoso Lopes   if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
197229729919SBruno Cardoso Lopes       !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
197329729919SBruno Cardoso Lopes                        StartLoc) &&
197429729919SBruno Cardoso Lopes       !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
197529729919SBruno Cardoso Lopes                        StartLoc) &&
197690b0a1fcSJordan Rose       ActiveModule->ModuleMapIsPrivate)
19775f11e128SBruno Cardoso Lopes     diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
19784d867640SGraydon Hoare 
1979718292f2SDouglas Gregor   bool Done = false;
1980718292f2SDouglas Gregor   do {
1981718292f2SDouglas Gregor     switch (Tok.Kind) {
1982718292f2SDouglas Gregor     case MMToken::EndOfFile:
1983718292f2SDouglas Gregor     case MMToken::RBrace:
1984718292f2SDouglas Gregor       Done = true;
1985718292f2SDouglas Gregor       break;
1986718292f2SDouglas Gregor 
198735b13eceSDouglas Gregor     case MMToken::ConfigMacros:
198835b13eceSDouglas Gregor       parseConfigMacros();
198935b13eceSDouglas Gregor       break;
199035b13eceSDouglas Gregor 
1991fb912657SDouglas Gregor     case MMToken::Conflict:
1992fb912657SDouglas Gregor       parseConflict();
1993fb912657SDouglas Gregor       break;
1994fb912657SDouglas Gregor 
1995718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
199697292843SDaniel Jasper     case MMToken::ExternKeyword:
1997f2161a70SDouglas Gregor     case MMToken::FrameworkKeyword:
1998718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
1999718292f2SDouglas Gregor       parseModuleDecl();
2000718292f2SDouglas Gregor       break;
2001718292f2SDouglas Gregor 
20022b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
20032b82c2a5SDouglas Gregor       parseExportDecl();
20042b82c2a5SDouglas Gregor       break;
20052b82c2a5SDouglas Gregor 
2006f0b11de2SDouglas Gregor     case MMToken::ExportAsKeyword:
2007f0b11de2SDouglas Gregor       parseExportAsDecl();
2008f0b11de2SDouglas Gregor       break;
2009f0b11de2SDouglas Gregor 
2010ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
2011ba7f2f71SDaniel Jasper       parseUseDecl();
2012ba7f2f71SDaniel Jasper       break;
2013ba7f2f71SDaniel Jasper 
20141fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
20151fb5c3a6SDouglas Gregor       parseRequiresDecl();
20161fb5c3a6SDouglas Gregor       break;
20171fb5c3a6SDouglas Gregor 
2018202210b3SRichard Smith     case MMToken::TextualKeyword:
2019202210b3SRichard Smith       parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
2020306d8920SRichard Smith       break;
2021306d8920SRichard Smith 
2022524e33e1SDouglas Gregor     case MMToken::UmbrellaKeyword: {
2023524e33e1SDouglas Gregor       SourceLocation UmbrellaLoc = consumeToken();
2024524e33e1SDouglas Gregor       if (Tok.is(MMToken::HeaderKeyword))
2025b53e5483SLawrence Crowl         parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
2026524e33e1SDouglas Gregor       else
2027524e33e1SDouglas Gregor         parseUmbrellaDirDecl(UmbrellaLoc);
2028718292f2SDouglas Gregor       break;
2029524e33e1SDouglas Gregor     }
2030718292f2SDouglas Gregor 
2031202210b3SRichard Smith     case MMToken::ExcludeKeyword:
2032202210b3SRichard Smith       parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
203359527666SDouglas Gregor       break;
203459527666SDouglas Gregor 
2035202210b3SRichard Smith     case MMToken::PrivateKeyword:
2036202210b3SRichard Smith       parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
2037b53e5483SLawrence Crowl       break;
2038b53e5483SLawrence Crowl 
2039322f633cSDouglas Gregor     case MMToken::HeaderKeyword:
2040202210b3SRichard Smith       parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
2041718292f2SDouglas Gregor       break;
2042718292f2SDouglas Gregor 
20436ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
20446ddfca91SDouglas Gregor       parseLinkDecl();
20456ddfca91SDouglas Gregor       break;
20466ddfca91SDouglas Gregor 
2047718292f2SDouglas Gregor     default:
2048718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
2049718292f2SDouglas Gregor       consumeToken();
2050718292f2SDouglas Gregor       break;
2051718292f2SDouglas Gregor     }
2052718292f2SDouglas Gregor   } while (!Done);
2053718292f2SDouglas Gregor 
2054718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
2055718292f2SDouglas Gregor     consumeToken();
2056718292f2SDouglas Gregor   else {
2057718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2058718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2059718292f2SDouglas Gregor     HadError = true;
2060718292f2SDouglas Gregor   }
2061718292f2SDouglas Gregor 
206211dfe6feSDouglas Gregor   // If the active module is a top-level framework, and there are no link
206311dfe6feSDouglas Gregor   // libraries, automatically link against the framework.
206411dfe6feSDouglas Gregor   if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
206511dfe6feSDouglas Gregor       ActiveModule->LinkLibraries.empty()) {
206611dfe6feSDouglas Gregor     inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
206711dfe6feSDouglas Gregor   }
206811dfe6feSDouglas Gregor 
2069ec8c9752SBen Langmuir   // If the module meets all requirements but is still unavailable, mark the
2070ec8c9752SBen Langmuir   // whole tree as unavailable to prevent it from building.
2071ec8c9752SBen Langmuir   if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement &&
2072ec8c9752SBen Langmuir       ActiveModule->Parent) {
2073ec8c9752SBen Langmuir     ActiveModule->getTopLevelModule()->markUnavailable();
2074ec8c9752SBen Langmuir     ActiveModule->getTopLevelModule()->MissingHeaders.append(
2075ec8c9752SBen Langmuir       ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
2076ec8c9752SBen Langmuir   }
2077ec8c9752SBen Langmuir 
2078e7ab3669SDouglas Gregor   // We're done parsing this module. Pop back to the previous module.
2079e7ab3669SDouglas Gregor   ActiveModule = PreviousActiveModule;
2080718292f2SDouglas Gregor }
2081718292f2SDouglas Gregor 
20829fc8faf9SAdrian Prantl /// Parse an extern module declaration.
208397292843SDaniel Jasper ///
208497292843SDaniel Jasper ///   extern module-declaration:
208597292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
208697292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() {
208797292843SDaniel Jasper   assert(Tok.is(MMToken::ExternKeyword));
2088ae6df27eSRichard Smith   SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
208997292843SDaniel Jasper 
209097292843SDaniel Jasper   // Parse 'module' keyword.
209197292843SDaniel Jasper   if (!Tok.is(MMToken::ModuleKeyword)) {
209297292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
209397292843SDaniel Jasper     consumeToken();
209497292843SDaniel Jasper     HadError = true;
209597292843SDaniel Jasper     return;
209697292843SDaniel Jasper   }
209797292843SDaniel Jasper   consumeToken(); // 'module' keyword
209897292843SDaniel Jasper 
209997292843SDaniel Jasper   // Parse the module name.
210097292843SDaniel Jasper   ModuleId Id;
210197292843SDaniel Jasper   if (parseModuleId(Id)) {
210297292843SDaniel Jasper     HadError = true;
210397292843SDaniel Jasper     return;
210497292843SDaniel Jasper   }
210597292843SDaniel Jasper 
210697292843SDaniel Jasper   // Parse the referenced module map file name.
210797292843SDaniel Jasper   if (!Tok.is(MMToken::StringLiteral)) {
210897292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
210997292843SDaniel Jasper     HadError = true;
211097292843SDaniel Jasper     return;
211197292843SDaniel Jasper   }
211297292843SDaniel Jasper   std::string FileName = Tok.getString();
211397292843SDaniel Jasper   consumeToken(); // filename
211497292843SDaniel Jasper 
211597292843SDaniel Jasper   StringRef FileNameRef = FileName;
211697292843SDaniel Jasper   SmallString<128> ModuleMapFileName;
211797292843SDaniel Jasper   if (llvm::sys::path::is_relative(FileNameRef)) {
211897292843SDaniel Jasper     ModuleMapFileName += Directory->getName();
211997292843SDaniel Jasper     llvm::sys::path::append(ModuleMapFileName, FileName);
212092e1b62dSYaron Keren     FileNameRef = ModuleMapFileName;
212197292843SDaniel Jasper   }
212297292843SDaniel Jasper   if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef))
21239acb99e3SRichard Smith     Map.parseModuleMapFile(
21249acb99e3SRichard Smith         File, /*IsSystem=*/false,
21259acb99e3SRichard Smith         Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
21269acb99e3SRichard Smith             ? Directory
21278128f332SRichard Smith             : File->getDir(),
2128c192d194SBruno Cardoso Lopes         FileID(), nullptr, ExternLoc);
212997292843SDaniel Jasper }
213097292843SDaniel Jasper 
21317ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M.
21327ff29148SBen Langmuir ///
21337ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system
21347ff29148SBen Langmuir /// module map files:
21357ff29148SBen Langmuir ///
21367ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which
21377ff29148SBen Langmuir ///    should really be mapped to 'textual' now that we have this feature.  We
21387ff29148SBen Langmuir ///    drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
21397ff29148SBen Langmuir ///    true.  Later, this bit will be used to map all the headers inside this
21407ff29148SBen Langmuir ///    module to 'textual'.
21417ff29148SBen Langmuir ///
21427ff29148SBen Langmuir ///    This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
21437ff29148SBen Langmuir ///
21447ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc.  This requirement
21457ff29148SBen Langmuir ///    was never correct and causes issues now that we check it, so drop it.
21467ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature,
21477ff29148SBen Langmuir                                  bool &IsRequiresExcludedHack) {
21488013e81dSBenjamin Kramer   if (Feature == "excluded" &&
21498013e81dSBenjamin Kramer       (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
21508013e81dSBenjamin Kramer        M->fullModuleNameIs({"Tcl", "Private"}))) {
21517ff29148SBen Langmuir     IsRequiresExcludedHack = true;
21527ff29148SBen Langmuir     return false;
21538013e81dSBenjamin Kramer   } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
21547ff29148SBen Langmuir     return false;
21557ff29148SBen Langmuir   }
21567ff29148SBen Langmuir 
21577ff29148SBen Langmuir   return true;
21587ff29148SBen Langmuir }
21597ff29148SBen Langmuir 
21609fc8faf9SAdrian Prantl /// Parse a requires declaration.
21611fb5c3a6SDouglas Gregor ///
21621fb5c3a6SDouglas Gregor ///   requires-declaration:
21631fb5c3a6SDouglas Gregor ///     'requires' feature-list
21641fb5c3a6SDouglas Gregor ///
21651fb5c3a6SDouglas Gregor ///   feature-list:
2166a3feee2aSRichard Smith ///     feature ',' feature-list
2167a3feee2aSRichard Smith ///     feature
2168a3feee2aSRichard Smith ///
2169a3feee2aSRichard Smith ///   feature:
2170a3feee2aSRichard Smith ///     '!'[opt] identifier
21711fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() {
21721fb5c3a6SDouglas Gregor   assert(Tok.is(MMToken::RequiresKeyword));
21731fb5c3a6SDouglas Gregor 
21741fb5c3a6SDouglas Gregor   // Parse 'requires' keyword.
21751fb5c3a6SDouglas Gregor   consumeToken();
21761fb5c3a6SDouglas Gregor 
21771fb5c3a6SDouglas Gregor   // Parse the feature-list.
21781fb5c3a6SDouglas Gregor   do {
2179a3feee2aSRichard Smith     bool RequiredState = true;
2180a3feee2aSRichard Smith     if (Tok.is(MMToken::Exclaim)) {
2181a3feee2aSRichard Smith       RequiredState = false;
2182a3feee2aSRichard Smith       consumeToken();
2183a3feee2aSRichard Smith     }
2184a3feee2aSRichard Smith 
21851fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
21861fb5c3a6SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
21871fb5c3a6SDouglas Gregor       HadError = true;
21881fb5c3a6SDouglas Gregor       return;
21891fb5c3a6SDouglas Gregor     }
21901fb5c3a6SDouglas Gregor 
21911fb5c3a6SDouglas Gregor     // Consume the feature name.
21921fb5c3a6SDouglas Gregor     std::string Feature = Tok.getString();
21931fb5c3a6SDouglas Gregor     consumeToken();
21941fb5c3a6SDouglas Gregor 
21957ff29148SBen Langmuir     bool IsRequiresExcludedHack = false;
21967ff29148SBen Langmuir     bool ShouldAddRequirement =
21977ff29148SBen Langmuir         shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
21987ff29148SBen Langmuir 
21997ff29148SBen Langmuir     if (IsRequiresExcludedHack)
22007ff29148SBen Langmuir       UsesRequiresExcludedHack.insert(ActiveModule);
22017ff29148SBen Langmuir 
22027ff29148SBen Langmuir     if (ShouldAddRequirement) {
22031fb5c3a6SDouglas Gregor       // Add this feature.
22047ff29148SBen Langmuir       ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
22057ff29148SBen Langmuir                                    *Map.Target);
22067ff29148SBen Langmuir     }
22071fb5c3a6SDouglas Gregor 
22081fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Comma))
22091fb5c3a6SDouglas Gregor       break;
22101fb5c3a6SDouglas Gregor 
22111fb5c3a6SDouglas Gregor     // Consume the comma.
22121fb5c3a6SDouglas Gregor     consumeToken();
22131fb5c3a6SDouglas Gregor   } while (true);
22141fb5c3a6SDouglas Gregor }
22151fb5c3a6SDouglas Gregor 
22169fc8faf9SAdrian Prantl /// Parse a header declaration.
2217718292f2SDouglas Gregor ///
2218718292f2SDouglas Gregor ///   header-declaration:
2219306d8920SRichard Smith ///     'textual'[opt] 'header' string-literal
2220202210b3SRichard Smith ///     'private' 'textual'[opt] 'header' string-literal
2221202210b3SRichard Smith ///     'exclude' 'header' string-literal
2222202210b3SRichard Smith ///     'umbrella' 'header' string-literal
2223306d8920SRichard Smith ///
2224306d8920SRichard Smith /// FIXME: Support 'private textual header'.
2225b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
2226b53e5483SLawrence Crowl                                       SourceLocation LeadingLoc) {
2227202210b3SRichard Smith   // We've already consumed the first token.
2228202210b3SRichard Smith   ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
2229202210b3SRichard Smith   if (LeadingToken == MMToken::PrivateKeyword) {
2230202210b3SRichard Smith     Role = ModuleMap::PrivateHeader;
2231202210b3SRichard Smith     // 'private' may optionally be followed by 'textual'.
2232202210b3SRichard Smith     if (Tok.is(MMToken::TextualKeyword)) {
2233202210b3SRichard Smith       LeadingToken = Tok.Kind;
22341871ed3dSBenjamin Kramer       consumeToken();
2235202210b3SRichard Smith     }
2236202210b3SRichard Smith   }
22377ff29148SBen Langmuir 
2238202210b3SRichard Smith   if (LeadingToken == MMToken::TextualKeyword)
2239202210b3SRichard Smith     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
2240202210b3SRichard Smith 
22417ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
22427ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
22437ff29148SBen Langmuir     // Module::UsesRequiresExcludedHack).
22447ff29148SBen Langmuir     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
22457ff29148SBen Langmuir   }
22467ff29148SBen Langmuir 
2247202210b3SRichard Smith   if (LeadingToken != MMToken::HeaderKeyword) {
2248202210b3SRichard Smith     if (!Tok.is(MMToken::HeaderKeyword)) {
2249202210b3SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2250202210b3SRichard Smith           << (LeadingToken == MMToken::PrivateKeyword ? "private" :
2251202210b3SRichard Smith               LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
2252202210b3SRichard Smith               LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
2253202210b3SRichard Smith       return;
2254202210b3SRichard Smith     }
2255202210b3SRichard Smith     consumeToken();
2256202210b3SRichard Smith   }
2257718292f2SDouglas Gregor 
2258718292f2SDouglas Gregor   // Parse the header name.
2259718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2260718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2261718292f2SDouglas Gregor       << "header";
2262718292f2SDouglas Gregor     HadError = true;
2263718292f2SDouglas Gregor     return;
2264718292f2SDouglas Gregor   }
22653c1a41adSRichard Smith   Module::UnresolvedHeaderDirective Header;
22660761a8a0SDaniel Jasper   Header.FileName = Tok.getString();
22670761a8a0SDaniel Jasper   Header.FileNameLoc = consumeToken();
22681d60987fSRichard Smith   Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
2269040e1266SRichard Smith   Header.Kind =
2270040e1266SRichard Smith       (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded
2271040e1266SRichard Smith                                                : Map.headerRoleToKind(Role));
2272718292f2SDouglas Gregor 
2273524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
22741d60987fSRichard Smith   if (Header.IsUmbrella && ActiveModule->Umbrella) {
22750761a8a0SDaniel Jasper     Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2276524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2277322f633cSDouglas Gregor     HadError = true;
2278322f633cSDouglas Gregor     return;
2279322f633cSDouglas Gregor   }
2280322f633cSDouglas Gregor 
2281040e1266SRichard Smith   // If we were given stat information, parse it so we can skip looking for
2282040e1266SRichard Smith   // the file.
2283040e1266SRichard Smith   if (Tok.is(MMToken::LBrace)) {
2284040e1266SRichard Smith     SourceLocation LBraceLoc = consumeToken();
22853ec6663bSDouglas Gregor 
2286040e1266SRichard Smith     while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
2287040e1266SRichard Smith       enum Attribute { Size, ModTime, Unknown };
2288040e1266SRichard Smith       StringRef Str = Tok.getString();
2289040e1266SRichard Smith       SourceLocation Loc = consumeToken();
2290040e1266SRichard Smith       switch (llvm::StringSwitch<Attribute>(Str)
2291040e1266SRichard Smith                   .Case("size", Size)
2292040e1266SRichard Smith                   .Case("mtime", ModTime)
2293040e1266SRichard Smith                   .Default(Unknown)) {
2294040e1266SRichard Smith       case Size:
2295040e1266SRichard Smith         if (Header.Size)
2296040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2297040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2298040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2299040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2300040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2301040e1266SRichard Smith           break;
2302040e1266SRichard Smith         }
2303040e1266SRichard Smith         Header.Size = Tok.getInteger();
2304040e1266SRichard Smith         consumeToken();
2305040e1266SRichard Smith         break;
2306040e1266SRichard Smith 
2307040e1266SRichard Smith       case ModTime:
2308040e1266SRichard Smith         if (Header.ModTime)
2309040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2310040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2311040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2312040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2313040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2314040e1266SRichard Smith           break;
2315040e1266SRichard Smith         }
2316040e1266SRichard Smith         Header.ModTime = Tok.getInteger();
2317040e1266SRichard Smith         consumeToken();
2318040e1266SRichard Smith         break;
2319040e1266SRichard Smith 
2320040e1266SRichard Smith       case Unknown:
2321040e1266SRichard Smith         Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
2322040e1266SRichard Smith         skipUntil(MMToken::RBrace);
2323040e1266SRichard Smith         break;
2324040e1266SRichard Smith       }
23253ec6663bSDouglas Gregor     }
23265257fc63SDouglas Gregor 
2327040e1266SRichard Smith     if (Tok.is(MMToken::RBrace))
2328040e1266SRichard Smith       consumeToken();
2329040e1266SRichard Smith     else {
2330040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2331040e1266SRichard Smith       Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2332322f633cSDouglas Gregor       HadError = true;
2333322f633cSDouglas Gregor     }
23340101b540SHans Wennborg   }
233525d50758SRichard Smith 
23369f6020bcSBruno Cardoso Lopes   bool NeedsFramework = false;
23379f6020bcSBruno Cardoso Lopes   Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
23389f6020bcSBruno Cardoso Lopes 
23399f6020bcSBruno Cardoso Lopes   if (NeedsFramework && ActiveModule)
23409f6020bcSBruno Cardoso Lopes     Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
23419f6020bcSBruno Cardoso Lopes       << ActiveModule->getFullModuleName()
23429f6020bcSBruno Cardoso Lopes       << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
2343718292f2SDouglas Gregor }
2344718292f2SDouglas Gregor 
234541f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A,
234641f81994SBen Langmuir                                 const Module::Header *B) {
234741f81994SBen Langmuir   return A->NameAsWritten.compare(B->NameAsWritten);
234841f81994SBen Langmuir }
234941f81994SBen Langmuir 
23509fc8faf9SAdrian Prantl /// Parse an umbrella directory declaration.
2351524e33e1SDouglas Gregor ///
2352524e33e1SDouglas Gregor ///   umbrella-dir-declaration:
2353524e33e1SDouglas Gregor ///     umbrella string-literal
2354524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
2355524e33e1SDouglas Gregor   // Parse the directory name.
2356524e33e1SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2357524e33e1SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2358524e33e1SDouglas Gregor       << "umbrella";
2359524e33e1SDouglas Gregor     HadError = true;
2360524e33e1SDouglas Gregor     return;
2361524e33e1SDouglas Gregor   }
2362524e33e1SDouglas Gregor 
2363524e33e1SDouglas Gregor   std::string DirName = Tok.getString();
2364524e33e1SDouglas Gregor   SourceLocation DirNameLoc = consumeToken();
2365524e33e1SDouglas Gregor 
2366524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
2367524e33e1SDouglas Gregor   if (ActiveModule->Umbrella) {
2368524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
2369524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2370524e33e1SDouglas Gregor     HadError = true;
2371524e33e1SDouglas Gregor     return;
2372524e33e1SDouglas Gregor   }
2373524e33e1SDouglas Gregor 
2374524e33e1SDouglas Gregor   // Look for this file.
2375d2d442caSCraig Topper   const DirectoryEntry *Dir = nullptr;
2376524e33e1SDouglas Gregor   if (llvm::sys::path::is_absolute(DirName))
2377524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(DirName);
2378524e33e1SDouglas Gregor   else {
23792c1dd271SDylan Noblesmith     SmallString<128> PathName;
2380524e33e1SDouglas Gregor     PathName = Directory->getName();
2381524e33e1SDouglas Gregor     llvm::sys::path::append(PathName, DirName);
2382524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(PathName);
2383524e33e1SDouglas Gregor   }
2384524e33e1SDouglas Gregor 
2385524e33e1SDouglas Gregor   if (!Dir) {
2386a0320b97SVassil Vassilev     Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
2387524e33e1SDouglas Gregor       << DirName;
2388524e33e1SDouglas Gregor     return;
2389524e33e1SDouglas Gregor   }
2390524e33e1SDouglas Gregor 
23917ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
23927ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
23937ff29148SBen Langmuir     // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
23947ff29148SBen Langmuir     // directory is relatively expensive, in practice this only applies to the
23957ff29148SBen Langmuir     // uncommonly used Tcl module on Darwin platforms.
23967ff29148SBen Langmuir     std::error_code EC;
23977ff29148SBen Langmuir     SmallVector<Module::Header, 6> Headers;
2398*fc51490bSJonas Devlieghere     llvm::vfs::FileSystem &FS =
2399*fc51490bSJonas Devlieghere         *SourceMgr.getFileManager().getVirtualFileSystem();
2400*fc51490bSJonas Devlieghere     for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
24017ff29148SBen Langmuir          I != E && !EC; I.increment(EC)) {
24020ae00567SSam McCall       if (const FileEntry *FE = SourceMgr.getFileManager().getFile(I->path())) {
24037ff29148SBen Langmuir 
24040ae00567SSam McCall         Module::Header Header = {I->path(), FE};
24057ff29148SBen Langmuir         Headers.push_back(std::move(Header));
24067ff29148SBen Langmuir       }
24077ff29148SBen Langmuir     }
24087ff29148SBen Langmuir 
24097ff29148SBen Langmuir     // Sort header paths so that the pcm doesn't depend on iteration order.
241041f81994SBen Langmuir     llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
241141f81994SBen Langmuir 
24127ff29148SBen Langmuir     for (auto &Header : Headers)
24137ff29148SBen Langmuir       Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
24147ff29148SBen Langmuir     return;
24157ff29148SBen Langmuir   }
24167ff29148SBen Langmuir 
2417524e33e1SDouglas Gregor   if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
2418524e33e1SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
2419524e33e1SDouglas Gregor       << OwningModule->getFullModuleName();
2420524e33e1SDouglas Gregor     HadError = true;
2421524e33e1SDouglas Gregor     return;
2422524e33e1SDouglas Gregor   }
2423524e33e1SDouglas Gregor 
2424524e33e1SDouglas Gregor   // Record this umbrella directory.
24252b63d15fSRichard Smith   Map.setUmbrellaDir(ActiveModule, Dir, DirName);
2426524e33e1SDouglas Gregor }
2427524e33e1SDouglas Gregor 
24289fc8faf9SAdrian Prantl /// Parse a module export declaration.
24292b82c2a5SDouglas Gregor ///
24302b82c2a5SDouglas Gregor ///   export-declaration:
24312b82c2a5SDouglas Gregor ///     'export' wildcard-module-id
24322b82c2a5SDouglas Gregor ///
24332b82c2a5SDouglas Gregor ///   wildcard-module-id:
24342b82c2a5SDouglas Gregor ///     identifier
24352b82c2a5SDouglas Gregor ///     '*'
24362b82c2a5SDouglas Gregor ///     identifier '.' wildcard-module-id
24372b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() {
24382b82c2a5SDouglas Gregor   assert(Tok.is(MMToken::ExportKeyword));
24392b82c2a5SDouglas Gregor   SourceLocation ExportLoc = consumeToken();
24402b82c2a5SDouglas Gregor 
24412b82c2a5SDouglas Gregor   // Parse the module-id with an optional wildcard at the end.
24422b82c2a5SDouglas Gregor   ModuleId ParsedModuleId;
24432b82c2a5SDouglas Gregor   bool Wildcard = false;
24442b82c2a5SDouglas Gregor   do {
2445306d8920SRichard Smith     // FIXME: Support string-literal module names here.
24462b82c2a5SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
24472b82c2a5SDouglas Gregor       ParsedModuleId.push_back(std::make_pair(Tok.getString(),
24482b82c2a5SDouglas Gregor                                               Tok.getLocation()));
24492b82c2a5SDouglas Gregor       consumeToken();
24502b82c2a5SDouglas Gregor 
24512b82c2a5SDouglas Gregor       if (Tok.is(MMToken::Period)) {
24522b82c2a5SDouglas Gregor         consumeToken();
24532b82c2a5SDouglas Gregor         continue;
24542b82c2a5SDouglas Gregor       }
24552b82c2a5SDouglas Gregor 
24562b82c2a5SDouglas Gregor       break;
24572b82c2a5SDouglas Gregor     }
24582b82c2a5SDouglas Gregor 
24592b82c2a5SDouglas Gregor     if(Tok.is(MMToken::Star)) {
24602b82c2a5SDouglas Gregor       Wildcard = true;
2461f5eedd05SDouglas Gregor       consumeToken();
24622b82c2a5SDouglas Gregor       break;
24632b82c2a5SDouglas Gregor     }
24642b82c2a5SDouglas Gregor 
2465ba7f2f71SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
24662b82c2a5SDouglas Gregor     HadError = true;
24672b82c2a5SDouglas Gregor     return;
24682b82c2a5SDouglas Gregor   } while (true);
24692b82c2a5SDouglas Gregor 
24702b82c2a5SDouglas Gregor   Module::UnresolvedExportDecl Unresolved = {
24712b82c2a5SDouglas Gregor     ExportLoc, ParsedModuleId, Wildcard
24722b82c2a5SDouglas Gregor   };
24732b82c2a5SDouglas Gregor   ActiveModule->UnresolvedExports.push_back(Unresolved);
24742b82c2a5SDouglas Gregor }
24752b82c2a5SDouglas Gregor 
24769fc8faf9SAdrian Prantl /// Parse a module export_as declaration.
2477f0b11de2SDouglas Gregor ///
2478f0b11de2SDouglas Gregor ///   export-as-declaration:
2479f0b11de2SDouglas Gregor ///     'export_as' identifier
2480f0b11de2SDouglas Gregor void ModuleMapParser::parseExportAsDecl() {
2481f0b11de2SDouglas Gregor   assert(Tok.is(MMToken::ExportAsKeyword));
2482f0b11de2SDouglas Gregor   consumeToken();
2483f0b11de2SDouglas Gregor 
2484f0b11de2SDouglas Gregor   if (!Tok.is(MMToken::Identifier)) {
2485f0b11de2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
2486f0b11de2SDouglas Gregor     HadError = true;
2487f0b11de2SDouglas Gregor     return;
2488f0b11de2SDouglas Gregor   }
2489f0b11de2SDouglas Gregor 
2490f0b11de2SDouglas Gregor   if (ActiveModule->Parent) {
2491f0b11de2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
2492f0b11de2SDouglas Gregor     consumeToken();
2493f0b11de2SDouglas Gregor     return;
2494f0b11de2SDouglas Gregor   }
2495f0b11de2SDouglas Gregor 
2496f0b11de2SDouglas Gregor   if (!ActiveModule->ExportAsModule.empty()) {
2497f0b11de2SDouglas Gregor     if (ActiveModule->ExportAsModule == Tok.getString()) {
2498f0b11de2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
2499f0b11de2SDouglas Gregor         << ActiveModule->Name << Tok.getString();
2500f0b11de2SDouglas Gregor     } else {
2501f0b11de2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
2502f0b11de2SDouglas Gregor         << ActiveModule->Name << ActiveModule->ExportAsModule
2503f0b11de2SDouglas Gregor         << Tok.getString();
2504f0b11de2SDouglas Gregor     }
2505f0b11de2SDouglas Gregor   }
2506f0b11de2SDouglas Gregor 
2507f0b11de2SDouglas Gregor   ActiveModule->ExportAsModule = Tok.getString();
2508a3b5f71eSBruno Cardoso Lopes   Map.addLinkAsDependency(ActiveModule);
2509a3b5f71eSBruno Cardoso Lopes 
2510f0b11de2SDouglas Gregor   consumeToken();
2511f0b11de2SDouglas Gregor }
2512f0b11de2SDouglas Gregor 
25139fc8faf9SAdrian Prantl /// Parse a module use declaration.
2514ba7f2f71SDaniel Jasper ///
25158f4d3ff1SRichard Smith ///   use-declaration:
25168f4d3ff1SRichard Smith ///     'use' wildcard-module-id
2517ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() {
2518ba7f2f71SDaniel Jasper   assert(Tok.is(MMToken::UseKeyword));
25198f4d3ff1SRichard Smith   auto KWLoc = consumeToken();
2520ba7f2f71SDaniel Jasper   // Parse the module-id.
2521ba7f2f71SDaniel Jasper   ModuleId ParsedModuleId;
25223cd34c76SDaniel Jasper   parseModuleId(ParsedModuleId);
2523ba7f2f71SDaniel Jasper 
25248f4d3ff1SRichard Smith   if (ActiveModule->Parent)
25258f4d3ff1SRichard Smith     Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
25268f4d3ff1SRichard Smith   else
2527ba7f2f71SDaniel Jasper     ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
2528ba7f2f71SDaniel Jasper }
2529ba7f2f71SDaniel Jasper 
25309fc8faf9SAdrian Prantl /// Parse a link declaration.
25316ddfca91SDouglas Gregor ///
25326ddfca91SDouglas Gregor ///   module-declaration:
25336ddfca91SDouglas Gregor ///     'link' 'framework'[opt] string-literal
25346ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() {
25356ddfca91SDouglas Gregor   assert(Tok.is(MMToken::LinkKeyword));
25366ddfca91SDouglas Gregor   SourceLocation LinkLoc = consumeToken();
25376ddfca91SDouglas Gregor 
25386ddfca91SDouglas Gregor   // Parse the optional 'framework' keyword.
25396ddfca91SDouglas Gregor   bool IsFramework = false;
25406ddfca91SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
25416ddfca91SDouglas Gregor     consumeToken();
25426ddfca91SDouglas Gregor     IsFramework = true;
25436ddfca91SDouglas Gregor   }
25446ddfca91SDouglas Gregor 
25456ddfca91SDouglas Gregor   // Parse the library name
25466ddfca91SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
25476ddfca91SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
25486ddfca91SDouglas Gregor       << IsFramework << SourceRange(LinkLoc);
25496ddfca91SDouglas Gregor     HadError = true;
25506ddfca91SDouglas Gregor     return;
25516ddfca91SDouglas Gregor   }
25526ddfca91SDouglas Gregor 
25536ddfca91SDouglas Gregor   std::string LibraryName = Tok.getString();
25546ddfca91SDouglas Gregor   consumeToken();
25556ddfca91SDouglas Gregor   ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
25566ddfca91SDouglas Gregor                                                             IsFramework));
25576ddfca91SDouglas Gregor }
25586ddfca91SDouglas Gregor 
25599fc8faf9SAdrian Prantl /// Parse a configuration macro declaration.
256035b13eceSDouglas Gregor ///
256135b13eceSDouglas Gregor ///   module-declaration:
256235b13eceSDouglas Gregor ///     'config_macros' attributes[opt] config-macro-list?
256335b13eceSDouglas Gregor ///
256435b13eceSDouglas Gregor ///   config-macro-list:
256535b13eceSDouglas Gregor ///     identifier (',' identifier)?
256635b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() {
256735b13eceSDouglas Gregor   assert(Tok.is(MMToken::ConfigMacros));
256835b13eceSDouglas Gregor   SourceLocation ConfigMacrosLoc = consumeToken();
256935b13eceSDouglas Gregor 
257035b13eceSDouglas Gregor   // Only top-level modules can have configuration macros.
257135b13eceSDouglas Gregor   if (ActiveModule->Parent) {
257235b13eceSDouglas Gregor     Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
257335b13eceSDouglas Gregor   }
257435b13eceSDouglas Gregor 
257535b13eceSDouglas Gregor   // Parse the optional attributes.
257635b13eceSDouglas Gregor   Attributes Attrs;
25775d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
25785d29dee0SDavide Italiano     return;
25795d29dee0SDavide Italiano 
258035b13eceSDouglas Gregor   if (Attrs.IsExhaustive && !ActiveModule->Parent) {
258135b13eceSDouglas Gregor     ActiveModule->ConfigMacrosExhaustive = true;
258235b13eceSDouglas Gregor   }
258335b13eceSDouglas Gregor 
258435b13eceSDouglas Gregor   // If we don't have an identifier, we're done.
2585306d8920SRichard Smith   // FIXME: Support macros with the same name as a keyword here.
258635b13eceSDouglas Gregor   if (!Tok.is(MMToken::Identifier))
258735b13eceSDouglas Gregor     return;
258835b13eceSDouglas Gregor 
258935b13eceSDouglas Gregor   // Consume the first identifier.
259035b13eceSDouglas Gregor   if (!ActiveModule->Parent) {
259135b13eceSDouglas Gregor     ActiveModule->ConfigMacros.push_back(Tok.getString().str());
259235b13eceSDouglas Gregor   }
259335b13eceSDouglas Gregor   consumeToken();
259435b13eceSDouglas Gregor 
259535b13eceSDouglas Gregor   do {
259635b13eceSDouglas Gregor     // If there's a comma, consume it.
259735b13eceSDouglas Gregor     if (!Tok.is(MMToken::Comma))
259835b13eceSDouglas Gregor       break;
259935b13eceSDouglas Gregor     consumeToken();
260035b13eceSDouglas Gregor 
260135b13eceSDouglas Gregor     // We expect to see a macro name here.
2602306d8920SRichard Smith     // FIXME: Support macros with the same name as a keyword here.
260335b13eceSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
260435b13eceSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
260535b13eceSDouglas Gregor       break;
260635b13eceSDouglas Gregor     }
260735b13eceSDouglas Gregor 
260835b13eceSDouglas Gregor     // Consume the macro name.
260935b13eceSDouglas Gregor     if (!ActiveModule->Parent) {
261035b13eceSDouglas Gregor       ActiveModule->ConfigMacros.push_back(Tok.getString().str());
261135b13eceSDouglas Gregor     }
261235b13eceSDouglas Gregor     consumeToken();
261335b13eceSDouglas Gregor   } while (true);
261435b13eceSDouglas Gregor }
261535b13eceSDouglas Gregor 
26169fc8faf9SAdrian Prantl /// Format a module-id into a string.
2617fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) {
2618fb912657SDouglas Gregor   std::string result;
2619fb912657SDouglas Gregor   {
2620fb912657SDouglas Gregor     llvm::raw_string_ostream OS(result);
2621fb912657SDouglas Gregor 
2622fb912657SDouglas Gregor     for (unsigned I = 0, N = Id.size(); I != N; ++I) {
2623fb912657SDouglas Gregor       if (I)
2624fb912657SDouglas Gregor         OS << ".";
2625fb912657SDouglas Gregor       OS << Id[I].first;
2626fb912657SDouglas Gregor     }
2627fb912657SDouglas Gregor   }
2628fb912657SDouglas Gregor 
2629fb912657SDouglas Gregor   return result;
2630fb912657SDouglas Gregor }
2631fb912657SDouglas Gregor 
26329fc8faf9SAdrian Prantl /// Parse a conflict declaration.
2633fb912657SDouglas Gregor ///
2634fb912657SDouglas Gregor ///   module-declaration:
2635fb912657SDouglas Gregor ///     'conflict' module-id ',' string-literal
2636fb912657SDouglas Gregor void ModuleMapParser::parseConflict() {
2637fb912657SDouglas Gregor   assert(Tok.is(MMToken::Conflict));
2638fb912657SDouglas Gregor   SourceLocation ConflictLoc = consumeToken();
2639fb912657SDouglas Gregor   Module::UnresolvedConflict Conflict;
2640fb912657SDouglas Gregor 
2641fb912657SDouglas Gregor   // Parse the module-id.
2642fb912657SDouglas Gregor   if (parseModuleId(Conflict.Id))
2643fb912657SDouglas Gregor     return;
2644fb912657SDouglas Gregor 
2645fb912657SDouglas Gregor   // Parse the ','.
2646fb912657SDouglas Gregor   if (!Tok.is(MMToken::Comma)) {
2647fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
2648fb912657SDouglas Gregor       << SourceRange(ConflictLoc);
2649fb912657SDouglas Gregor     return;
2650fb912657SDouglas Gregor   }
2651fb912657SDouglas Gregor   consumeToken();
2652fb912657SDouglas Gregor 
2653fb912657SDouglas Gregor   // Parse the message.
2654fb912657SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2655fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
2656fb912657SDouglas Gregor       << formatModuleId(Conflict.Id);
2657fb912657SDouglas Gregor     return;
2658fb912657SDouglas Gregor   }
2659fb912657SDouglas Gregor   Conflict.Message = Tok.getString().str();
2660fb912657SDouglas Gregor   consumeToken();
2661fb912657SDouglas Gregor 
2662fb912657SDouglas Gregor   // Add this unresolved conflict.
2663fb912657SDouglas Gregor   ActiveModule->UnresolvedConflicts.push_back(Conflict);
2664fb912657SDouglas Gregor }
2665fb912657SDouglas Gregor 
26669fc8faf9SAdrian Prantl /// Parse an inferred module declaration (wildcard modules).
26679194a91dSDouglas Gregor ///
26689194a91dSDouglas Gregor ///   module-declaration:
26699194a91dSDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
26709194a91dSDouglas Gregor ///       { inferred-module-member* }
26719194a91dSDouglas Gregor ///
26729194a91dSDouglas Gregor ///   inferred-module-member:
26739194a91dSDouglas Gregor ///     'export' '*'
26749194a91dSDouglas Gregor ///     'exclude' identifier
26759194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
267673441091SDouglas Gregor   assert(Tok.is(MMToken::Star));
267773441091SDouglas Gregor   SourceLocation StarLoc = consumeToken();
267873441091SDouglas Gregor   bool Failed = false;
267973441091SDouglas Gregor 
268073441091SDouglas Gregor   // Inferred modules must be submodules.
26819194a91dSDouglas Gregor   if (!ActiveModule && !Framework) {
268273441091SDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
268373441091SDouglas Gregor     Failed = true;
268473441091SDouglas Gregor   }
268573441091SDouglas Gregor 
26869194a91dSDouglas Gregor   if (ActiveModule) {
2687524e33e1SDouglas Gregor     // Inferred modules must have umbrella directories.
26884898cde4SBen Langmuir     if (!Failed && ActiveModule->IsAvailable &&
26894898cde4SBen Langmuir         !ActiveModule->getUmbrellaDir()) {
269073441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
269173441091SDouglas Gregor       Failed = true;
269273441091SDouglas Gregor     }
269373441091SDouglas Gregor 
269473441091SDouglas Gregor     // Check for redefinition of an inferred module.
2695dd005f69SDouglas Gregor     if (!Failed && ActiveModule->InferSubmodules) {
269673441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2697dd005f69SDouglas Gregor       if (ActiveModule->InferredSubmoduleLoc.isValid())
2698dd005f69SDouglas Gregor         Diags.Report(ActiveModule->InferredSubmoduleLoc,
269973441091SDouglas Gregor                      diag::note_mmap_prev_definition);
270073441091SDouglas Gregor       Failed = true;
270173441091SDouglas Gregor     }
270273441091SDouglas Gregor 
27039194a91dSDouglas Gregor     // Check for the 'framework' keyword, which is not permitted here.
27049194a91dSDouglas Gregor     if (Framework) {
27059194a91dSDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
27069194a91dSDouglas Gregor       Framework = false;
27079194a91dSDouglas Gregor     }
27089194a91dSDouglas Gregor   } else if (Explicit) {
27099194a91dSDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
27109194a91dSDouglas Gregor     Explicit = false;
27119194a91dSDouglas Gregor   }
27129194a91dSDouglas Gregor 
271373441091SDouglas Gregor   // If there were any problems with this inferred submodule, skip its body.
271473441091SDouglas Gregor   if (Failed) {
271573441091SDouglas Gregor     if (Tok.is(MMToken::LBrace)) {
271673441091SDouglas Gregor       consumeToken();
271773441091SDouglas Gregor       skipUntil(MMToken::RBrace);
271873441091SDouglas Gregor       if (Tok.is(MMToken::RBrace))
271973441091SDouglas Gregor         consumeToken();
272073441091SDouglas Gregor     }
272173441091SDouglas Gregor     HadError = true;
272273441091SDouglas Gregor     return;
272373441091SDouglas Gregor   }
272473441091SDouglas Gregor 
27259194a91dSDouglas Gregor   // Parse optional attributes.
27264442605fSBill Wendling   Attributes Attrs;
27275d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
27285d29dee0SDavide Italiano     return;
27299194a91dSDouglas Gregor 
27309194a91dSDouglas Gregor   if (ActiveModule) {
273173441091SDouglas Gregor     // Note that we have an inferred submodule.
2732dd005f69SDouglas Gregor     ActiveModule->InferSubmodules = true;
2733dd005f69SDouglas Gregor     ActiveModule->InferredSubmoduleLoc = StarLoc;
2734dd005f69SDouglas Gregor     ActiveModule->InferExplicitSubmodules = Explicit;
27359194a91dSDouglas Gregor   } else {
27369194a91dSDouglas Gregor     // We'll be inferring framework modules for this directory.
27379194a91dSDouglas Gregor     Map.InferredDirectories[Directory].InferModules = true;
2738c1d88ea5SBen Langmuir     Map.InferredDirectories[Directory].Attrs = Attrs;
2739beee15e7SBen Langmuir     Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
2740131daca0SRichard Smith     // FIXME: Handle the 'framework' keyword.
27419194a91dSDouglas Gregor   }
274273441091SDouglas Gregor 
274373441091SDouglas Gregor   // Parse the opening brace.
274473441091SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
274573441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
274673441091SDouglas Gregor     HadError = true;
274773441091SDouglas Gregor     return;
274873441091SDouglas Gregor   }
274973441091SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
275073441091SDouglas Gregor 
275173441091SDouglas Gregor   // Parse the body of the inferred submodule.
275273441091SDouglas Gregor   bool Done = false;
275373441091SDouglas Gregor   do {
275473441091SDouglas Gregor     switch (Tok.Kind) {
275573441091SDouglas Gregor     case MMToken::EndOfFile:
275673441091SDouglas Gregor     case MMToken::RBrace:
275773441091SDouglas Gregor       Done = true;
275873441091SDouglas Gregor       break;
275973441091SDouglas Gregor 
2760afd1b1c9SEugene Zelenko     case MMToken::ExcludeKeyword:
27619194a91dSDouglas Gregor       if (ActiveModule) {
27629194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2763d2d442caSCraig Topper           << (ActiveModule != nullptr);
27649194a91dSDouglas Gregor         consumeToken();
27659194a91dSDouglas Gregor         break;
27669194a91dSDouglas Gregor       }
27679194a91dSDouglas Gregor 
27689194a91dSDouglas Gregor       consumeToken();
2769306d8920SRichard Smith       // FIXME: Support string-literal module names here.
27709194a91dSDouglas Gregor       if (!Tok.is(MMToken::Identifier)) {
27719194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
27729194a91dSDouglas Gregor         break;
27739194a91dSDouglas Gregor       }
27749194a91dSDouglas Gregor 
27759194a91dSDouglas Gregor       Map.InferredDirectories[Directory].ExcludedModules
27769194a91dSDouglas Gregor         .push_back(Tok.getString());
27779194a91dSDouglas Gregor       consumeToken();
27789194a91dSDouglas Gregor       break;
27799194a91dSDouglas Gregor 
27809194a91dSDouglas Gregor     case MMToken::ExportKeyword:
27819194a91dSDouglas Gregor       if (!ActiveModule) {
27829194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2783d2d442caSCraig Topper           << (ActiveModule != nullptr);
27849194a91dSDouglas Gregor         consumeToken();
27859194a91dSDouglas Gregor         break;
27869194a91dSDouglas Gregor       }
27879194a91dSDouglas Gregor 
278873441091SDouglas Gregor       consumeToken();
278973441091SDouglas Gregor       if (Tok.is(MMToken::Star))
2790dd005f69SDouglas Gregor         ActiveModule->InferExportWildcard = true;
279173441091SDouglas Gregor       else
279273441091SDouglas Gregor         Diags.Report(Tok.getLocation(),
279373441091SDouglas Gregor                      diag::err_mmap_expected_export_wildcard);
279473441091SDouglas Gregor       consumeToken();
279573441091SDouglas Gregor       break;
279673441091SDouglas Gregor 
279773441091SDouglas Gregor     case MMToken::ExplicitKeyword:
279873441091SDouglas Gregor     case MMToken::ModuleKeyword:
279973441091SDouglas Gregor     case MMToken::HeaderKeyword:
2800b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
280173441091SDouglas Gregor     case MMToken::UmbrellaKeyword:
280273441091SDouglas Gregor     default:
28039194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2804d2d442caSCraig Topper           << (ActiveModule != nullptr);
280573441091SDouglas Gregor       consumeToken();
280673441091SDouglas Gregor       break;
280773441091SDouglas Gregor     }
280873441091SDouglas Gregor   } while (!Done);
280973441091SDouglas Gregor 
281073441091SDouglas Gregor   if (Tok.is(MMToken::RBrace))
281173441091SDouglas Gregor     consumeToken();
281273441091SDouglas Gregor   else {
281373441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
281473441091SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
281573441091SDouglas Gregor     HadError = true;
281673441091SDouglas Gregor   }
281773441091SDouglas Gregor }
281873441091SDouglas Gregor 
28199fc8faf9SAdrian Prantl /// Parse optional attributes.
28209194a91dSDouglas Gregor ///
28219194a91dSDouglas Gregor ///   attributes:
28229194a91dSDouglas Gregor ///     attribute attributes
28239194a91dSDouglas Gregor ///     attribute
28249194a91dSDouglas Gregor ///
28259194a91dSDouglas Gregor ///   attribute:
28269194a91dSDouglas Gregor ///     [ identifier ]
28279194a91dSDouglas Gregor ///
28289194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes.
28299194a91dSDouglas Gregor ///
28309194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise.
28314442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
28329194a91dSDouglas Gregor   bool HadError = false;
28339194a91dSDouglas Gregor 
28349194a91dSDouglas Gregor   while (Tok.is(MMToken::LSquare)) {
28359194a91dSDouglas Gregor     // Consume the '['.
28369194a91dSDouglas Gregor     SourceLocation LSquareLoc = consumeToken();
28379194a91dSDouglas Gregor 
28389194a91dSDouglas Gregor     // Check whether we have an attribute name here.
28399194a91dSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
28409194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
28419194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
28429194a91dSDouglas Gregor       if (Tok.is(MMToken::RSquare))
28439194a91dSDouglas Gregor         consumeToken();
28449194a91dSDouglas Gregor       HadError = true;
28459194a91dSDouglas Gregor     }
28469194a91dSDouglas Gregor 
28479194a91dSDouglas Gregor     // Decode the attribute name.
28489194a91dSDouglas Gregor     AttributeKind Attribute
28499194a91dSDouglas Gregor       = llvm::StringSwitch<AttributeKind>(Tok.getString())
285035b13eceSDouglas Gregor           .Case("exhaustive", AT_exhaustive)
285177944868SRichard Smith           .Case("extern_c", AT_extern_c)
2852ed84df00SBruno Cardoso Lopes           .Case("no_undeclared_includes", AT_no_undeclared_includes)
28539194a91dSDouglas Gregor           .Case("system", AT_system)
28549194a91dSDouglas Gregor           .Default(AT_unknown);
28559194a91dSDouglas Gregor     switch (Attribute) {
28569194a91dSDouglas Gregor     case AT_unknown:
28579194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
28589194a91dSDouglas Gregor         << Tok.getString();
28599194a91dSDouglas Gregor       break;
28609194a91dSDouglas Gregor 
28619194a91dSDouglas Gregor     case AT_system:
28629194a91dSDouglas Gregor       Attrs.IsSystem = true;
28639194a91dSDouglas Gregor       break;
286435b13eceSDouglas Gregor 
286577944868SRichard Smith     case AT_extern_c:
286677944868SRichard Smith       Attrs.IsExternC = true;
286777944868SRichard Smith       break;
286877944868SRichard Smith 
286935b13eceSDouglas Gregor     case AT_exhaustive:
287035b13eceSDouglas Gregor       Attrs.IsExhaustive = true;
287135b13eceSDouglas Gregor       break;
2872ed84df00SBruno Cardoso Lopes 
2873ed84df00SBruno Cardoso Lopes     case AT_no_undeclared_includes:
2874ed84df00SBruno Cardoso Lopes       Attrs.NoUndeclaredIncludes = true;
2875ed84df00SBruno Cardoso Lopes       break;
28769194a91dSDouglas Gregor     }
28779194a91dSDouglas Gregor     consumeToken();
28789194a91dSDouglas Gregor 
28799194a91dSDouglas Gregor     // Consume the ']'.
28809194a91dSDouglas Gregor     if (!Tok.is(MMToken::RSquare)) {
28819194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
28829194a91dSDouglas Gregor       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
28839194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
28849194a91dSDouglas Gregor       HadError = true;
28859194a91dSDouglas Gregor     }
28869194a91dSDouglas Gregor 
28879194a91dSDouglas Gregor     if (Tok.is(MMToken::RSquare))
28889194a91dSDouglas Gregor       consumeToken();
28899194a91dSDouglas Gregor   }
28909194a91dSDouglas Gregor 
28919194a91dSDouglas Gregor   return HadError;
28929194a91dSDouglas Gregor }
28939194a91dSDouglas Gregor 
28949fc8faf9SAdrian Prantl /// Parse a module map file.
2895718292f2SDouglas Gregor ///
2896718292f2SDouglas Gregor ///   module-map-file:
2897718292f2SDouglas Gregor ///     module-declaration*
2898718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
2899718292f2SDouglas Gregor   do {
2900718292f2SDouglas Gregor     switch (Tok.Kind) {
2901718292f2SDouglas Gregor     case MMToken::EndOfFile:
2902718292f2SDouglas Gregor       return HadError;
2903718292f2SDouglas Gregor 
2904e7ab3669SDouglas Gregor     case MMToken::ExplicitKeyword:
290597292843SDaniel Jasper     case MMToken::ExternKeyword:
2906718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
2907755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
2908718292f2SDouglas Gregor       parseModuleDecl();
2909718292f2SDouglas Gregor       break;
2910718292f2SDouglas Gregor 
29111fb5c3a6SDouglas Gregor     case MMToken::Comma:
291235b13eceSDouglas Gregor     case MMToken::ConfigMacros:
2913fb912657SDouglas Gregor     case MMToken::Conflict:
2914a3feee2aSRichard Smith     case MMToken::Exclaim:
291559527666SDouglas Gregor     case MMToken::ExcludeKeyword:
29162b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
2917f0b11de2SDouglas Gregor     case MMToken::ExportAsKeyword:
2918718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
2919718292f2SDouglas Gregor     case MMToken::Identifier:
2920718292f2SDouglas Gregor     case MMToken::LBrace:
29216ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
2922a686e1b0SDouglas Gregor     case MMToken::LSquare:
29232b82c2a5SDouglas Gregor     case MMToken::Period:
2924b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
2925718292f2SDouglas Gregor     case MMToken::RBrace:
2926a686e1b0SDouglas Gregor     case MMToken::RSquare:
29271fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
29282b82c2a5SDouglas Gregor     case MMToken::Star:
2929718292f2SDouglas Gregor     case MMToken::StringLiteral:
2930040e1266SRichard Smith     case MMToken::IntegerLiteral:
2931b8afebe2SRichard Smith     case MMToken::TextualKeyword:
2932718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
2933ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
2934718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
2935718292f2SDouglas Gregor       HadError = true;
2936718292f2SDouglas Gregor       consumeToken();
2937718292f2SDouglas Gregor       break;
2938718292f2SDouglas Gregor     }
2939718292f2SDouglas Gregor   } while (true);
2940718292f2SDouglas Gregor }
2941718292f2SDouglas Gregor 
29429acb99e3SRichard Smith bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
2943c192d194SBruno Cardoso Lopes                                    const DirectoryEntry *Dir, FileID ID,
29448128f332SRichard Smith                                    unsigned *Offset,
2945ae6df27eSRichard Smith                                    SourceLocation ExternModuleLoc) {
29468128f332SRichard Smith   assert(Target && "Missing target information");
29474ddf2221SDouglas Gregor   llvm::DenseMap<const FileEntry *, bool>::iterator Known
29484ddf2221SDouglas Gregor     = ParsedModuleMap.find(File);
29494ddf2221SDouglas Gregor   if (Known != ParsedModuleMap.end())
29504ddf2221SDouglas Gregor     return Known->second;
29514ddf2221SDouglas Gregor 
29528128f332SRichard Smith   // If the module map file wasn't already entered, do so now.
29538128f332SRichard Smith   if (ID.isInvalid()) {
2954f3f84616SRichard Smith     auto FileCharacter =
2955f3f84616SRichard Smith         IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
29568128f332SRichard Smith     ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
29578128f332SRichard Smith   }
29588128f332SRichard Smith 
29598128f332SRichard Smith   assert(Target && "Missing target information");
29601f76c4e8SManuel Klimek   const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID);
2961718292f2SDouglas Gregor   if (!Buffer)
29624ddf2221SDouglas Gregor     return ParsedModuleMap[File] = true;
29638128f332SRichard Smith   assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
29648128f332SRichard Smith          "invalid buffer offset");
2965718292f2SDouglas Gregor 
2966718292f2SDouglas Gregor   // Parse this module map file.
29678128f332SRichard Smith   Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
29688128f332SRichard Smith           Buffer->getBufferStart(),
29698128f332SRichard Smith           Buffer->getBufferStart() + (Offset ? *Offset : 0),
29708128f332SRichard Smith           Buffer->getBufferEnd());
29712a6edb30SRichard Smith   SourceLocation Start = L.getSourceLocation();
2972beee15e7SBen Langmuir   ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
2973c192d194SBruno Cardoso Lopes                          IsSystem);
2974718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
29754ddf2221SDouglas Gregor   ParsedModuleMap[File] = Result;
29762a6edb30SRichard Smith 
29778128f332SRichard Smith   if (Offset) {
29788128f332SRichard Smith     auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
29798128f332SRichard Smith     assert(Loc.first == ID && "stopped in a different file?");
29808128f332SRichard Smith     *Offset = Loc.second;
29818128f332SRichard Smith   }
29828128f332SRichard Smith 
29832a6edb30SRichard Smith   // Notify callbacks that we parsed it.
29842a6edb30SRichard Smith   for (const auto &Cb : Callbacks)
29852a6edb30SRichard Smith     Cb->moduleMapFileRead(Start, *File, IsSystem);
29868587dfd9SBruno Cardoso Lopes 
2987718292f2SDouglas Gregor   return Result;
2988718292f2SDouglas Gregor }
2989