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"
25afd1b1c9SEugene Zelenko #include "clang/Basic/VirtualFileSystem.h"
26b146baabSArgyrios Kyrtzidis #include "clang/Lex/HeaderSearch.h"
279acb99e3SRichard Smith #include "clang/Lex/HeaderSearchOptions.h"
283a02247dSChandler Carruth #include "clang/Lex/LexDiagnostic.h"
293a02247dSChandler Carruth #include "clang/Lex/Lexer.h"
303a02247dSChandler Carruth #include "clang/Lex/LiteralSupport.h"
31afd1b1c9SEugene Zelenko #include "clang/Lex/Token.h"
32afd1b1c9SEugene Zelenko #include "llvm/ADT/DenseMap.h"
33afd1b1c9SEugene Zelenko #include "llvm/ADT/None.h"
34afd1b1c9SEugene Zelenko #include "llvm/ADT/STLExtras.h"
35afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallPtrSet.h"
36afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallString.h"
37afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallVector.h"
38afd1b1c9SEugene Zelenko #include "llvm/ADT/StringMap.h"
393a02247dSChandler Carruth #include "llvm/ADT/StringRef.h"
403a02247dSChandler Carruth #include "llvm/ADT/StringSwitch.h"
41718292f2SDouglas Gregor #include "llvm/Support/Allocator.h"
42afd1b1c9SEugene Zelenko #include "llvm/Support/Compiler.h"
43afd1b1c9SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
44afd1b1c9SEugene Zelenko #include "llvm/Support/MemoryBuffer.h"
45552c169eSRafael Espindola #include "llvm/Support/Path.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 
57*a3b5f71eSBruno Cardoso Lopes void ModuleMap::resolveLinkAsDependencies(Module *Mod) {
58*a3b5f71eSBruno Cardoso Lopes   auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name);
59*a3b5f71eSBruno Cardoso Lopes   if (PendingLinkAs != PendingLinkAsModule.end()) {
60*a3b5f71eSBruno Cardoso Lopes     for (auto &Name : PendingLinkAs->second) {
61*a3b5f71eSBruno Cardoso Lopes       auto *M = findModule(Name.getKey());
62*a3b5f71eSBruno Cardoso Lopes       if (M)
63*a3b5f71eSBruno Cardoso Lopes         M->UseExportAsModuleLinkName = true;
64*a3b5f71eSBruno Cardoso Lopes     }
65*a3b5f71eSBruno Cardoso Lopes   }
66*a3b5f71eSBruno Cardoso Lopes }
67*a3b5f71eSBruno Cardoso Lopes 
68*a3b5f71eSBruno Cardoso Lopes void ModuleMap::addLinkAsDependency(Module *Mod) {
69*a3b5f71eSBruno Cardoso Lopes   if (findModule(Mod->ExportAsModule))
70*a3b5f71eSBruno Cardoso Lopes     Mod->UseExportAsModuleLinkName = true;
71*a3b5f71eSBruno Cardoso Lopes   else
72*a3b5f71eSBruno Cardoso Lopes     PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name);
73*a3b5f71eSBruno Cardoso Lopes }
74*a3b5f71eSBruno 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 
1541d60987fSRichard Smith /// \brief 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 
1731d60987fSRichard Smith const FileEntry *
174040e1266SRichard Smith ModuleMap::findHeader(Module *M,
175040e1266SRichard Smith                       const Module::UnresolvedHeaderDirective &Header,
1761d60987fSRichard Smith                       SmallVectorImpl<char> &RelativePathName) {
177040e1266SRichard Smith   auto GetFile = [&](StringRef Filename) -> const FileEntry * {
178040e1266SRichard Smith     auto *File = SourceMgr.getFileManager().getFile(Filename);
179040e1266SRichard Smith     if (!File ||
180040e1266SRichard Smith         (Header.Size && File->getSize() != *Header.Size) ||
181040e1266SRichard Smith         (Header.ModTime && File->getModificationTime() != *Header.ModTime))
182040e1266SRichard Smith       return nullptr;
183040e1266SRichard Smith     return File;
184040e1266SRichard Smith   };
185040e1266SRichard Smith 
1861d60987fSRichard Smith   if (llvm::sys::path::is_absolute(Header.FileName)) {
1871d60987fSRichard Smith     RelativePathName.clear();
1881d60987fSRichard Smith     RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
189040e1266SRichard Smith     return GetFile(Header.FileName);
1901d60987fSRichard Smith   }
1911d60987fSRichard Smith 
1921d60987fSRichard Smith   // Search for the header file within the module's home directory.
1931d60987fSRichard Smith   auto *Directory = M->Directory;
1941d60987fSRichard Smith   SmallString<128> FullPathName(Directory->getName());
1951d60987fSRichard Smith   unsigned FullPathLength = FullPathName.size();
1961d60987fSRichard Smith 
1971d60987fSRichard Smith   if (M->isPartOfFramework()) {
1981d60987fSRichard Smith     appendSubframeworkPaths(M, RelativePathName);
1991d60987fSRichard Smith     unsigned RelativePathLength = RelativePathName.size();
2001d60987fSRichard Smith 
2011d60987fSRichard Smith     // Check whether this file is in the public headers.
2021d60987fSRichard Smith     llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
2031d60987fSRichard Smith     llvm::sys::path::append(FullPathName, RelativePathName);
204040e1266SRichard Smith     if (auto *File = GetFile(FullPathName))
2051d60987fSRichard Smith       return File;
2061d60987fSRichard Smith 
2071d60987fSRichard Smith     // Check whether this file is in the private headers.
2081d60987fSRichard Smith     // Ideally, private modules in the form 'FrameworkName.Private' should
2091d60987fSRichard Smith     // be defined as 'module FrameworkName.Private', and not as
2101d60987fSRichard Smith     // 'framework module FrameworkName.Private', since a 'Private.Framework'
2111d60987fSRichard Smith     // does not usually exist. However, since both are currently widely used
2121d60987fSRichard Smith     // for private modules, make sure we find the right path in both cases.
2131d60987fSRichard Smith     if (M->IsFramework && M->Name == "Private")
2141d60987fSRichard Smith       RelativePathName.clear();
2151d60987fSRichard Smith     else
2161d60987fSRichard Smith       RelativePathName.resize(RelativePathLength);
2171d60987fSRichard Smith     FullPathName.resize(FullPathLength);
2181d60987fSRichard Smith     llvm::sys::path::append(RelativePathName, "PrivateHeaders",
2191d60987fSRichard Smith                             Header.FileName);
2201d60987fSRichard Smith     llvm::sys::path::append(FullPathName, RelativePathName);
221040e1266SRichard Smith     return GetFile(FullPathName);
2221d60987fSRichard Smith   }
2231d60987fSRichard Smith 
2241d60987fSRichard Smith   // Lookup for normal headers.
2251d60987fSRichard Smith   llvm::sys::path::append(RelativePathName, Header.FileName);
2261d60987fSRichard Smith   llvm::sys::path::append(FullPathName, RelativePathName);
227040e1266SRichard Smith   return GetFile(FullPathName);
2281d60987fSRichard Smith }
2291d60987fSRichard Smith 
230040e1266SRichard Smith void ModuleMap::resolveHeader(Module *Mod,
231040e1266SRichard Smith                               const Module::UnresolvedHeaderDirective &Header) {
232040e1266SRichard Smith   SmallString<128> RelativePathName;
233040e1266SRichard Smith   if (const FileEntry *File = findHeader(Mod, Header, RelativePathName)) {
234040e1266SRichard Smith     if (Header.IsUmbrella) {
235040e1266SRichard Smith       const DirectoryEntry *UmbrellaDir = File->getDir();
236040e1266SRichard Smith       if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
237040e1266SRichard Smith         Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
238040e1266SRichard Smith           << UmbrellaMod->getFullModuleName();
239040e1266SRichard Smith       else
240040e1266SRichard Smith         // Record this umbrella header.
241040e1266SRichard Smith         setUmbrellaHeader(Mod, File, RelativePathName.str());
242040e1266SRichard Smith     } else {
243040e1266SRichard Smith       Module::Header H = {RelativePathName.str(), File};
244040e1266SRichard Smith       if (Header.Kind == Module::HK_Excluded)
245040e1266SRichard Smith         excludeHeader(Mod, H);
246040e1266SRichard Smith       else
247040e1266SRichard Smith         addHeader(Mod, H, headerKindToRole(Header.Kind));
248040e1266SRichard Smith     }
249040e1266SRichard Smith   } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
250040e1266SRichard Smith     // There's a builtin header but no corresponding on-disk header. Assume
251040e1266SRichard Smith     // this was supposed to modularize the builtin header alone.
252040e1266SRichard Smith   } else if (Header.Kind == Module::HK_Excluded) {
253040e1266SRichard Smith     // Ignore missing excluded header files. They're optional anyway.
254040e1266SRichard Smith   } else {
255040e1266SRichard Smith     // If we find a module that has a missing header, we mark this module as
256040e1266SRichard Smith     // unavailable and store the header directive for displaying diagnostics.
257040e1266SRichard Smith     Mod->MissingHeaders.push_back(Header);
258040e1266SRichard Smith     // A missing header with stat information doesn't make the module
259040e1266SRichard Smith     // unavailable; this keeps our behavior consistent as headers are lazily
260040e1266SRichard Smith     // resolved. (Such a module still can't be built though, except from
261040e1266SRichard Smith     // preprocessed source.)
262040e1266SRichard Smith     if (!Header.Size && !Header.ModTime)
263040e1266SRichard Smith       Mod->markUnavailable();
264040e1266SRichard Smith   }
265040e1266SRichard Smith }
266040e1266SRichard Smith 
267040e1266SRichard Smith bool ModuleMap::resolveAsBuiltinHeader(
268040e1266SRichard Smith     Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
269040e1266SRichard Smith   if (Header.Kind == Module::HK_Excluded ||
270040e1266SRichard Smith       llvm::sys::path::is_absolute(Header.FileName) ||
271040e1266SRichard Smith       Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
272040e1266SRichard Smith       !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
273040e1266SRichard Smith       !isBuiltinHeader(Header.FileName))
274040e1266SRichard Smith     return false;
2751d60987fSRichard Smith 
2761d60987fSRichard Smith   // This is a system module with a top-level header. This header
2771d60987fSRichard Smith   // may have a counterpart (or replacement) in the set of headers
2781d60987fSRichard Smith   // supplied by Clang. Find that builtin header.
279040e1266SRichard Smith   SmallString<128> Path;
280040e1266SRichard Smith   llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
281040e1266SRichard Smith   auto *File = SourceMgr.getFileManager().getFile(Path);
282040e1266SRichard Smith   if (!File)
283040e1266SRichard Smith     return false;
284040e1266SRichard Smith 
285040e1266SRichard Smith   auto Role = headerKindToRole(Header.Kind);
286040e1266SRichard Smith   Module::Header H = {Path.str(), File};
287040e1266SRichard Smith   addHeader(Mod, H, Role);
288040e1266SRichard Smith   return true;
2891d60987fSRichard Smith }
2901d60987fSRichard Smith 
2910761a8a0SDaniel Jasper ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
292b146baabSArgyrios Kyrtzidis                      const LangOptions &LangOpts, const TargetInfo *Target,
293b146baabSArgyrios Kyrtzidis                      HeaderSearch &HeaderInfo)
2940761a8a0SDaniel Jasper     : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
295056bf77fSRichard Smith       HeaderInfo(HeaderInfo) {
2960414b857SRichard Smith   MMapLangOpts.LineComment = true;
2970414b857SRichard Smith }
298718292f2SDouglas Gregor 
299718292f2SDouglas Gregor ModuleMap::~ModuleMap() {
30021668754SDavide Italiano   for (auto &M : Modules)
30121668754SDavide Italiano     delete M.getValue();
3028587dfd9SBruno Cardoso Lopes   for (auto *M : ShadowModules)
3038587dfd9SBruno Cardoso Lopes     delete M;
304718292f2SDouglas Gregor }
305718292f2SDouglas Gregor 
30689929282SDouglas Gregor void ModuleMap::setTarget(const TargetInfo &Target) {
30789929282SDouglas Gregor   assert((!this->Target || this->Target == &Target) &&
30889929282SDouglas Gregor          "Improper target override");
30989929282SDouglas Gregor   this->Target = &Target;
31089929282SDouglas Gregor }
31189929282SDouglas Gregor 
312056396aeSDouglas Gregor /// \brief "Sanitize" a filename so that it can be used as an identifier.
313056396aeSDouglas Gregor static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
314056396aeSDouglas Gregor                                               SmallVectorImpl<char> &Buffer) {
315056396aeSDouglas Gregor   if (Name.empty())
316056396aeSDouglas Gregor     return Name;
317056396aeSDouglas Gregor 
318a7d03840SJordan Rose   if (!isValidIdentifier(Name)) {
319056396aeSDouglas Gregor     // If we don't already have something with the form of an identifier,
320056396aeSDouglas Gregor     // create a buffer with the sanitized name.
321056396aeSDouglas Gregor     Buffer.clear();
322a7d03840SJordan Rose     if (isDigit(Name[0]))
323056396aeSDouglas Gregor       Buffer.push_back('_');
324056396aeSDouglas Gregor     Buffer.reserve(Buffer.size() + Name.size());
325056396aeSDouglas Gregor     for (unsigned I = 0, N = Name.size(); I != N; ++I) {
326a7d03840SJordan Rose       if (isIdentifierBody(Name[I]))
327056396aeSDouglas Gregor         Buffer.push_back(Name[I]);
328056396aeSDouglas Gregor       else
329056396aeSDouglas Gregor         Buffer.push_back('_');
330056396aeSDouglas Gregor     }
331056396aeSDouglas Gregor 
332056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
333056396aeSDouglas Gregor   }
334056396aeSDouglas Gregor 
335056396aeSDouglas Gregor   while (llvm::StringSwitch<bool>(Name)
336056396aeSDouglas Gregor #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
337056396aeSDouglas Gregor #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
338056396aeSDouglas Gregor #include "clang/Basic/TokenKinds.def"
339056396aeSDouglas Gregor            .Default(false)) {
340056396aeSDouglas Gregor     if (Name.data() != Buffer.data())
341056396aeSDouglas Gregor       Buffer.append(Name.begin(), Name.end());
342056396aeSDouglas Gregor     Buffer.push_back('_');
343056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
344056396aeSDouglas Gregor   }
345056396aeSDouglas Gregor 
346056396aeSDouglas Gregor   return Name;
347056396aeSDouglas Gregor }
348056396aeSDouglas Gregor 
34934d52749SDouglas Gregor /// \brief Determine whether the given file name is the name of a builtin
35034d52749SDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system
35134d52749SDouglas Gregor /// headers.
352ba1b5c98SBruno Cardoso Lopes bool ModuleMap::isBuiltinHeader(StringRef FileName) {
35334d52749SDouglas Gregor   return llvm::StringSwitch<bool>(FileName)
35434d52749SDouglas Gregor            .Case("float.h", true)
35534d52749SDouglas Gregor            .Case("iso646.h", true)
35634d52749SDouglas Gregor            .Case("limits.h", true)
35734d52749SDouglas Gregor            .Case("stdalign.h", true)
35834d52749SDouglas Gregor            .Case("stdarg.h", true)
3593c4b1290SBen Langmuir            .Case("stdatomic.h", true)
36034d52749SDouglas Gregor            .Case("stdbool.h", true)
36134d52749SDouglas Gregor            .Case("stddef.h", true)
36234d52749SDouglas Gregor            .Case("stdint.h", true)
36334d52749SDouglas Gregor            .Case("tgmath.h", true)
36434d52749SDouglas Gregor            .Case("unwind.h", true)
36534d52749SDouglas Gregor            .Default(false);
36634d52749SDouglas Gregor }
36734d52749SDouglas Gregor 
36892669ee4SDaniel Jasper ModuleMap::HeadersMap::iterator
36992669ee4SDaniel Jasper ModuleMap::findKnownHeader(const FileEntry *File) {
370040e1266SRichard Smith   resolveHeaderDirectives(File);
37159527666SDouglas Gregor   HeadersMap::iterator Known = Headers.find(File);
37247972afdSRichard Smith   if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
37347972afdSRichard Smith       Known == Headers.end() && File->getDir() == BuiltinIncludeDir &&
374ba1b5c98SBruno Cardoso Lopes       ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()))) {
3754eaf0a6cSDaniel Jasper     HeaderInfo.loadTopLevelSystemModules();
37692669ee4SDaniel Jasper     return Headers.find(File);
3774eaf0a6cSDaniel Jasper   }
37892669ee4SDaniel Jasper   return Known;
37992669ee4SDaniel Jasper }
38092669ee4SDaniel Jasper 
3814469138eSBen Langmuir ModuleMap::KnownHeader
3824469138eSBen Langmuir ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
3834469138eSBen Langmuir                     SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
38447972afdSRichard Smith   if (UmbrellaDirs.empty())
385afd1b1c9SEugene Zelenko     return {};
38647972afdSRichard Smith 
3874469138eSBen Langmuir   const DirectoryEntry *Dir = File->getDir();
3884469138eSBen Langmuir   assert(Dir && "file in no directory");
3894469138eSBen Langmuir 
3904469138eSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
3914469138eSBen Langmuir   // frameworks moving from top-level frameworks to embedded frameworks tend
3924469138eSBen Langmuir   // to be symlinked from the top-level location to the embedded location,
3934469138eSBen Langmuir   // and we need to resolve lookups as if we had found the embedded location.
3944469138eSBen Langmuir   StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
3954469138eSBen Langmuir 
3964469138eSBen Langmuir   // Keep walking up the directory hierarchy, looking for a directory with
3974469138eSBen Langmuir   // an umbrella header.
3984469138eSBen Langmuir   do {
3994469138eSBen Langmuir     auto KnownDir = UmbrellaDirs.find(Dir);
4004469138eSBen Langmuir     if (KnownDir != UmbrellaDirs.end())
4014469138eSBen Langmuir       return KnownHeader(KnownDir->second, NormalHeader);
4024469138eSBen Langmuir 
4034469138eSBen Langmuir     IntermediateDirs.push_back(Dir);
4044469138eSBen Langmuir 
4054469138eSBen Langmuir     // Retrieve our parent path.
4064469138eSBen Langmuir     DirName = llvm::sys::path::parent_path(DirName);
4074469138eSBen Langmuir     if (DirName.empty())
4084469138eSBen Langmuir       break;
4094469138eSBen Langmuir 
4104469138eSBen Langmuir     // Resolve the parent path to a directory entry.
4114469138eSBen Langmuir     Dir = SourceMgr.getFileManager().getDirectory(DirName);
4124469138eSBen Langmuir   } while (Dir);
413afd1b1c9SEugene Zelenko   return {};
4144469138eSBen Langmuir }
4154469138eSBen Langmuir 
41692669ee4SDaniel Jasper static bool violatesPrivateInclude(Module *RequestingModule,
41792669ee4SDaniel Jasper                                    const FileEntry *IncFileEnt,
4184eb8393cSRichard Smith                                    ModuleMap::KnownHeader Header) {
41992669ee4SDaniel Jasper #ifndef NDEBUG
4204eb8393cSRichard Smith   if (Header.getRole() & ModuleMap::PrivateHeader) {
42192669ee4SDaniel Jasper     // Check for consistency between the module header role
42292669ee4SDaniel Jasper     // as obtained from the lookup and as obtained from the module.
42392669ee4SDaniel Jasper     // This check is not cheap, so enable it only for debugging.
4242708e520SRichard Smith     bool IsPrivate = false;
4252708e520SRichard Smith     SmallVectorImpl<Module::Header> *HeaderList[] = {
4264eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_Private],
4274eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_PrivateTextual]};
4282708e520SRichard Smith     for (auto *Hs : HeaderList)
4292708e520SRichard Smith       IsPrivate |=
4302708e520SRichard Smith           std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) {
4313c1a41adSRichard Smith             return H.Entry == IncFileEnt;
4322708e520SRichard Smith           }) != Hs->end();
4334eb8393cSRichard Smith     assert(IsPrivate && "inconsistent headers and roles");
43400bc95ecSRichard Smith   }
43592669ee4SDaniel Jasper #endif
4364eb8393cSRichard Smith   return !Header.isAccessibleFrom(RequestingModule);
43792669ee4SDaniel Jasper }
43892669ee4SDaniel Jasper 
43971e1a64fSBen Langmuir static Module *getTopLevelOrNull(Module *M) {
44071e1a64fSBen Langmuir   return M ? M->getTopLevelModule() : nullptr;
44171e1a64fSBen Langmuir }
44271e1a64fSBen Langmuir 
44392669ee4SDaniel Jasper void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
4448d4e90b3SRichard Smith                                         bool RequestingModuleIsModuleInterface,
44592669ee4SDaniel Jasper                                         SourceLocation FilenameLoc,
44692669ee4SDaniel Jasper                                         StringRef Filename,
44792669ee4SDaniel Jasper                                         const FileEntry *File) {
44892669ee4SDaniel Jasper   // No errors for indirect modules. This may be a bit of a problem for modules
44992669ee4SDaniel Jasper   // with no source files.
45071e1a64fSBen Langmuir   if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
45192669ee4SDaniel Jasper     return;
45292669ee4SDaniel Jasper 
453040e1266SRichard Smith   if (RequestingModule) {
45492669ee4SDaniel Jasper     resolveUses(RequestingModule, /*Complain=*/false);
455040e1266SRichard Smith     resolveHeaderDirectives(RequestingModule);
456040e1266SRichard Smith   }
45792669ee4SDaniel Jasper 
45871e1a64fSBen Langmuir   bool Excluded = false;
459d2d442caSCraig Topper   Module *Private = nullptr;
460d2d442caSCraig Topper   Module *NotUsed = nullptr;
46171e1a64fSBen Langmuir 
46271e1a64fSBen Langmuir   HeadersMap::iterator Known = findKnownHeader(File);
46371e1a64fSBen Langmuir   if (Known != Headers.end()) {
46471e1a64fSBen Langmuir     for (const KnownHeader &Header : Known->second) {
46592669ee4SDaniel Jasper       // Remember private headers for later printing of a diagnostic.
4664eb8393cSRichard Smith       if (violatesPrivateInclude(RequestingModule, File, Header)) {
46771e1a64fSBen Langmuir         Private = Header.getModule();
46892669ee4SDaniel Jasper         continue;
46992669ee4SDaniel Jasper       }
47092669ee4SDaniel Jasper 
47192669ee4SDaniel Jasper       // If uses need to be specified explicitly, we are only allowed to return
47292669ee4SDaniel Jasper       // modules that are explicitly used by the requesting module.
47392669ee4SDaniel Jasper       if (RequestingModule && LangOpts.ModulesDeclUse &&
4748f4d3ff1SRichard Smith           !RequestingModule->directlyUses(Header.getModule())) {
47571e1a64fSBen Langmuir         NotUsed = Header.getModule();
47692669ee4SDaniel Jasper         continue;
47792669ee4SDaniel Jasper       }
47892669ee4SDaniel Jasper 
47992669ee4SDaniel Jasper       // We have found a module that we can happily use.
48092669ee4SDaniel Jasper       return;
48192669ee4SDaniel Jasper     }
482feb54b6dSRichard Smith 
483feb54b6dSRichard Smith     Excluded = true;
48471e1a64fSBen Langmuir   }
48592669ee4SDaniel Jasper 
48692669ee4SDaniel Jasper   // We have found a header, but it is private.
487d2d442caSCraig Topper   if (Private) {
48811152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
48992669ee4SDaniel Jasper         << Filename;
49092669ee4SDaniel Jasper     return;
49192669ee4SDaniel Jasper   }
49292669ee4SDaniel Jasper 
49392669ee4SDaniel Jasper   // We have found a module, but we don't use it.
494d2d442caSCraig Topper   if (NotUsed) {
49511152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
4964ea330c8SDaniel Jasper         << RequestingModule->getTopLevelModule()->Name << Filename;
49792669ee4SDaniel Jasper     return;
49892669ee4SDaniel Jasper   }
49992669ee4SDaniel Jasper 
50071e1a64fSBen Langmuir   if (Excluded || isHeaderInUmbrellaDirs(File))
50171e1a64fSBen Langmuir     return;
50271e1a64fSBen Langmuir 
50371e1a64fSBen Langmuir   // At this point, only non-modular includes remain.
50471e1a64fSBen Langmuir 
50571e1a64fSBen Langmuir   if (LangOpts.ModulesStrictDeclUse) {
50611152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5074ea330c8SDaniel Jasper         << RequestingModule->getTopLevelModule()->Name << Filename;
508a67e4d32SManman Ren   } else if (RequestingModule && RequestingModuleIsModuleInterface &&
509a67e4d32SManman Ren              LangOpts.isCompilingModule()) {
510a67e4d32SManman Ren     // Do not diagnose when we are not compiling a module.
51171e1a64fSBen Langmuir     diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
51271e1a64fSBen Langmuir         diag::warn_non_modular_include_in_framework_module :
51371e1a64fSBen Langmuir         diag::warn_non_modular_include_in_module;
51470a7738fSManman Ren     Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
51570a7738fSManman Ren         << File->getName();
51671e1a64fSBen Langmuir   }
51792669ee4SDaniel Jasper }
51892669ee4SDaniel Jasper 
519ec87a50aSRichard Smith static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
520ec87a50aSRichard Smith                                 const ModuleMap::KnownHeader &Old) {
5218b7c0398SSean Silva   // Prefer available modules.
5228b7c0398SSean Silva   if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
5238b7c0398SSean Silva     return true;
5248b7c0398SSean Silva 
525ec87a50aSRichard Smith   // Prefer a public header over a private header.
526ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::PrivateHeader) !=
527ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::PrivateHeader))
528ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::PrivateHeader);
529ec87a50aSRichard Smith 
530ec87a50aSRichard Smith   // Prefer a non-textual header over a textual header.
531ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::TextualHeader) !=
532ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::TextualHeader))
533ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::TextualHeader);
534ec87a50aSRichard Smith 
535ec87a50aSRichard Smith   // Don't have a reason to choose between these. Just keep the first one.
536ec87a50aSRichard Smith   return false;
537ec87a50aSRichard Smith }
538ec87a50aSRichard Smith 
539ed84df00SBruno Cardoso Lopes ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
540ed84df00SBruno Cardoso Lopes                                                       bool AllowTextual) {
541306d8920SRichard Smith   auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
542ed84df00SBruno Cardoso Lopes     if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
543afd1b1c9SEugene Zelenko       return {};
544306d8920SRichard Smith     return R;
545306d8920SRichard Smith   };
546306d8920SRichard Smith 
5474881e8b2SSean Silva   HeadersMap::iterator Known = findKnownHeader(File);
5481fb5c3a6SDouglas Gregor   if (Known != Headers.end()) {
549202210b3SRichard Smith     ModuleMap::KnownHeader Result;
55097da9178SDaniel Jasper     // Iterate over all modules that 'File' is part of to find the best fit.
5514881e8b2SSean Silva     for (KnownHeader &H : Known->second) {
5527e82e019SRichard Smith       // Prefer a header from the source module over all others.
5537e82e019SRichard Smith       if (H.getModule()->getTopLevelModule() == SourceModule)
5542f633e7cSRichard Smith         return MakeResult(H);
5554881e8b2SSean Silva       if (!Result || isBetterKnownHeader(H, Result))
5564881e8b2SSean Silva         Result = H;
55797da9178SDaniel Jasper     }
558306d8920SRichard Smith     return MakeResult(Result);
5591fb5c3a6SDouglas Gregor   }
560ab0c8a84SDouglas Gregor 
561386bb073SRichard Smith   return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
562386bb073SRichard Smith }
563386bb073SRichard Smith 
564386bb073SRichard Smith ModuleMap::KnownHeader
565386bb073SRichard Smith ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
566386bb073SRichard Smith   assert(!Headers.count(File) && "already have a module for this header");
567386bb073SRichard Smith 
568f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
5694469138eSBen Langmuir   KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
5704469138eSBen Langmuir   if (H) {
5714469138eSBen Langmuir     Module *Result = H.getModule();
572930a85ccSDouglas Gregor 
573930a85ccSDouglas Gregor     // Search up the module stack until we find a module with an umbrella
57473141fa9SDouglas Gregor     // directory.
575930a85ccSDouglas Gregor     Module *UmbrellaModule = Result;
57673141fa9SDouglas Gregor     while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
577930a85ccSDouglas Gregor       UmbrellaModule = UmbrellaModule->Parent;
578930a85ccSDouglas Gregor 
579930a85ccSDouglas Gregor     if (UmbrellaModule->InferSubmodules) {
5809d6448b1SBen Langmuir       const FileEntry *UmbrellaModuleMap =
5819d6448b1SBen Langmuir           getModuleMapFileForUniquing(UmbrellaModule);
5829d6448b1SBen Langmuir 
583a89c5ac4SDouglas Gregor       // Infer submodules for each of the directories we found between
584a89c5ac4SDouglas Gregor       // the directory of the umbrella header and the directory where
585a89c5ac4SDouglas Gregor       // the actual header is located.
5869458f82dSDouglas Gregor       bool Explicit = UmbrellaModule->InferExplicitSubmodules;
5879458f82dSDouglas Gregor 
5887033127bSDouglas Gregor       for (unsigned I = SkippedDirs.size(); I != 0; --I) {
589a89c5ac4SDouglas Gregor         // Find or create the module that corresponds to this directory name.
590056396aeSDouglas Gregor         SmallString<32> NameBuf;
591056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
5924469138eSBen Langmuir             llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
5939d6448b1SBen Langmuir         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
5949d6448b1SBen Langmuir                                     Explicit).first;
5959d6448b1SBen Langmuir         InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
596ffbafa2aSBen Langmuir         Result->IsInferred = true;
597a89c5ac4SDouglas Gregor 
598a89c5ac4SDouglas Gregor         // Associate the module and the directory.
599a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I-1]] = Result;
600a89c5ac4SDouglas Gregor 
601a89c5ac4SDouglas Gregor         // If inferred submodules export everything they import, add a
602a89c5ac4SDouglas Gregor         // wildcard to the set of exports.
603930a85ccSDouglas Gregor         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
604d2d442caSCraig Topper           Result->Exports.push_back(Module::ExportDecl(nullptr, true));
605a89c5ac4SDouglas Gregor       }
606a89c5ac4SDouglas Gregor 
607a89c5ac4SDouglas Gregor       // Infer a submodule with the same name as this header file.
608056396aeSDouglas Gregor       SmallString<32> NameBuf;
609056396aeSDouglas Gregor       StringRef Name = sanitizeFilenameAsIdentifier(
610056396aeSDouglas Gregor                          llvm::sys::path::stem(File->getName()), NameBuf);
6119d6448b1SBen Langmuir       Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6129d6448b1SBen Langmuir                                   Explicit).first;
6139d6448b1SBen Langmuir       InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
614ffbafa2aSBen Langmuir       Result->IsInferred = true;
6153c5305c1SArgyrios Kyrtzidis       Result->addTopHeader(File);
616a89c5ac4SDouglas Gregor 
617a89c5ac4SDouglas Gregor       // If inferred submodules export everything they import, add a
618a89c5ac4SDouglas Gregor       // wildcard to the set of exports.
619930a85ccSDouglas Gregor       if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
620d2d442caSCraig Topper         Result->Exports.push_back(Module::ExportDecl(nullptr, true));
621a89c5ac4SDouglas Gregor     } else {
622a89c5ac4SDouglas Gregor       // Record each of the directories we stepped through as being part of
623a89c5ac4SDouglas Gregor       // the module we found, since the umbrella header covers them all.
624a89c5ac4SDouglas Gregor       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
625a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I]] = Result;
626a89c5ac4SDouglas Gregor     }
627a89c5ac4SDouglas Gregor 
628386bb073SRichard Smith     KnownHeader Header(Result, NormalHeader);
629386bb073SRichard Smith     Headers[File].push_back(Header);
630386bb073SRichard Smith     return Header;
631a89c5ac4SDouglas Gregor   }
632a89c5ac4SDouglas Gregor 
633afd1b1c9SEugene Zelenko   return {};
634ab0c8a84SDouglas Gregor }
635ab0c8a84SDouglas Gregor 
636386bb073SRichard Smith ArrayRef<ModuleMap::KnownHeader>
637386bb073SRichard Smith ModuleMap::findAllModulesForHeader(const FileEntry *File) const {
638040e1266SRichard Smith   resolveHeaderDirectives(File);
639386bb073SRichard Smith   auto It = Headers.find(File);
640386bb073SRichard Smith   if (It == Headers.end())
641386bb073SRichard Smith     return None;
642386bb073SRichard Smith   return It->second;
643386bb073SRichard Smith }
644386bb073SRichard Smith 
645e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
646d2d442caSCraig Topper   return isHeaderUnavailableInModule(Header, nullptr);
64750996ce1SRichard Smith }
64850996ce1SRichard Smith 
64962bcd925SDmitri Gribenko bool
65062bcd925SDmitri Gribenko ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
65162bcd925SDmitri Gribenko                                        const Module *RequestingModule) const {
652040e1266SRichard Smith   resolveHeaderDirectives(Header);
653e4412640SArgyrios Kyrtzidis   HeadersMap::const_iterator Known = Headers.find(Header);
65497da9178SDaniel Jasper   if (Known != Headers.end()) {
65597da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator
65697da9178SDaniel Jasper              I = Known->second.begin(),
65797da9178SDaniel Jasper              E = Known->second.end();
65897da9178SDaniel Jasper          I != E; ++I) {
659052d95a6SBruno Cardoso Lopes 
660052d95a6SBruno Cardoso Lopes       if (I->isAvailable() &&
661052d95a6SBruno Cardoso Lopes           (!RequestingModule ||
662052d95a6SBruno Cardoso Lopes            I->getModule()->isSubModuleOf(RequestingModule))) {
663052d95a6SBruno Cardoso Lopes         // When no requesting module is available, the caller is looking if a
664052d95a6SBruno Cardoso Lopes         // header is part a module by only looking into the module map. This is
665052d95a6SBruno Cardoso Lopes         // done by warn_uncovered_module_header checks; don't consider textual
666052d95a6SBruno Cardoso Lopes         // headers part of it in this mode, otherwise we get misleading warnings
667052d95a6SBruno Cardoso Lopes         // that a umbrella header is not including a textual header.
668052d95a6SBruno Cardoso Lopes         if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
669052d95a6SBruno Cardoso Lopes           continue;
67097da9178SDaniel Jasper         return false;
67197da9178SDaniel Jasper       }
672052d95a6SBruno Cardoso Lopes     }
67397da9178SDaniel Jasper     return true;
67497da9178SDaniel Jasper   }
6751fb5c3a6SDouglas Gregor 
6761fb5c3a6SDouglas Gregor   const DirectoryEntry *Dir = Header->getDir();
677f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
6781fb5c3a6SDouglas Gregor   StringRef DirName = Dir->getName();
6791fb5c3a6SDouglas Gregor 
68050996ce1SRichard Smith   auto IsUnavailable = [&](const Module *M) {
68150996ce1SRichard Smith     return !M->isAvailable() && (!RequestingModule ||
68250996ce1SRichard Smith                                  M->isSubModuleOf(RequestingModule));
68350996ce1SRichard Smith   };
68450996ce1SRichard Smith 
6851fb5c3a6SDouglas Gregor   // Keep walking up the directory hierarchy, looking for a directory with
6861fb5c3a6SDouglas Gregor   // an umbrella header.
6871fb5c3a6SDouglas Gregor   do {
688e4412640SArgyrios Kyrtzidis     llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
6891fb5c3a6SDouglas Gregor       = UmbrellaDirs.find(Dir);
6901fb5c3a6SDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
6911fb5c3a6SDouglas Gregor       Module *Found = KnownDir->second;
69250996ce1SRichard Smith       if (IsUnavailable(Found))
6931fb5c3a6SDouglas Gregor         return true;
6941fb5c3a6SDouglas Gregor 
6951fb5c3a6SDouglas Gregor       // Search up the module stack until we find a module with an umbrella
6961fb5c3a6SDouglas Gregor       // directory.
6971fb5c3a6SDouglas Gregor       Module *UmbrellaModule = Found;
6981fb5c3a6SDouglas Gregor       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
6991fb5c3a6SDouglas Gregor         UmbrellaModule = UmbrellaModule->Parent;
7001fb5c3a6SDouglas Gregor 
7011fb5c3a6SDouglas Gregor       if (UmbrellaModule->InferSubmodules) {
7021fb5c3a6SDouglas Gregor         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
7031fb5c3a6SDouglas Gregor           // Find or create the module that corresponds to this directory name.
704056396aeSDouglas Gregor           SmallString<32> NameBuf;
705056396aeSDouglas Gregor           StringRef Name = sanitizeFilenameAsIdentifier(
706056396aeSDouglas Gregor                              llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
707056396aeSDouglas Gregor                              NameBuf);
7081fb5c3a6SDouglas Gregor           Found = lookupModuleQualified(Name, Found);
7091fb5c3a6SDouglas Gregor           if (!Found)
7101fb5c3a6SDouglas Gregor             return false;
71150996ce1SRichard Smith           if (IsUnavailable(Found))
7121fb5c3a6SDouglas Gregor             return true;
7131fb5c3a6SDouglas Gregor         }
7141fb5c3a6SDouglas Gregor 
7151fb5c3a6SDouglas Gregor         // Infer a submodule with the same name as this header file.
716056396aeSDouglas Gregor         SmallString<32> NameBuf;
717056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
718056396aeSDouglas Gregor                            llvm::sys::path::stem(Header->getName()),
719056396aeSDouglas Gregor                            NameBuf);
7201fb5c3a6SDouglas Gregor         Found = lookupModuleQualified(Name, Found);
7211fb5c3a6SDouglas Gregor         if (!Found)
7221fb5c3a6SDouglas Gregor           return false;
7231fb5c3a6SDouglas Gregor       }
7241fb5c3a6SDouglas Gregor 
72550996ce1SRichard Smith       return IsUnavailable(Found);
7261fb5c3a6SDouglas Gregor     }
7271fb5c3a6SDouglas Gregor 
7281fb5c3a6SDouglas Gregor     SkippedDirs.push_back(Dir);
7291fb5c3a6SDouglas Gregor 
7301fb5c3a6SDouglas Gregor     // Retrieve our parent path.
7311fb5c3a6SDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
7321fb5c3a6SDouglas Gregor     if (DirName.empty())
7331fb5c3a6SDouglas Gregor       break;
7341fb5c3a6SDouglas Gregor 
7351fb5c3a6SDouglas Gregor     // Resolve the parent path to a directory entry.
7361f76c4e8SManuel Klimek     Dir = SourceMgr.getFileManager().getDirectory(DirName);
7371fb5c3a6SDouglas Gregor   } while (Dir);
7381fb5c3a6SDouglas Gregor 
7391fb5c3a6SDouglas Gregor   return false;
7401fb5c3a6SDouglas Gregor }
7411fb5c3a6SDouglas Gregor 
742e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const {
743e4412640SArgyrios Kyrtzidis   llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
74488bdfb0eSDouglas Gregor   if (Known != Modules.end())
74588bdfb0eSDouglas Gregor     return Known->getValue();
74688bdfb0eSDouglas Gregor 
747d2d442caSCraig Topper   return nullptr;
74888bdfb0eSDouglas Gregor }
74988bdfb0eSDouglas Gregor 
750e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
751e4412640SArgyrios Kyrtzidis                                            Module *Context) const {
7522b82c2a5SDouglas Gregor   for(; Context; Context = Context->Parent) {
7532b82c2a5SDouglas Gregor     if (Module *Sub = lookupModuleQualified(Name, Context))
7542b82c2a5SDouglas Gregor       return Sub;
7552b82c2a5SDouglas Gregor   }
7562b82c2a5SDouglas Gregor 
7572b82c2a5SDouglas Gregor   return findModule(Name);
7582b82c2a5SDouglas Gregor }
7592b82c2a5SDouglas Gregor 
760e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
7612b82c2a5SDouglas Gregor   if (!Context)
7622b82c2a5SDouglas Gregor     return findModule(Name);
7632b82c2a5SDouglas Gregor 
764eb90e830SDouglas Gregor   return Context->findSubmodule(Name);
7652b82c2a5SDouglas Gregor }
7662b82c2a5SDouglas Gregor 
767c192d194SBruno Cardoso Lopes std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
768c192d194SBruno Cardoso Lopes                                                         Module *Parent,
769c192d194SBruno Cardoso Lopes                                                         bool IsFramework,
770c192d194SBruno Cardoso Lopes                                                         bool IsExplicit) {
77169021974SDouglas Gregor   // Try to find an existing module with this name.
772eb90e830SDouglas Gregor   if (Module *Sub = lookupModuleQualified(Name, Parent))
773eb90e830SDouglas Gregor     return std::make_pair(Sub, false);
77469021974SDouglas Gregor 
77569021974SDouglas Gregor   // Create a new module with this name.
7769ffe5a35SDavid Blaikie   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
7779ffe5a35SDavid Blaikie                               IsExplicit, NumCreatedModules++);
7786f722b4eSArgyrios Kyrtzidis   if (!Parent) {
7797e82e019SRichard Smith     if (LangOpts.CurrentModule == Name)
7807e82e019SRichard Smith       SourceModule = Result;
78169021974SDouglas Gregor     Modules[Name] = Result;
782c192d194SBruno Cardoso Lopes     ModuleScopeIDs[Result] = CurrentModuleScopeID;
7836f722b4eSArgyrios Kyrtzidis   }
78469021974SDouglas Gregor   return std::make_pair(Result, true);
78569021974SDouglas Gregor }
78669021974SDouglas Gregor 
787dd8b5337SRichard Smith Module *ModuleMap::createGlobalModuleForInterfaceUnit(SourceLocation Loc) {
788056bf77fSRichard Smith   assert(!PendingGlobalModule && "created multiple global modules");
789056bf77fSRichard Smith   PendingGlobalModule.reset(
790056bf77fSRichard Smith       new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
791056bf77fSRichard Smith                  /*IsExplicit*/ true, NumCreatedModules++));
792056bf77fSRichard Smith   PendingGlobalModule->Kind = Module::GlobalModuleFragment;
793056bf77fSRichard Smith   return PendingGlobalModule.get();
794dd8b5337SRichard Smith }
795dd8b5337SRichard Smith 
796bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
797dd8b5337SRichard Smith                                                 StringRef Name,
798dd8b5337SRichard Smith                                                 Module *GlobalModule) {
799bbcc9f04SRichard Smith   assert(LangOpts.CurrentModule == Name && "module name mismatch");
800bbcc9f04SRichard Smith   assert(!Modules[Name] && "redefining existing module");
801bbcc9f04SRichard Smith 
802bbcc9f04SRichard Smith   auto *Result =
803bbcc9f04SRichard Smith       new Module(Name, Loc, nullptr, /*IsFramework*/ false,
804bbcc9f04SRichard Smith                  /*IsExplicit*/ false, NumCreatedModules++);
805145e15a3SRichard Smith   Result->Kind = Module::ModuleInterfaceUnit;
806bbcc9f04SRichard Smith   Modules[Name] = SourceModule = Result;
807bbcc9f04SRichard Smith 
808dd8b5337SRichard Smith   // Reparent the current global module fragment as a submodule of this module.
809056bf77fSRichard Smith   assert(GlobalModule == PendingGlobalModule.get() &&
810056bf77fSRichard Smith          "unexpected global module");
811dd8b5337SRichard Smith   GlobalModule->setParent(Result);
812056bf77fSRichard Smith   PendingGlobalModule.release(); // now owned by parent
813dd8b5337SRichard Smith 
814bbcc9f04SRichard Smith   // Mark the main source file as being within the newly-created module so that
815bbcc9f04SRichard Smith   // declarations and macros are properly visibility-restricted to it.
816bbcc9f04SRichard Smith   auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
817bbcc9f04SRichard Smith   assert(MainFile && "no input file for module interface");
818bbcc9f04SRichard Smith   Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader));
819bbcc9f04SRichard Smith 
820bbcc9f04SRichard Smith   return Result;
821bbcc9f04SRichard Smith }
822bbcc9f04SRichard Smith 
82311dfe6feSDouglas Gregor /// \brief For a framework module, infer the framework against which we
82411dfe6feSDouglas Gregor /// should link.
82511dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
82611dfe6feSDouglas Gregor                                FileManager &FileMgr) {
82711dfe6feSDouglas Gregor   assert(Mod->IsFramework && "Can only infer linking for framework modules");
82811dfe6feSDouglas Gregor   assert(!Mod->isSubFramework() &&
82911dfe6feSDouglas Gregor          "Can only infer linking for top-level frameworks");
83011dfe6feSDouglas Gregor 
83111dfe6feSDouglas Gregor   SmallString<128> LibName;
83211dfe6feSDouglas Gregor   LibName += FrameworkDir->getName();
83311dfe6feSDouglas Gregor   llvm::sys::path::append(LibName, Mod->Name);
8348aaae5a9SJuergen Ributzka 
8358aaae5a9SJuergen Ributzka   // The library name of a framework has more than one possible extension since
8368aaae5a9SJuergen Ributzka   // the introduction of the text-based dynamic library format. We need to check
8378aaae5a9SJuergen Ributzka   // for both before we give up.
8388013e81dSBenjamin Kramer   for (const char *extension : {"", ".tbd"}) {
8398aaae5a9SJuergen Ributzka     llvm::sys::path::replace_extension(LibName, extension);
84011dfe6feSDouglas Gregor     if (FileMgr.getFile(LibName)) {
84111dfe6feSDouglas Gregor       Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
84211dfe6feSDouglas Gregor                                                        /*IsFramework=*/true));
8438aaae5a9SJuergen Ributzka       return;
8448aaae5a9SJuergen Ributzka     }
84511dfe6feSDouglas Gregor   }
84611dfe6feSDouglas Gregor }
84711dfe6feSDouglas Gregor 
848a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
849a525400dSBen Langmuir                                         bool IsSystem, Module *Parent) {
850c1d88ea5SBen Langmuir   Attributes Attrs;
851c1d88ea5SBen Langmuir   Attrs.IsSystem = IsSystem;
852a525400dSBen Langmuir   return inferFrameworkModule(FrameworkDir, Attrs, Parent);
853c1d88ea5SBen Langmuir }
854c1d88ea5SBen Langmuir 
855a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
856c1d88ea5SBen Langmuir                                         Attributes Attrs, Module *Parent) {
857a525400dSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
858a525400dSBen Langmuir   // we might be looking at an embedded framework that symlinks out to a
859a525400dSBen Langmuir   // top-level framework, and we need to infer as if we were naming the
860a525400dSBen Langmuir   // top-level framework.
861a525400dSBen Langmuir   StringRef FrameworkDirName =
862a525400dSBen Langmuir       SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
863a525400dSBen Langmuir 
864a525400dSBen Langmuir   // In case this is a case-insensitive filesystem, use the canonical
865a525400dSBen Langmuir   // directory name as the ModuleName, since modules are case-sensitive.
866a525400dSBen Langmuir   // FIXME: we should be able to give a fix-it hint for the correct spelling.
867a525400dSBen Langmuir   SmallString<32> ModuleNameStorage;
868a525400dSBen Langmuir   StringRef ModuleName = sanitizeFilenameAsIdentifier(
869a525400dSBen Langmuir       llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
870c1d88ea5SBen Langmuir 
87156c64013SDouglas Gregor   // Check whether we've already found this module.
872e89dbc1dSDouglas Gregor   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
873e89dbc1dSDouglas Gregor     return Mod;
874e89dbc1dSDouglas Gregor 
8751f76c4e8SManuel Klimek   FileManager &FileMgr = SourceMgr.getFileManager();
87656c64013SDouglas Gregor 
8779194a91dSDouglas Gregor   // If the framework has a parent path from which we're allowed to infer
8789194a91dSDouglas Gregor   // a framework module, do so.
879beee15e7SBen Langmuir   const FileEntry *ModuleMapFile = nullptr;
8809194a91dSDouglas Gregor   if (!Parent) {
8814ddf2221SDouglas Gregor     // Determine whether we're allowed to infer a module map.
8829194a91dSDouglas Gregor     bool canInfer = false;
8834ddf2221SDouglas Gregor     if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
8849194a91dSDouglas Gregor       // Figure out the parent path.
8854ddf2221SDouglas Gregor       StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
8869194a91dSDouglas Gregor       if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) {
8879194a91dSDouglas Gregor         // Check whether we have already looked into the parent directory
8889194a91dSDouglas Gregor         // for a module map.
889e4412640SArgyrios Kyrtzidis         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
8909194a91dSDouglas Gregor           inferred = InferredDirectories.find(ParentDir);
8919194a91dSDouglas Gregor         if (inferred == InferredDirectories.end()) {
8929194a91dSDouglas Gregor           // We haven't looked here before. Load a module map, if there is
8939194a91dSDouglas Gregor           // one.
894984e1df7SBen Langmuir           bool IsFrameworkDir = Parent.endswith(".framework");
895984e1df7SBen Langmuir           if (const FileEntry *ModMapFile =
896984e1df7SBen Langmuir                 HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) {
897c1d88ea5SBen Langmuir             parseModuleMapFile(ModMapFile, Attrs.IsSystem, ParentDir);
8989194a91dSDouglas Gregor             inferred = InferredDirectories.find(ParentDir);
8999194a91dSDouglas Gregor           }
9009194a91dSDouglas Gregor 
9019194a91dSDouglas Gregor           if (inferred == InferredDirectories.end())
9029194a91dSDouglas Gregor             inferred = InferredDirectories.insert(
9039194a91dSDouglas Gregor                          std::make_pair(ParentDir, InferredDirectory())).first;
9049194a91dSDouglas Gregor         }
9059194a91dSDouglas Gregor 
9069194a91dSDouglas Gregor         if (inferred->second.InferModules) {
9079194a91dSDouglas Gregor           // We're allowed to infer for this directory, but make sure it's okay
9089194a91dSDouglas Gregor           // to infer this particular module.
9094ddf2221SDouglas Gregor           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
9109194a91dSDouglas Gregor           canInfer = std::find(inferred->second.ExcludedModules.begin(),
9119194a91dSDouglas Gregor                                inferred->second.ExcludedModules.end(),
9129194a91dSDouglas Gregor                                Name) == inferred->second.ExcludedModules.end();
9139194a91dSDouglas Gregor 
914c1d88ea5SBen Langmuir           Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
915c1d88ea5SBen Langmuir           Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
916c1d88ea5SBen Langmuir           Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
917ed84df00SBruno Cardoso Lopes           Attrs.NoUndeclaredIncludes |=
918ed84df00SBruno Cardoso Lopes               inferred->second.Attrs.NoUndeclaredIncludes;
919beee15e7SBen Langmuir           ModuleMapFile = inferred->second.ModuleMapFile;
9209194a91dSDouglas Gregor         }
9219194a91dSDouglas Gregor       }
9229194a91dSDouglas Gregor     }
9239194a91dSDouglas Gregor 
9249194a91dSDouglas Gregor     // If we're not allowed to infer a framework module, don't.
9259194a91dSDouglas Gregor     if (!canInfer)
926d2d442caSCraig Topper       return nullptr;
927beee15e7SBen Langmuir   } else
9289d6448b1SBen Langmuir     ModuleMapFile = getModuleMapFileForUniquing(Parent);
9299194a91dSDouglas Gregor 
9309194a91dSDouglas Gregor 
93156c64013SDouglas Gregor   // Look for an umbrella header.
9322c1dd271SDylan Noblesmith   SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
93317381a06SBenjamin Kramer   llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
934e89dbc1dSDouglas Gregor   const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
93556c64013SDouglas Gregor 
93656c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
93756c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
93856c64013SDouglas Gregor   // idea.
93956c64013SDouglas Gregor   if (!UmbrellaHeader)
940d2d442caSCraig Topper     return nullptr;
94156c64013SDouglas Gregor 
9429d6448b1SBen Langmuir   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
943a7e2cc68SRichard Smith                               /*IsFramework=*/true, /*IsExplicit=*/false,
944a7e2cc68SRichard Smith                               NumCreatedModules++);
9459d6448b1SBen Langmuir   InferredModuleAllowedBy[Result] = ModuleMapFile;
9469d6448b1SBen Langmuir   Result->IsInferred = true;
9477e82e019SRichard Smith   if (!Parent) {
9487e82e019SRichard Smith     if (LangOpts.CurrentModule == ModuleName)
949ba7f2f71SDaniel Jasper       SourceModule = Result;
9507e82e019SRichard Smith     Modules[ModuleName] = Result;
951c192d194SBruno Cardoso Lopes     ModuleScopeIDs[Result] = CurrentModuleScopeID;
952ba7f2f71SDaniel Jasper   }
953c1d88ea5SBen Langmuir 
954c1d88ea5SBen Langmuir   Result->IsSystem |= Attrs.IsSystem;
955c1d88ea5SBen Langmuir   Result->IsExternC |= Attrs.IsExternC;
956c1d88ea5SBen Langmuir   Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
957ed84df00SBruno Cardoso Lopes   Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
9582b63d15fSRichard Smith   Result->Directory = FrameworkDir;
959a686e1b0SDouglas Gregor 
960322f633cSDouglas Gregor   // umbrella header "umbrella-header-name"
9612b63d15fSRichard Smith   //
9622b63d15fSRichard Smith   // The "Headers/" component of the name is implied because this is
9632b63d15fSRichard Smith   // a framework module.
9642b63d15fSRichard Smith   setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h");
965d8bd7537SDouglas Gregor 
966d8bd7537SDouglas Gregor   // export *
967d2d442caSCraig Topper   Result->Exports.push_back(Module::ExportDecl(nullptr, true));
968d8bd7537SDouglas Gregor 
969a89c5ac4SDouglas Gregor   // module * { export * }
970a89c5ac4SDouglas Gregor   Result->InferSubmodules = true;
971a89c5ac4SDouglas Gregor   Result->InferExportWildcard = true;
972a89c5ac4SDouglas Gregor 
973e89dbc1dSDouglas Gregor   // Look for subframeworks.
974c080917eSRafael Espindola   std::error_code EC;
9752c1dd271SDylan Noblesmith   SmallString<128> SubframeworksDirName
976ddaa69cbSDouglas Gregor     = StringRef(FrameworkDir->getName());
977e89dbc1dSDouglas Gregor   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
9782d4d8cb3SBenjamin Kramer   llvm::sys::path::native(SubframeworksDirName);
979b171a59bSBruno Cardoso Lopes   vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
980b171a59bSBruno Cardoso Lopes   for (vfs::directory_iterator Dir = FS.dir_begin(SubframeworksDirName, EC),
981b171a59bSBruno Cardoso Lopes                                DirEnd;
982e89dbc1dSDouglas Gregor        Dir != DirEnd && !EC; Dir.increment(EC)) {
983b171a59bSBruno Cardoso Lopes     if (!StringRef(Dir->getName()).endswith(".framework"))
984e89dbc1dSDouglas Gregor       continue;
985f2161a70SDouglas Gregor 
986b171a59bSBruno Cardoso Lopes     if (const DirectoryEntry *SubframeworkDir =
987b171a59bSBruno Cardoso Lopes             FileMgr.getDirectory(Dir->getName())) {
98807c22b78SDouglas Gregor       // Note: as an egregious but useful hack, we use the real path here and
98907c22b78SDouglas Gregor       // check whether it is actually a subdirectory of the parent directory.
99007c22b78SDouglas Gregor       // This will not be the case if the 'subframework' is actually a symlink
99107c22b78SDouglas Gregor       // out to a top-level framework.
992e00c8b20SDouglas Gregor       StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir);
99307c22b78SDouglas Gregor       bool FoundParent = false;
99407c22b78SDouglas Gregor       do {
99507c22b78SDouglas Gregor         // Get the parent directory name.
99607c22b78SDouglas Gregor         SubframeworkDirName
99707c22b78SDouglas Gregor           = llvm::sys::path::parent_path(SubframeworkDirName);
99807c22b78SDouglas Gregor         if (SubframeworkDirName.empty())
99907c22b78SDouglas Gregor           break;
100007c22b78SDouglas Gregor 
100107c22b78SDouglas Gregor         if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) {
100207c22b78SDouglas Gregor           FoundParent = true;
100307c22b78SDouglas Gregor           break;
100407c22b78SDouglas Gregor         }
100507c22b78SDouglas Gregor       } while (true);
100607c22b78SDouglas Gregor 
100707c22b78SDouglas Gregor       if (!FoundParent)
100807c22b78SDouglas Gregor         continue;
100907c22b78SDouglas Gregor 
1010e89dbc1dSDouglas Gregor       // FIXME: Do we want to warn about subframeworks without umbrella headers?
1011a525400dSBen Langmuir       inferFrameworkModule(SubframeworkDir, Attrs, Result);
1012e89dbc1dSDouglas Gregor     }
1013e89dbc1dSDouglas Gregor   }
1014e89dbc1dSDouglas Gregor 
101511dfe6feSDouglas Gregor   // If the module is a top-level framework, automatically link against the
101611dfe6feSDouglas Gregor   // framework.
101711dfe6feSDouglas Gregor   if (!Result->isSubFramework()) {
101811dfe6feSDouglas Gregor     inferFrameworkLink(Result, FrameworkDir, FileMgr);
101911dfe6feSDouglas Gregor   }
102011dfe6feSDouglas Gregor 
102156c64013SDouglas Gregor   return Result;
102256c64013SDouglas Gregor }
102356c64013SDouglas Gregor 
10248587dfd9SBruno Cardoso Lopes Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
10258587dfd9SBruno Cardoso Lopes                                         Module *ShadowingModule) {
10268587dfd9SBruno Cardoso Lopes 
10278587dfd9SBruno Cardoso Lopes   // Create a new module with this name.
10288587dfd9SBruno Cardoso Lopes   Module *Result =
10298587dfd9SBruno Cardoso Lopes       new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
10308587dfd9SBruno Cardoso Lopes                  /*IsExplicit=*/false, NumCreatedModules++);
10318587dfd9SBruno Cardoso Lopes   Result->ShadowingModule = ShadowingModule;
10328587dfd9SBruno Cardoso Lopes   Result->IsAvailable = false;
1033c192d194SBruno Cardoso Lopes   ModuleScopeIDs[Result] = CurrentModuleScopeID;
10348587dfd9SBruno Cardoso Lopes   ShadowModules.push_back(Result);
10358587dfd9SBruno Cardoso Lopes 
10368587dfd9SBruno Cardoso Lopes   return Result;
10378587dfd9SBruno Cardoso Lopes }
10388587dfd9SBruno Cardoso Lopes 
10392b63d15fSRichard Smith void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
10402b63d15fSRichard Smith                                   Twine NameAsWritten) {
104197da9178SDaniel Jasper   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
104273141fa9SDouglas Gregor   Mod->Umbrella = UmbrellaHeader;
10432b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
10447033127bSDouglas Gregor   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
1045b3a0fa48SBruno Cardoso Lopes 
1046b3a0fa48SBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1047b3a0fa48SBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1048b3a0fa48SBruno Cardoso Lopes     Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
1049a89c5ac4SDouglas Gregor }
1050a89c5ac4SDouglas Gregor 
10512b63d15fSRichard Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
10522b63d15fSRichard Smith                                Twine NameAsWritten) {
1053524e33e1SDouglas Gregor   Mod->Umbrella = UmbrellaDir;
10542b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
1055524e33e1SDouglas Gregor   UmbrellaDirs[UmbrellaDir] = Mod;
1056524e33e1SDouglas Gregor }
1057524e33e1SDouglas Gregor 
1058040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod,
1059040e1266SRichard Smith                                     Module::UnresolvedHeaderDirective Header) {
1060040e1266SRichard Smith   // If there is a builtin counterpart to this file, add it now so it can
1061040e1266SRichard Smith   // wrap the system header.
1062040e1266SRichard Smith   if (resolveAsBuiltinHeader(Mod, Header)) {
1063040e1266SRichard Smith     // If we have both a builtin and system version of the file, the
1064040e1266SRichard Smith     // builtin version may want to inject macros into the system header, so
1065040e1266SRichard Smith     // force the system header to be treated as a textual header in this
1066040e1266SRichard Smith     // case.
1067040e1266SRichard Smith     Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
1068040e1266SRichard Smith         headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
1069040e1266SRichard Smith     Header.HasBuiltinHeader = true;
10703c1a41adSRichard Smith   }
1071040e1266SRichard Smith 
1072040e1266SRichard Smith   // If possible, don't stat the header until we need to. This requires the
1073040e1266SRichard Smith   // user to have provided us with some stat information about the file.
1074040e1266SRichard Smith   // FIXME: Add support for lazily stat'ing umbrella headers and excluded
1075040e1266SRichard Smith   // headers.
1076040e1266SRichard Smith   if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
1077040e1266SRichard Smith       Header.Kind != Module::HK_Excluded) {
1078040e1266SRichard Smith     // We expect more variation in mtime than size, so if we're given both,
1079040e1266SRichard Smith     // use the mtime as the key.
1080040e1266SRichard Smith     if (Header.ModTime)
1081040e1266SRichard Smith       LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
1082040e1266SRichard Smith     else
1083040e1266SRichard Smith       LazyHeadersBySize[*Header.Size].push_back(Mod);
1084040e1266SRichard Smith     Mod->UnresolvedHeaders.push_back(Header);
1085040e1266SRichard Smith     return;
1086040e1266SRichard Smith   }
1087040e1266SRichard Smith 
1088040e1266SRichard Smith   // We don't have stat information or can't defer looking this file up.
1089040e1266SRichard Smith   // Perform the lookup now.
1090040e1266SRichard Smith   resolveHeader(Mod, Header);
1091040e1266SRichard Smith }
1092040e1266SRichard Smith 
1093040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
1094040e1266SRichard Smith   auto BySize = LazyHeadersBySize.find(File->getSize());
1095040e1266SRichard Smith   if (BySize != LazyHeadersBySize.end()) {
1096040e1266SRichard Smith     for (auto *M : BySize->second)
1097040e1266SRichard Smith       resolveHeaderDirectives(M);
1098040e1266SRichard Smith     LazyHeadersBySize.erase(BySize);
1099040e1266SRichard Smith   }
1100040e1266SRichard Smith 
1101040e1266SRichard Smith   auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
1102040e1266SRichard Smith   if (ByModTime != LazyHeadersByModTime.end()) {
1103040e1266SRichard Smith     for (auto *M : ByModTime->second)
1104040e1266SRichard Smith       resolveHeaderDirectives(M);
1105040e1266SRichard Smith     LazyHeadersByModTime.erase(ByModTime);
1106040e1266SRichard Smith   }
1107040e1266SRichard Smith }
1108040e1266SRichard Smith 
1109040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(Module *Mod) const {
1110040e1266SRichard Smith   for (auto &Header : Mod->UnresolvedHeaders)
1111040e1266SRichard Smith     // This operation is logically const; we're just changing how we represent
1112040e1266SRichard Smith     // the header information for this file.
1113040e1266SRichard Smith     const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header);
1114040e1266SRichard Smith   Mod->UnresolvedHeaders.clear();
11150e98d938SNAKAMURA Takumi }
1116202210b3SRichard Smith 
11173c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header,
1118d8879c85SRichard Smith                           ModuleHeaderRole Role, bool Imported) {
1119386bb073SRichard Smith   KnownHeader KH(Mod, Role);
11203c1a41adSRichard Smith 
1121386bb073SRichard Smith   // Only add each header to the headers list once.
1122386bb073SRichard Smith   // FIXME: Should we diagnose if a header is listed twice in the
1123386bb073SRichard Smith   // same module definition?
1124386bb073SRichard Smith   auto &HeaderList = Headers[Header.Entry];
1125386bb073SRichard Smith   for (auto H : HeaderList)
1126386bb073SRichard Smith     if (H == KH)
1127386bb073SRichard Smith       return;
1128386bb073SRichard Smith 
1129386bb073SRichard Smith   HeaderList.push_back(KH);
11301ec383c7SPiotr Padlewski   Mod->Headers[headerRoleToKind(Role)].push_back(Header);
1131386bb073SRichard Smith 
11327e82e019SRichard Smith   bool isCompilingModuleHeader =
1133bbcc9f04SRichard Smith       LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
1134d8879c85SRichard Smith   if (!Imported || isCompilingModuleHeader) {
1135d8879c85SRichard Smith     // When we import HeaderFileInfo, the external source is expected to
1136d8879c85SRichard Smith     // set the isModuleHeader flag itself.
1137d8879c85SRichard Smith     HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
1138d8879c85SRichard Smith                                     isCompilingModuleHeader);
1139d8879c85SRichard Smith   }
1140e62cfd7cSBruno Cardoso Lopes 
1141e62cfd7cSBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1142e62cfd7cSBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1143f0841790SBruno Cardoso Lopes     Cb->moduleMapAddHeader(Header.Entry->getName());
1144a89c5ac4SDouglas Gregor }
1145a89c5ac4SDouglas Gregor 
11463c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
1147feb54b6dSRichard Smith   // Add this as a known header so we won't implicitly add it to any
1148feb54b6dSRichard Smith   // umbrella directory module.
1149feb54b6dSRichard Smith   // FIXME: Should we only exclude it from umbrella modules within the
1150feb54b6dSRichard Smith   // specified module?
11513c1a41adSRichard Smith   (void) Headers[Header.Entry];
11523c1a41adSRichard Smith 
11533c1a41adSRichard Smith   Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
1154feb54b6dSRichard Smith }
1155feb54b6dSRichard Smith 
1156514b636aSDouglas Gregor const FileEntry *
11574b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const {
11581f76c4e8SManuel Klimek   if (Module->DefinitionLoc.isInvalid())
1159d2d442caSCraig Topper     return nullptr;
1160514b636aSDouglas Gregor 
11611f76c4e8SManuel Klimek   return SourceMgr.getFileEntryForID(
11621f76c4e8SManuel Klimek            SourceMgr.getFileID(Module->DefinitionLoc));
1163514b636aSDouglas Gregor }
1164514b636aSDouglas Gregor 
11654b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
11669d6448b1SBen Langmuir   if (M->IsInferred) {
11679d6448b1SBen Langmuir     assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
11689d6448b1SBen Langmuir     return InferredModuleAllowedBy.find(M)->second;
11699d6448b1SBen Langmuir   }
11709d6448b1SBen Langmuir   return getContainingModuleMapFile(M);
11719d6448b1SBen Langmuir }
11729d6448b1SBen Langmuir 
11739d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
11749d6448b1SBen Langmuir   assert(M->IsInferred && "module not inferred");
11759d6448b1SBen Langmuir   InferredModuleAllowedBy[M] = ModMap;
11769d6448b1SBen Langmuir }
11779d6448b1SBen Langmuir 
1178cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() {
1179718292f2SDouglas Gregor   llvm::errs() << "Modules:";
1180718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1181718292f2SDouglas Gregor                                         MEnd = Modules.end();
1182718292f2SDouglas Gregor        M != MEnd; ++M)
1183d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
1184718292f2SDouglas Gregor 
1185718292f2SDouglas Gregor   llvm::errs() << "Headers:";
118659527666SDouglas Gregor   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1187718292f2SDouglas Gregor        H != HEnd; ++H) {
118897da9178SDaniel Jasper     llvm::errs() << "  \"" << H->first->getName() << "\" -> ";
118997da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
119097da9178SDaniel Jasper                                                       E = H->second.end();
119197da9178SDaniel Jasper          I != E; ++I) {
119297da9178SDaniel Jasper       if (I != H->second.begin())
119397da9178SDaniel Jasper         llvm::errs() << ",";
119497da9178SDaniel Jasper       llvm::errs() << I->getModule()->getFullModuleName();
119597da9178SDaniel Jasper     }
119697da9178SDaniel Jasper     llvm::errs() << "\n";
1197718292f2SDouglas Gregor   }
1198718292f2SDouglas Gregor }
1199718292f2SDouglas Gregor 
12002b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
120142413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedExports);
120242413141SRichard Smith   Mod->UnresolvedExports.clear();
120342413141SRichard Smith   for (auto &UE : Unresolved) {
120442413141SRichard Smith     Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
1205f5eedd05SDouglas Gregor     if (Export.getPointer() || Export.getInt())
12062b82c2a5SDouglas Gregor       Mod->Exports.push_back(Export);
12072b82c2a5SDouglas Gregor     else
120842413141SRichard Smith       Mod->UnresolvedExports.push_back(UE);
12092b82c2a5SDouglas Gregor   }
121042413141SRichard Smith   return !Mod->UnresolvedExports.empty();
12112b82c2a5SDouglas Gregor }
12122b82c2a5SDouglas Gregor 
1213ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
121442413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedDirectUses);
121542413141SRichard Smith   Mod->UnresolvedDirectUses.clear();
121642413141SRichard Smith   for (auto &UDU : Unresolved) {
121742413141SRichard Smith     Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
1218ba7f2f71SDaniel Jasper     if (DirectUse)
1219ba7f2f71SDaniel Jasper       Mod->DirectUses.push_back(DirectUse);
1220ba7f2f71SDaniel Jasper     else
122142413141SRichard Smith       Mod->UnresolvedDirectUses.push_back(UDU);
1222ba7f2f71SDaniel Jasper   }
122342413141SRichard Smith   return !Mod->UnresolvedDirectUses.empty();
1224ba7f2f71SDaniel Jasper }
1225ba7f2f71SDaniel Jasper 
1226fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
122742413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedConflicts);
122842413141SRichard Smith   Mod->UnresolvedConflicts.clear();
122942413141SRichard Smith   for (auto &UC : Unresolved) {
123042413141SRichard Smith     if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1231fb912657SDouglas Gregor       Module::Conflict Conflict;
1232fb912657SDouglas Gregor       Conflict.Other = OtherMod;
123342413141SRichard Smith       Conflict.Message = UC.Message;
1234fb912657SDouglas Gregor       Mod->Conflicts.push_back(Conflict);
123542413141SRichard Smith     } else
123642413141SRichard Smith       Mod->UnresolvedConflicts.push_back(UC);
1237fb912657SDouglas Gregor   }
123842413141SRichard Smith   return !Mod->UnresolvedConflicts.empty();
1239fb912657SDouglas Gregor }
1240fb912657SDouglas Gregor 
1241718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1242718292f2SDouglas Gregor // Module map file parser
1243718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1244718292f2SDouglas Gregor 
1245718292f2SDouglas Gregor namespace clang {
1246afd1b1c9SEugene Zelenko 
1247718292f2SDouglas Gregor   /// \brief A token in a module map file.
1248718292f2SDouglas Gregor   struct MMToken {
1249718292f2SDouglas Gregor     enum TokenKind {
12501fb5c3a6SDouglas Gregor       Comma,
125135b13eceSDouglas Gregor       ConfigMacros,
1252fb912657SDouglas Gregor       Conflict,
1253718292f2SDouglas Gregor       EndOfFile,
1254718292f2SDouglas Gregor       HeaderKeyword,
1255718292f2SDouglas Gregor       Identifier,
1256a3feee2aSRichard Smith       Exclaim,
125759527666SDouglas Gregor       ExcludeKeyword,
1258718292f2SDouglas Gregor       ExplicitKeyword,
12592b82c2a5SDouglas Gregor       ExportKeyword,
1260f0b11de2SDouglas Gregor       ExportAsKeyword,
126197292843SDaniel Jasper       ExternKeyword,
1262755b2055SDouglas Gregor       FrameworkKeyword,
12636ddfca91SDouglas Gregor       LinkKeyword,
1264718292f2SDouglas Gregor       ModuleKeyword,
12652b82c2a5SDouglas Gregor       Period,
1266b53e5483SLawrence Crowl       PrivateKeyword,
1267718292f2SDouglas Gregor       UmbrellaKeyword,
1268ba7f2f71SDaniel Jasper       UseKeyword,
12691fb5c3a6SDouglas Gregor       RequiresKeyword,
12702b82c2a5SDouglas Gregor       Star,
1271718292f2SDouglas Gregor       StringLiteral,
1272040e1266SRichard Smith       IntegerLiteral,
1273306d8920SRichard Smith       TextualKeyword,
1274718292f2SDouglas Gregor       LBrace,
1275a686e1b0SDouglas Gregor       RBrace,
1276a686e1b0SDouglas Gregor       LSquare,
1277a686e1b0SDouglas Gregor       RSquare
1278718292f2SDouglas Gregor     } Kind;
1279718292f2SDouglas Gregor 
1280718292f2SDouglas Gregor     unsigned Location;
1281718292f2SDouglas Gregor     unsigned StringLength;
1282040e1266SRichard Smith     union {
1283040e1266SRichard Smith       // If Kind != IntegerLiteral.
1284718292f2SDouglas Gregor       const char *StringData;
1285afd1b1c9SEugene Zelenko 
1286040e1266SRichard Smith       // If Kind == IntegerLiteral.
1287040e1266SRichard Smith       uint64_t IntegerValue;
1288040e1266SRichard Smith     };
1289718292f2SDouglas Gregor 
1290718292f2SDouglas Gregor     void clear() {
1291718292f2SDouglas Gregor       Kind = EndOfFile;
1292718292f2SDouglas Gregor       Location = 0;
1293718292f2SDouglas Gregor       StringLength = 0;
1294d2d442caSCraig Topper       StringData = nullptr;
1295718292f2SDouglas Gregor     }
1296718292f2SDouglas Gregor 
1297718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
1298718292f2SDouglas Gregor 
1299718292f2SDouglas Gregor     SourceLocation getLocation() const {
1300718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
1301718292f2SDouglas Gregor     }
1302718292f2SDouglas Gregor 
1303040e1266SRichard Smith     uint64_t getInteger() const {
1304040e1266SRichard Smith       return Kind == IntegerLiteral ? IntegerValue : 0;
1305040e1266SRichard Smith     }
1306040e1266SRichard Smith 
1307718292f2SDouglas Gregor     StringRef getString() const {
1308040e1266SRichard Smith       return Kind == IntegerLiteral ? StringRef()
1309040e1266SRichard Smith                                     : StringRef(StringData, StringLength);
1310718292f2SDouglas Gregor     }
1311718292f2SDouglas Gregor   };
1312718292f2SDouglas Gregor 
1313718292f2SDouglas Gregor   class ModuleMapParser {
1314718292f2SDouglas Gregor     Lexer &L;
1315718292f2SDouglas Gregor     SourceManager &SourceMgr;
1316bc10b9fbSDouglas Gregor 
1317bc10b9fbSDouglas Gregor     /// \brief Default target information, used only for string literal
1318bc10b9fbSDouglas Gregor     /// parsing.
1319bc10b9fbSDouglas Gregor     const TargetInfo *Target;
1320bc10b9fbSDouglas Gregor 
1321718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
1322718292f2SDouglas Gregor     ModuleMap &Map;
1323718292f2SDouglas Gregor 
1324beee15e7SBen Langmuir     /// \brief The current module map file.
1325beee15e7SBen Langmuir     const FileEntry *ModuleMapFile;
1326beee15e7SBen Langmuir 
13279acb99e3SRichard Smith     /// \brief The directory that file names in this module map file should
13289acb99e3SRichard Smith     /// be resolved relative to.
13295257fc63SDouglas Gregor     const DirectoryEntry *Directory;
13305257fc63SDouglas Gregor 
1331963c5535SDouglas Gregor     /// \brief Whether this module map is in a system header directory.
1332963c5535SDouglas Gregor     bool IsSystem;
1333963c5535SDouglas Gregor 
1334718292f2SDouglas Gregor     /// \brief Whether an error occurred.
1335afd1b1c9SEugene Zelenko     bool HadError = false;
1336718292f2SDouglas Gregor 
1337718292f2SDouglas Gregor     /// \brief Stores string data for the various string literals referenced
1338718292f2SDouglas Gregor     /// during parsing.
1339718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
1340718292f2SDouglas Gregor 
1341718292f2SDouglas Gregor     /// \brief The current token.
1342718292f2SDouglas Gregor     MMToken Tok;
1343718292f2SDouglas Gregor 
1344718292f2SDouglas Gregor     /// \brief The active module.
1345afd1b1c9SEugene Zelenko     Module *ActiveModule = nullptr;
1346718292f2SDouglas Gregor 
13477ff29148SBen Langmuir     /// \brief Whether a module uses the 'requires excluded' hack to mark its
13487ff29148SBen Langmuir     /// contents as 'textual'.
13497ff29148SBen Langmuir     ///
13507ff29148SBen Langmuir     /// On older Darwin SDK versions, 'requires excluded' is used to mark the
13517ff29148SBen Langmuir     /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
13527ff29148SBen Langmuir     /// non-modular headers.  For backwards compatibility, we continue to
13537ff29148SBen Langmuir     /// support this idiom for just these modules, and map the headers to
13547ff29148SBen Langmuir     /// 'textual' to match the original intent.
13557ff29148SBen Langmuir     llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
13567ff29148SBen Langmuir 
1357718292f2SDouglas Gregor     /// \brief Consume the current token and return its location.
1358718292f2SDouglas Gregor     SourceLocation consumeToken();
1359718292f2SDouglas Gregor 
1360718292f2SDouglas Gregor     /// \brief Skip tokens until we reach the a token with the given kind
1361718292f2SDouglas Gregor     /// (or the end of the file).
1362718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
1363718292f2SDouglas Gregor 
1364afd1b1c9SEugene Zelenko     using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
1365afd1b1c9SEugene Zelenko 
1366e7ab3669SDouglas Gregor     bool parseModuleId(ModuleId &Id);
1367718292f2SDouglas Gregor     void parseModuleDecl();
136897292843SDaniel Jasper     void parseExternModuleDecl();
13691fb5c3a6SDouglas Gregor     void parseRequiresDecl();
1370afd1b1c9SEugene Zelenko     void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
1371524e33e1SDouglas Gregor     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
13722b82c2a5SDouglas Gregor     void parseExportDecl();
1373f0b11de2SDouglas Gregor     void parseExportAsDecl();
1374ba7f2f71SDaniel Jasper     void parseUseDecl();
13756ddfca91SDouglas Gregor     void parseLinkDecl();
137635b13eceSDouglas Gregor     void parseConfigMacros();
1377fb912657SDouglas Gregor     void parseConflict();
13789194a91dSDouglas Gregor     void parseInferredModuleDecl(bool Framework, bool Explicit);
1379c1d88ea5SBen Langmuir 
1380afd1b1c9SEugene Zelenko     using Attributes = ModuleMap::Attributes;
1381afd1b1c9SEugene Zelenko 
13824442605fSBill Wendling     bool parseOptionalAttributes(Attributes &Attrs);
1383718292f2SDouglas Gregor 
1384718292f2SDouglas Gregor   public:
1385718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
13868587dfd9SBruno Cardoso Lopes                              const TargetInfo *Target, DiagnosticsEngine &Diags,
13878587dfd9SBruno Cardoso Lopes                              ModuleMap &Map, const FileEntry *ModuleMapFile,
1388c192d194SBruno Cardoso Lopes                              const DirectoryEntry *Directory, bool IsSystem)
1389bc10b9fbSDouglas Gregor         : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
1390beee15e7SBen Langmuir           ModuleMapFile(ModuleMapFile), Directory(Directory),
1391c192d194SBruno Cardoso Lopes           IsSystem(IsSystem) {
1392718292f2SDouglas Gregor       Tok.clear();
1393718292f2SDouglas Gregor       consumeToken();
1394718292f2SDouglas Gregor     }
1395718292f2SDouglas Gregor 
1396718292f2SDouglas Gregor     bool parseModuleMapFile();
13978128f332SRichard Smith 
13988128f332SRichard Smith     bool terminatedByDirective() { return false; }
13998128f332SRichard Smith     SourceLocation getLocation() { return Tok.getLocation(); }
1400718292f2SDouglas Gregor   };
1401afd1b1c9SEugene Zelenko 
1402afd1b1c9SEugene Zelenko } // namespace clang
1403718292f2SDouglas Gregor 
1404718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
1405718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
1406718292f2SDouglas Gregor 
14078128f332SRichard Smith retry:
14088128f332SRichard Smith   Tok.clear();
1409718292f2SDouglas Gregor   Token LToken;
1410718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
1411718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
1412718292f2SDouglas Gregor   switch (LToken.getKind()) {
14132d57cea2SAlp Toker   case tok::raw_identifier: {
14142d57cea2SAlp Toker     StringRef RI = LToken.getRawIdentifier();
14152d57cea2SAlp Toker     Tok.StringData = RI.data();
14162d57cea2SAlp Toker     Tok.StringLength = RI.size();
14172d57cea2SAlp Toker     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
141835b13eceSDouglas Gregor                  .Case("config_macros", MMToken::ConfigMacros)
1419fb912657SDouglas Gregor                  .Case("conflict", MMToken::Conflict)
142059527666SDouglas Gregor                  .Case("exclude", MMToken::ExcludeKeyword)
1421718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
14222b82c2a5SDouglas Gregor                  .Case("export", MMToken::ExportKeyword)
1423f0b11de2SDouglas Gregor                  .Case("export_as", MMToken::ExportAsKeyword)
142497292843SDaniel Jasper                  .Case("extern", MMToken::ExternKeyword)
1425755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
142635b13eceSDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
14276ddfca91SDouglas Gregor                  .Case("link", MMToken::LinkKeyword)
1428718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
1429b53e5483SLawrence Crowl                  .Case("private", MMToken::PrivateKeyword)
14301fb5c3a6SDouglas Gregor                  .Case("requires", MMToken::RequiresKeyword)
1431306d8920SRichard Smith                  .Case("textual", MMToken::TextualKeyword)
1432718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
1433ba7f2f71SDaniel Jasper                  .Case("use", MMToken::UseKeyword)
1434718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
1435718292f2SDouglas Gregor     break;
14362d57cea2SAlp Toker   }
1437718292f2SDouglas Gregor 
14381fb5c3a6SDouglas Gregor   case tok::comma:
14391fb5c3a6SDouglas Gregor     Tok.Kind = MMToken::Comma;
14401fb5c3a6SDouglas Gregor     break;
14411fb5c3a6SDouglas Gregor 
1442718292f2SDouglas Gregor   case tok::eof:
1443718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
1444718292f2SDouglas Gregor     break;
1445718292f2SDouglas Gregor 
1446718292f2SDouglas Gregor   case tok::l_brace:
1447718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
1448718292f2SDouglas Gregor     break;
1449718292f2SDouglas Gregor 
1450a686e1b0SDouglas Gregor   case tok::l_square:
1451a686e1b0SDouglas Gregor     Tok.Kind = MMToken::LSquare;
1452a686e1b0SDouglas Gregor     break;
1453a686e1b0SDouglas Gregor 
14542b82c2a5SDouglas Gregor   case tok::period:
14552b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Period;
14562b82c2a5SDouglas Gregor     break;
14572b82c2a5SDouglas Gregor 
1458718292f2SDouglas Gregor   case tok::r_brace:
1459718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
1460718292f2SDouglas Gregor     break;
1461718292f2SDouglas Gregor 
1462a686e1b0SDouglas Gregor   case tok::r_square:
1463a686e1b0SDouglas Gregor     Tok.Kind = MMToken::RSquare;
1464a686e1b0SDouglas Gregor     break;
1465a686e1b0SDouglas Gregor 
14662b82c2a5SDouglas Gregor   case tok::star:
14672b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Star;
14682b82c2a5SDouglas Gregor     break;
14692b82c2a5SDouglas Gregor 
1470a3feee2aSRichard Smith   case tok::exclaim:
1471a3feee2aSRichard Smith     Tok.Kind = MMToken::Exclaim;
1472a3feee2aSRichard Smith     break;
1473a3feee2aSRichard Smith 
1474718292f2SDouglas Gregor   case tok::string_literal: {
1475d67aea28SRichard Smith     if (LToken.hasUDSuffix()) {
1476d67aea28SRichard Smith       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
1477d67aea28SRichard Smith       HadError = true;
1478d67aea28SRichard Smith       goto retry;
1479d67aea28SRichard Smith     }
1480d67aea28SRichard Smith 
1481718292f2SDouglas Gregor     // Parse the string literal.
1482718292f2SDouglas Gregor     LangOptions LangOpts;
14839d5583efSCraig Topper     StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
1484718292f2SDouglas Gregor     if (StringLiteral.hadError)
1485718292f2SDouglas Gregor       goto retry;
1486718292f2SDouglas Gregor 
1487718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
1488718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
1489718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
1490718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
1491718292f2SDouglas Gregor     Saved[Length] = 0;
1492718292f2SDouglas Gregor 
1493718292f2SDouglas Gregor     // Form the token.
1494718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
1495718292f2SDouglas Gregor     Tok.StringData = Saved;
1496718292f2SDouglas Gregor     Tok.StringLength = Length;
1497718292f2SDouglas Gregor     break;
1498718292f2SDouglas Gregor   }
1499718292f2SDouglas Gregor 
1500040e1266SRichard Smith   case tok::numeric_constant: {
1501040e1266SRichard Smith     // We don't support any suffixes or other complications.
1502040e1266SRichard Smith     SmallString<32> SpellingBuffer;
1503040e1266SRichard Smith     SpellingBuffer.resize(LToken.getLength() + 1);
1504040e1266SRichard Smith     const char *Start = SpellingBuffer.data();
1505040e1266SRichard Smith     unsigned Length =
1506040e1266SRichard Smith         Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts());
1507040e1266SRichard Smith     uint64_t Value;
1508040e1266SRichard Smith     if (StringRef(Start, Length).getAsInteger(0, Value)) {
1509040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1510040e1266SRichard Smith       HadError = true;
1511040e1266SRichard Smith       goto retry;
1512040e1266SRichard Smith     }
1513040e1266SRichard Smith 
1514040e1266SRichard Smith     Tok.Kind = MMToken::IntegerLiteral;
1515040e1266SRichard Smith     Tok.IntegerValue = Value;
1516040e1266SRichard Smith     break;
1517040e1266SRichard Smith   }
1518040e1266SRichard Smith 
1519718292f2SDouglas Gregor   case tok::comment:
1520718292f2SDouglas Gregor     goto retry;
1521718292f2SDouglas Gregor 
15228128f332SRichard Smith   case tok::hash:
15238128f332SRichard Smith     // A module map can be terminated prematurely by
15248128f332SRichard Smith     //   #pragma clang module contents
15258128f332SRichard Smith     // When building the module, we'll treat the rest of the file as the
15268128f332SRichard Smith     // contents of the module.
15278128f332SRichard Smith     {
15288128f332SRichard Smith       auto NextIsIdent = [&](StringRef Str) -> bool {
15298128f332SRichard Smith         L.LexFromRawLexer(LToken);
15308128f332SRichard Smith         return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
15318128f332SRichard Smith                LToken.getRawIdentifier() == Str;
15328128f332SRichard Smith       };
15338128f332SRichard Smith       if (NextIsIdent("pragma") && NextIsIdent("clang") &&
15348128f332SRichard Smith           NextIsIdent("module") && NextIsIdent("contents")) {
15358128f332SRichard Smith         Tok.Kind = MMToken::EndOfFile;
15368128f332SRichard Smith         break;
15378128f332SRichard Smith       }
15388128f332SRichard Smith     }
15398128f332SRichard Smith     LLVM_FALLTHROUGH;
15408128f332SRichard Smith 
1541718292f2SDouglas Gregor   default:
15428128f332SRichard Smith     Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1543718292f2SDouglas Gregor     HadError = true;
1544718292f2SDouglas Gregor     goto retry;
1545718292f2SDouglas Gregor   }
1546718292f2SDouglas Gregor 
1547718292f2SDouglas Gregor   return Result;
1548718292f2SDouglas Gregor }
1549718292f2SDouglas Gregor 
1550718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
1551718292f2SDouglas Gregor   unsigned braceDepth = 0;
1552a686e1b0SDouglas Gregor   unsigned squareDepth = 0;
1553718292f2SDouglas Gregor   do {
1554718292f2SDouglas Gregor     switch (Tok.Kind) {
1555718292f2SDouglas Gregor     case MMToken::EndOfFile:
1556718292f2SDouglas Gregor       return;
1557718292f2SDouglas Gregor 
1558718292f2SDouglas Gregor     case MMToken::LBrace:
1559a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1560718292f2SDouglas Gregor         return;
1561718292f2SDouglas Gregor 
1562718292f2SDouglas Gregor       ++braceDepth;
1563718292f2SDouglas Gregor       break;
1564718292f2SDouglas Gregor 
1565a686e1b0SDouglas Gregor     case MMToken::LSquare:
1566a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1567a686e1b0SDouglas Gregor         return;
1568a686e1b0SDouglas Gregor 
1569a686e1b0SDouglas Gregor       ++squareDepth;
1570a686e1b0SDouglas Gregor       break;
1571a686e1b0SDouglas Gregor 
1572718292f2SDouglas Gregor     case MMToken::RBrace:
1573718292f2SDouglas Gregor       if (braceDepth > 0)
1574718292f2SDouglas Gregor         --braceDepth;
1575718292f2SDouglas Gregor       else if (Tok.is(K))
1576718292f2SDouglas Gregor         return;
1577718292f2SDouglas Gregor       break;
1578718292f2SDouglas Gregor 
1579a686e1b0SDouglas Gregor     case MMToken::RSquare:
1580a686e1b0SDouglas Gregor       if (squareDepth > 0)
1581a686e1b0SDouglas Gregor         --squareDepth;
1582a686e1b0SDouglas Gregor       else if (Tok.is(K))
1583a686e1b0SDouglas Gregor         return;
1584a686e1b0SDouglas Gregor       break;
1585a686e1b0SDouglas Gregor 
1586718292f2SDouglas Gregor     default:
1587a686e1b0SDouglas Gregor       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
1588718292f2SDouglas Gregor         return;
1589718292f2SDouglas Gregor       break;
1590718292f2SDouglas Gregor     }
1591718292f2SDouglas Gregor 
1592718292f2SDouglas Gregor    consumeToken();
1593718292f2SDouglas Gregor   } while (true);
1594718292f2SDouglas Gregor }
1595718292f2SDouglas Gregor 
1596e7ab3669SDouglas Gregor /// \brief Parse a module-id.
1597e7ab3669SDouglas Gregor ///
1598e7ab3669SDouglas Gregor ///   module-id:
1599e7ab3669SDouglas Gregor ///     identifier
1600e7ab3669SDouglas Gregor ///     identifier '.' module-id
1601e7ab3669SDouglas Gregor ///
1602e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise.
1603e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) {
1604e7ab3669SDouglas Gregor   Id.clear();
1605e7ab3669SDouglas Gregor   do {
16063cd34c76SDaniel Jasper     if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1607e7ab3669SDouglas Gregor       Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
1608e7ab3669SDouglas Gregor       consumeToken();
1609e7ab3669SDouglas Gregor     } else {
1610e7ab3669SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1611e7ab3669SDouglas Gregor       return true;
1612e7ab3669SDouglas Gregor     }
1613e7ab3669SDouglas Gregor 
1614e7ab3669SDouglas Gregor     if (!Tok.is(MMToken::Period))
1615e7ab3669SDouglas Gregor       break;
1616e7ab3669SDouglas Gregor 
1617e7ab3669SDouglas Gregor     consumeToken();
1618e7ab3669SDouglas Gregor   } while (true);
1619e7ab3669SDouglas Gregor 
1620e7ab3669SDouglas Gregor   return false;
1621e7ab3669SDouglas Gregor }
1622e7ab3669SDouglas Gregor 
1623a686e1b0SDouglas Gregor namespace {
1624afd1b1c9SEugene Zelenko 
1625a686e1b0SDouglas Gregor   /// \brief Enumerates the known attributes.
1626a686e1b0SDouglas Gregor   enum AttributeKind {
1627a686e1b0SDouglas Gregor     /// \brief An unknown attribute.
1628a686e1b0SDouglas Gregor     AT_unknown,
1629afd1b1c9SEugene Zelenko 
1630a686e1b0SDouglas Gregor     /// \brief The 'system' attribute.
163135b13eceSDouglas Gregor     AT_system,
1632afd1b1c9SEugene Zelenko 
163377944868SRichard Smith     /// \brief The 'extern_c' attribute.
163477944868SRichard Smith     AT_extern_c,
1635afd1b1c9SEugene Zelenko 
163635b13eceSDouglas Gregor     /// \brief The 'exhaustive' attribute.
1637ed84df00SBruno Cardoso Lopes     AT_exhaustive,
1638afd1b1c9SEugene Zelenko 
1639ed84df00SBruno Cardoso Lopes     /// \brief The 'no_undeclared_includes' attribute.
1640ed84df00SBruno Cardoso Lopes     AT_no_undeclared_includes
1641a686e1b0SDouglas Gregor   };
1642afd1b1c9SEugene Zelenko 
1643afd1b1c9SEugene Zelenko } // namespace
1644a686e1b0SDouglas Gregor 
164529729919SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra
164629729919SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH
164729729919SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written
164829729919SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
164929729919SBruno Cardoso Lopes static void diagnosePrivateModules(const ModuleMap &Map,
165029729919SBruno Cardoso Lopes                                    DiagnosticsEngine &Diags,
16517d29486dSBruno Cardoso Lopes                                    const Module *ActiveModule,
16527d29486dSBruno Cardoso Lopes                                    SourceLocation InlineParent) {
165329729919SBruno Cardoso Lopes 
165429729919SBruno Cardoso Lopes   auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
16557d29486dSBruno Cardoso Lopes                              const Module *M, SourceRange ReplLoc) {
165629729919SBruno Cardoso Lopes     auto D = Diags.Report(ActiveModule->DefinitionLoc,
165729729919SBruno Cardoso Lopes                           diag::note_mmap_rename_top_level_private_module);
165829729919SBruno Cardoso Lopes     D << BadName << M->Name;
16597d29486dSBruno Cardoso Lopes     D << FixItHint::CreateReplacement(ReplLoc, Canonical);
166029729919SBruno Cardoso Lopes   };
166129729919SBruno Cardoso Lopes 
166229729919SBruno Cardoso Lopes   for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
166329729919SBruno Cardoso Lopes     auto const *M = E->getValue();
166429729919SBruno Cardoso Lopes     if (M->Directory != ActiveModule->Directory)
166529729919SBruno Cardoso Lopes       continue;
166629729919SBruno Cardoso Lopes 
166729729919SBruno Cardoso Lopes     SmallString<128> FullName(ActiveModule->getFullModuleName());
166829729919SBruno Cardoso Lopes     if (!FullName.startswith(M->Name) && !FullName.endswith("Private"))
166929729919SBruno Cardoso Lopes       continue;
167029729919SBruno Cardoso Lopes     SmallString<128> Canonical(M->Name);
167129729919SBruno Cardoso Lopes     Canonical.append("_Private");
167229729919SBruno Cardoso Lopes 
167329729919SBruno Cardoso Lopes     // Foo.Private -> Foo_Private
167429729919SBruno Cardoso Lopes     if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
167529729919SBruno Cardoso Lopes         M->Name == ActiveModule->Parent->Name) {
167629729919SBruno Cardoso Lopes       Diags.Report(ActiveModule->DefinitionLoc,
167729729919SBruno Cardoso Lopes                    diag::warn_mmap_mismatched_private_submodule)
167829729919SBruno Cardoso Lopes           << FullName;
16797d29486dSBruno Cardoso Lopes       GenNoteAndFixIt(FullName, Canonical, M,
16807d29486dSBruno Cardoso Lopes                       SourceRange(InlineParent, ActiveModule->DefinitionLoc));
168129729919SBruno Cardoso Lopes       continue;
168229729919SBruno Cardoso Lopes     }
168329729919SBruno Cardoso Lopes 
168429729919SBruno Cardoso Lopes     // FooPrivate and whatnots -> Foo_Private
168529729919SBruno Cardoso Lopes     if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
168629729919SBruno Cardoso Lopes         ActiveModule->Name != Canonical) {
168729729919SBruno Cardoso Lopes       Diags.Report(ActiveModule->DefinitionLoc,
168829729919SBruno Cardoso Lopes                    diag::warn_mmap_mismatched_private_module_name)
168929729919SBruno Cardoso Lopes           << ActiveModule->Name;
16907d29486dSBruno Cardoso Lopes       GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
16917d29486dSBruno Cardoso Lopes                       SourceRange(ActiveModule->DefinitionLoc));
169229729919SBruno Cardoso Lopes     }
169329729919SBruno Cardoso Lopes   }
169429729919SBruno Cardoso Lopes }
169529729919SBruno Cardoso Lopes 
1696718292f2SDouglas Gregor /// \brief Parse a module declaration.
1697718292f2SDouglas Gregor ///
1698718292f2SDouglas Gregor ///   module-declaration:
169997292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
1700a686e1b0SDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1701a686e1b0SDouglas Gregor ///       { module-member* }
1702a686e1b0SDouglas Gregor ///
1703718292f2SDouglas Gregor ///   module-member:
17041fb5c3a6SDouglas Gregor ///     requires-declaration
1705718292f2SDouglas Gregor ///     header-declaration
1706e7ab3669SDouglas Gregor ///     submodule-declaration
17072b82c2a5SDouglas Gregor ///     export-declaration
1708f0b11de2SDouglas Gregor ///     export-as-declaration
17096ddfca91SDouglas Gregor ///     link-declaration
171073441091SDouglas Gregor ///
171173441091SDouglas Gregor ///   submodule-declaration:
171273441091SDouglas Gregor ///     module-declaration
171373441091SDouglas Gregor ///     inferred-submodule-declaration
1714718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
1715755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
171697292843SDaniel Jasper          Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
171797292843SDaniel Jasper   if (Tok.is(MMToken::ExternKeyword)) {
171897292843SDaniel Jasper     parseExternModuleDecl();
171997292843SDaniel Jasper     return;
172097292843SDaniel Jasper   }
172197292843SDaniel Jasper 
1722f2161a70SDouglas Gregor   // Parse 'explicit' or 'framework' keyword, if present.
1723e7ab3669SDouglas Gregor   SourceLocation ExplicitLoc;
1724718292f2SDouglas Gregor   bool Explicit = false;
1725f2161a70SDouglas Gregor   bool Framework = false;
1726755b2055SDouglas Gregor 
1727f2161a70SDouglas Gregor   // Parse 'explicit' keyword, if present.
1728f2161a70SDouglas Gregor   if (Tok.is(MMToken::ExplicitKeyword)) {
1729e7ab3669SDouglas Gregor     ExplicitLoc = consumeToken();
1730f2161a70SDouglas Gregor     Explicit = true;
1731f2161a70SDouglas Gregor   }
1732f2161a70SDouglas Gregor 
1733f2161a70SDouglas Gregor   // Parse 'framework' keyword, if present.
1734755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
1735755b2055SDouglas Gregor     consumeToken();
1736755b2055SDouglas Gregor     Framework = true;
1737755b2055SDouglas Gregor   }
1738718292f2SDouglas Gregor 
1739718292f2SDouglas Gregor   // Parse 'module' keyword.
1740718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
1741d6343c99SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1742718292f2SDouglas Gregor     consumeToken();
1743718292f2SDouglas Gregor     HadError = true;
1744718292f2SDouglas Gregor     return;
1745718292f2SDouglas Gregor   }
1746718292f2SDouglas Gregor   consumeToken(); // 'module' keyword
1747718292f2SDouglas Gregor 
174873441091SDouglas Gregor   // If we have a wildcard for the module name, this is an inferred submodule.
174973441091SDouglas Gregor   // Parse it.
175073441091SDouglas Gregor   if (Tok.is(MMToken::Star))
17519194a91dSDouglas Gregor     return parseInferredModuleDecl(Framework, Explicit);
175273441091SDouglas Gregor 
1753718292f2SDouglas Gregor   // Parse the module name.
1754e7ab3669SDouglas Gregor   ModuleId Id;
1755e7ab3669SDouglas Gregor   if (parseModuleId(Id)) {
1756718292f2SDouglas Gregor     HadError = true;
1757718292f2SDouglas Gregor     return;
1758718292f2SDouglas Gregor   }
1759e7ab3669SDouglas Gregor 
1760e7ab3669SDouglas Gregor   if (ActiveModule) {
1761e7ab3669SDouglas Gregor     if (Id.size() > 1) {
1762e7ab3669SDouglas Gregor       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1763e7ab3669SDouglas Gregor         << SourceRange(Id.front().second, Id.back().second);
1764e7ab3669SDouglas Gregor 
1765e7ab3669SDouglas Gregor       HadError = true;
1766e7ab3669SDouglas Gregor       return;
1767e7ab3669SDouglas Gregor     }
1768e7ab3669SDouglas Gregor   } else if (Id.size() == 1 && Explicit) {
1769e7ab3669SDouglas Gregor     // Top-level modules can't be explicit.
1770e7ab3669SDouglas Gregor     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1771e7ab3669SDouglas Gregor     Explicit = false;
1772e7ab3669SDouglas Gregor     ExplicitLoc = SourceLocation();
1773e7ab3669SDouglas Gregor     HadError = true;
1774e7ab3669SDouglas Gregor   }
1775e7ab3669SDouglas Gregor 
1776e7ab3669SDouglas Gregor   Module *PreviousActiveModule = ActiveModule;
17777d29486dSBruno Cardoso Lopes   SourceLocation LastInlineParentLoc = SourceLocation();
1778e7ab3669SDouglas Gregor   if (Id.size() > 1) {
1779e7ab3669SDouglas Gregor     // This module map defines a submodule. Go find the module of which it
1780e7ab3669SDouglas Gregor     // is a submodule.
1781d2d442caSCraig Topper     ActiveModule = nullptr;
17824b8a9e95SBen Langmuir     const Module *TopLevelModule = nullptr;
1783e7ab3669SDouglas Gregor     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1784e7ab3669SDouglas Gregor       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
17854b8a9e95SBen Langmuir         if (I == 0)
17864b8a9e95SBen Langmuir           TopLevelModule = Next;
1787e7ab3669SDouglas Gregor         ActiveModule = Next;
17887d29486dSBruno Cardoso Lopes         LastInlineParentLoc = Id[I].second;
1789e7ab3669SDouglas Gregor         continue;
1790e7ab3669SDouglas Gregor       }
1791e7ab3669SDouglas Gregor 
1792e7ab3669SDouglas Gregor       if (ActiveModule) {
1793e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
17945b5d21eaSRichard Smith           << Id[I].first
17955b5d21eaSRichard Smith           << ActiveModule->getTopLevelModule()->getFullModuleName();
1796e7ab3669SDouglas Gregor       } else {
1797e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1798e7ab3669SDouglas Gregor       }
1799e7ab3669SDouglas Gregor       HadError = true;
1800e7ab3669SDouglas Gregor       return;
1801e7ab3669SDouglas Gregor     }
18024b8a9e95SBen Langmuir 
18034b8a9e95SBen Langmuir     if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
18044b8a9e95SBen Langmuir       assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
18054b8a9e95SBen Langmuir              "submodule defined in same file as 'module *' that allowed its "
18064b8a9e95SBen Langmuir              "top-level module");
18074b8a9e95SBen Langmuir       Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
18084b8a9e95SBen Langmuir     }
1809e7ab3669SDouglas Gregor   }
1810e7ab3669SDouglas Gregor 
1811e7ab3669SDouglas Gregor   StringRef ModuleName = Id.back().first;
1812e7ab3669SDouglas Gregor   SourceLocation ModuleNameLoc = Id.back().second;
1813718292f2SDouglas Gregor 
1814a686e1b0SDouglas Gregor   // Parse the optional attribute list.
18154442605fSBill Wendling   Attributes Attrs;
18165d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
18175d29dee0SDavide Italiano     return;
18185d29dee0SDavide Italiano 
1819718292f2SDouglas Gregor   // Parse the opening brace.
1820718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
1821718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1822718292f2SDouglas Gregor       << ModuleName;
1823718292f2SDouglas Gregor     HadError = true;
1824718292f2SDouglas Gregor     return;
1825718292f2SDouglas Gregor   }
1826718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
1827718292f2SDouglas Gregor 
1828718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
18298587dfd9SBruno Cardoso Lopes   Module *ShadowingModule = nullptr;
1830eb90e830SDouglas Gregor   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
18314a3751ffSRichard Smith     // We might see a (re)definition of a module that we already have a
18324a3751ffSRichard Smith     // definition for in two cases:
18334a3751ffSRichard Smith     //  - If we loaded one definition from an AST file and we've just found a
18344a3751ffSRichard Smith     //    corresponding definition in a module map file, or
18354a3751ffSRichard Smith     bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
18364a3751ffSRichard Smith     //  - If we're building a (preprocessed) module and we've just loaded the
18374a3751ffSRichard Smith     //    module map file from which it was created.
18384a3751ffSRichard Smith     bool ParsedAsMainInput =
18394a3751ffSRichard Smith         Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
18404a3751ffSRichard Smith         Map.LangOpts.CurrentModule == ModuleName &&
18414a3751ffSRichard Smith         SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
18424a3751ffSRichard Smith             SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
18434a3751ffSRichard Smith     if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
1844fcc54a3bSDouglas Gregor       // Skip the module definition.
1845fcc54a3bSDouglas Gregor       skipUntil(MMToken::RBrace);
1846fcc54a3bSDouglas Gregor       if (Tok.is(MMToken::RBrace))
1847fcc54a3bSDouglas Gregor         consumeToken();
1848fcc54a3bSDouglas Gregor       else {
1849fcc54a3bSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1850fcc54a3bSDouglas Gregor         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1851fcc54a3bSDouglas Gregor         HadError = true;
1852fcc54a3bSDouglas Gregor       }
1853fcc54a3bSDouglas Gregor       return;
1854fcc54a3bSDouglas Gregor     }
1855fcc54a3bSDouglas Gregor 
1856c192d194SBruno Cardoso Lopes     if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
18578587dfd9SBruno Cardoso Lopes       ShadowingModule = Existing;
18588587dfd9SBruno Cardoso Lopes     } else {
18598587dfd9SBruno Cardoso Lopes       // This is not a shawdowed module decl, it is an illegal redefinition.
1860718292f2SDouglas Gregor       Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1861718292f2SDouglas Gregor           << ModuleName;
1862eb90e830SDouglas Gregor       Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1863718292f2SDouglas Gregor 
1864718292f2SDouglas Gregor       // Skip the module definition.
1865718292f2SDouglas Gregor       skipUntil(MMToken::RBrace);
1866718292f2SDouglas Gregor       if (Tok.is(MMToken::RBrace))
1867718292f2SDouglas Gregor         consumeToken();
1868718292f2SDouglas Gregor 
1869718292f2SDouglas Gregor       HadError = true;
1870718292f2SDouglas Gregor       return;
1871718292f2SDouglas Gregor     }
18728587dfd9SBruno Cardoso Lopes   }
1873718292f2SDouglas Gregor 
1874718292f2SDouglas Gregor   // Start defining this module.
18758587dfd9SBruno Cardoso Lopes   if (ShadowingModule) {
18768587dfd9SBruno Cardoso Lopes     ActiveModule =
18778587dfd9SBruno Cardoso Lopes         Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
18788587dfd9SBruno Cardoso Lopes   } else {
1879c192d194SBruno Cardoso Lopes     ActiveModule =
1880c192d194SBruno Cardoso Lopes         Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
18818587dfd9SBruno Cardoso Lopes             .first;
18828587dfd9SBruno Cardoso Lopes   }
18838587dfd9SBruno Cardoso Lopes 
1884eb90e830SDouglas Gregor   ActiveModule->DefinitionLoc = ModuleNameLoc;
1885963c5535SDouglas Gregor   if (Attrs.IsSystem || IsSystem)
1886a686e1b0SDouglas Gregor     ActiveModule->IsSystem = true;
188777944868SRichard Smith   if (Attrs.IsExternC)
188877944868SRichard Smith     ActiveModule->IsExternC = true;
1889ed84df00SBruno Cardoso Lopes   if (Attrs.NoUndeclaredIncludes ||
1890ed84df00SBruno Cardoso Lopes       (!ActiveModule->Parent && ModuleName == "Darwin"))
1891ed84df00SBruno Cardoso Lopes     ActiveModule->NoUndeclaredIncludes = true;
18923c1a41adSRichard Smith   ActiveModule->Directory = Directory;
1893718292f2SDouglas Gregor 
189429729919SBruno Cardoso Lopes 
189529729919SBruno Cardoso Lopes   // Private modules named as FooPrivate, Foo.Private or similar are likely a
189629729919SBruno Cardoso Lopes   // user error; provide warnings, notes and fixits to direct users to use
189729729919SBruno Cardoso Lopes   // Foo_Private instead.
189829729919SBruno Cardoso Lopes   SourceLocation StartLoc =
189929729919SBruno Cardoso Lopes       SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
19004d867640SGraydon Hoare   StringRef MapFileName(ModuleMapFile->getName());
190129729919SBruno Cardoso Lopes   if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
190229729919SBruno Cardoso Lopes       !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
190329729919SBruno Cardoso Lopes                        StartLoc) &&
190429729919SBruno Cardoso Lopes       !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
190529729919SBruno Cardoso Lopes                        StartLoc) &&
190629729919SBruno Cardoso Lopes       (MapFileName.endswith("module.private.modulemap") ||
190729729919SBruno Cardoso Lopes        MapFileName.endswith("module_private.map")))
19087d29486dSBruno Cardoso Lopes     diagnosePrivateModules(Map, Diags, ActiveModule, LastInlineParentLoc);
19094d867640SGraydon Hoare 
1910718292f2SDouglas Gregor   bool Done = false;
1911718292f2SDouglas Gregor   do {
1912718292f2SDouglas Gregor     switch (Tok.Kind) {
1913718292f2SDouglas Gregor     case MMToken::EndOfFile:
1914718292f2SDouglas Gregor     case MMToken::RBrace:
1915718292f2SDouglas Gregor       Done = true;
1916718292f2SDouglas Gregor       break;
1917718292f2SDouglas Gregor 
191835b13eceSDouglas Gregor     case MMToken::ConfigMacros:
191935b13eceSDouglas Gregor       parseConfigMacros();
192035b13eceSDouglas Gregor       break;
192135b13eceSDouglas Gregor 
1922fb912657SDouglas Gregor     case MMToken::Conflict:
1923fb912657SDouglas Gregor       parseConflict();
1924fb912657SDouglas Gregor       break;
1925fb912657SDouglas Gregor 
1926718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
192797292843SDaniel Jasper     case MMToken::ExternKeyword:
1928f2161a70SDouglas Gregor     case MMToken::FrameworkKeyword:
1929718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
1930718292f2SDouglas Gregor       parseModuleDecl();
1931718292f2SDouglas Gregor       break;
1932718292f2SDouglas Gregor 
19332b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
19342b82c2a5SDouglas Gregor       parseExportDecl();
19352b82c2a5SDouglas Gregor       break;
19362b82c2a5SDouglas Gregor 
1937f0b11de2SDouglas Gregor     case MMToken::ExportAsKeyword:
1938f0b11de2SDouglas Gregor       parseExportAsDecl();
1939f0b11de2SDouglas Gregor       break;
1940f0b11de2SDouglas Gregor 
1941ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
1942ba7f2f71SDaniel Jasper       parseUseDecl();
1943ba7f2f71SDaniel Jasper       break;
1944ba7f2f71SDaniel Jasper 
19451fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
19461fb5c3a6SDouglas Gregor       parseRequiresDecl();
19471fb5c3a6SDouglas Gregor       break;
19481fb5c3a6SDouglas Gregor 
1949202210b3SRichard Smith     case MMToken::TextualKeyword:
1950202210b3SRichard Smith       parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
1951306d8920SRichard Smith       break;
1952306d8920SRichard Smith 
1953524e33e1SDouglas Gregor     case MMToken::UmbrellaKeyword: {
1954524e33e1SDouglas Gregor       SourceLocation UmbrellaLoc = consumeToken();
1955524e33e1SDouglas Gregor       if (Tok.is(MMToken::HeaderKeyword))
1956b53e5483SLawrence Crowl         parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
1957524e33e1SDouglas Gregor       else
1958524e33e1SDouglas Gregor         parseUmbrellaDirDecl(UmbrellaLoc);
1959718292f2SDouglas Gregor       break;
1960524e33e1SDouglas Gregor     }
1961718292f2SDouglas Gregor 
1962202210b3SRichard Smith     case MMToken::ExcludeKeyword:
1963202210b3SRichard Smith       parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
196459527666SDouglas Gregor       break;
196559527666SDouglas Gregor 
1966202210b3SRichard Smith     case MMToken::PrivateKeyword:
1967202210b3SRichard Smith       parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
1968b53e5483SLawrence Crowl       break;
1969b53e5483SLawrence Crowl 
1970322f633cSDouglas Gregor     case MMToken::HeaderKeyword:
1971202210b3SRichard Smith       parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
1972718292f2SDouglas Gregor       break;
1973718292f2SDouglas Gregor 
19746ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
19756ddfca91SDouglas Gregor       parseLinkDecl();
19766ddfca91SDouglas Gregor       break;
19776ddfca91SDouglas Gregor 
1978718292f2SDouglas Gregor     default:
1979718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
1980718292f2SDouglas Gregor       consumeToken();
1981718292f2SDouglas Gregor       break;
1982718292f2SDouglas Gregor     }
1983718292f2SDouglas Gregor   } while (!Done);
1984718292f2SDouglas Gregor 
1985718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
1986718292f2SDouglas Gregor     consumeToken();
1987718292f2SDouglas Gregor   else {
1988718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1989718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1990718292f2SDouglas Gregor     HadError = true;
1991718292f2SDouglas Gregor   }
1992718292f2SDouglas Gregor 
199311dfe6feSDouglas Gregor   // If the active module is a top-level framework, and there are no link
199411dfe6feSDouglas Gregor   // libraries, automatically link against the framework.
199511dfe6feSDouglas Gregor   if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
199611dfe6feSDouglas Gregor       ActiveModule->LinkLibraries.empty()) {
199711dfe6feSDouglas Gregor     inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
199811dfe6feSDouglas Gregor   }
199911dfe6feSDouglas Gregor 
2000ec8c9752SBen Langmuir   // If the module meets all requirements but is still unavailable, mark the
2001ec8c9752SBen Langmuir   // whole tree as unavailable to prevent it from building.
2002ec8c9752SBen Langmuir   if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement &&
2003ec8c9752SBen Langmuir       ActiveModule->Parent) {
2004ec8c9752SBen Langmuir     ActiveModule->getTopLevelModule()->markUnavailable();
2005ec8c9752SBen Langmuir     ActiveModule->getTopLevelModule()->MissingHeaders.append(
2006ec8c9752SBen Langmuir       ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
2007ec8c9752SBen Langmuir   }
2008ec8c9752SBen Langmuir 
2009e7ab3669SDouglas Gregor   // We're done parsing this module. Pop back to the previous module.
2010e7ab3669SDouglas Gregor   ActiveModule = PreviousActiveModule;
2011718292f2SDouglas Gregor }
2012718292f2SDouglas Gregor 
201397292843SDaniel Jasper /// \brief Parse an extern module declaration.
201497292843SDaniel Jasper ///
201597292843SDaniel Jasper ///   extern module-declaration:
201697292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
201797292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() {
201897292843SDaniel Jasper   assert(Tok.is(MMToken::ExternKeyword));
2019ae6df27eSRichard Smith   SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
202097292843SDaniel Jasper 
202197292843SDaniel Jasper   // Parse 'module' keyword.
202297292843SDaniel Jasper   if (!Tok.is(MMToken::ModuleKeyword)) {
202397292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
202497292843SDaniel Jasper     consumeToken();
202597292843SDaniel Jasper     HadError = true;
202697292843SDaniel Jasper     return;
202797292843SDaniel Jasper   }
202897292843SDaniel Jasper   consumeToken(); // 'module' keyword
202997292843SDaniel Jasper 
203097292843SDaniel Jasper   // Parse the module name.
203197292843SDaniel Jasper   ModuleId Id;
203297292843SDaniel Jasper   if (parseModuleId(Id)) {
203397292843SDaniel Jasper     HadError = true;
203497292843SDaniel Jasper     return;
203597292843SDaniel Jasper   }
203697292843SDaniel Jasper 
203797292843SDaniel Jasper   // Parse the referenced module map file name.
203897292843SDaniel Jasper   if (!Tok.is(MMToken::StringLiteral)) {
203997292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
204097292843SDaniel Jasper     HadError = true;
204197292843SDaniel Jasper     return;
204297292843SDaniel Jasper   }
204397292843SDaniel Jasper   std::string FileName = Tok.getString();
204497292843SDaniel Jasper   consumeToken(); // filename
204597292843SDaniel Jasper 
204697292843SDaniel Jasper   StringRef FileNameRef = FileName;
204797292843SDaniel Jasper   SmallString<128> ModuleMapFileName;
204897292843SDaniel Jasper   if (llvm::sys::path::is_relative(FileNameRef)) {
204997292843SDaniel Jasper     ModuleMapFileName += Directory->getName();
205097292843SDaniel Jasper     llvm::sys::path::append(ModuleMapFileName, FileName);
205192e1b62dSYaron Keren     FileNameRef = ModuleMapFileName;
205297292843SDaniel Jasper   }
205397292843SDaniel Jasper   if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef))
20549acb99e3SRichard Smith     Map.parseModuleMapFile(
20559acb99e3SRichard Smith         File, /*IsSystem=*/false,
20569acb99e3SRichard Smith         Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
20579acb99e3SRichard Smith             ? Directory
20588128f332SRichard Smith             : File->getDir(),
2059c192d194SBruno Cardoso Lopes         FileID(), nullptr, ExternLoc);
206097292843SDaniel Jasper }
206197292843SDaniel Jasper 
20627ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M.
20637ff29148SBen Langmuir ///
20647ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system
20657ff29148SBen Langmuir /// module map files:
20667ff29148SBen Langmuir ///
20677ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which
20687ff29148SBen Langmuir ///    should really be mapped to 'textual' now that we have this feature.  We
20697ff29148SBen Langmuir ///    drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
20707ff29148SBen Langmuir ///    true.  Later, this bit will be used to map all the headers inside this
20717ff29148SBen Langmuir ///    module to 'textual'.
20727ff29148SBen Langmuir ///
20737ff29148SBen Langmuir ///    This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
20747ff29148SBen Langmuir ///
20757ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc.  This requirement
20767ff29148SBen Langmuir ///    was never correct and causes issues now that we check it, so drop it.
20777ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature,
20787ff29148SBen Langmuir                                  bool &IsRequiresExcludedHack) {
20798013e81dSBenjamin Kramer   if (Feature == "excluded" &&
20808013e81dSBenjamin Kramer       (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
20818013e81dSBenjamin Kramer        M->fullModuleNameIs({"Tcl", "Private"}))) {
20827ff29148SBen Langmuir     IsRequiresExcludedHack = true;
20837ff29148SBen Langmuir     return false;
20848013e81dSBenjamin Kramer   } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
20857ff29148SBen Langmuir     return false;
20867ff29148SBen Langmuir   }
20877ff29148SBen Langmuir 
20887ff29148SBen Langmuir   return true;
20897ff29148SBen Langmuir }
20907ff29148SBen Langmuir 
20911fb5c3a6SDouglas Gregor /// \brief Parse a requires declaration.
20921fb5c3a6SDouglas Gregor ///
20931fb5c3a6SDouglas Gregor ///   requires-declaration:
20941fb5c3a6SDouglas Gregor ///     'requires' feature-list
20951fb5c3a6SDouglas Gregor ///
20961fb5c3a6SDouglas Gregor ///   feature-list:
2097a3feee2aSRichard Smith ///     feature ',' feature-list
2098a3feee2aSRichard Smith ///     feature
2099a3feee2aSRichard Smith ///
2100a3feee2aSRichard Smith ///   feature:
2101a3feee2aSRichard Smith ///     '!'[opt] identifier
21021fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() {
21031fb5c3a6SDouglas Gregor   assert(Tok.is(MMToken::RequiresKeyword));
21041fb5c3a6SDouglas Gregor 
21051fb5c3a6SDouglas Gregor   // Parse 'requires' keyword.
21061fb5c3a6SDouglas Gregor   consumeToken();
21071fb5c3a6SDouglas Gregor 
21081fb5c3a6SDouglas Gregor   // Parse the feature-list.
21091fb5c3a6SDouglas Gregor   do {
2110a3feee2aSRichard Smith     bool RequiredState = true;
2111a3feee2aSRichard Smith     if (Tok.is(MMToken::Exclaim)) {
2112a3feee2aSRichard Smith       RequiredState = false;
2113a3feee2aSRichard Smith       consumeToken();
2114a3feee2aSRichard Smith     }
2115a3feee2aSRichard Smith 
21161fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
21171fb5c3a6SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
21181fb5c3a6SDouglas Gregor       HadError = true;
21191fb5c3a6SDouglas Gregor       return;
21201fb5c3a6SDouglas Gregor     }
21211fb5c3a6SDouglas Gregor 
21221fb5c3a6SDouglas Gregor     // Consume the feature name.
21231fb5c3a6SDouglas Gregor     std::string Feature = Tok.getString();
21241fb5c3a6SDouglas Gregor     consumeToken();
21251fb5c3a6SDouglas Gregor 
21267ff29148SBen Langmuir     bool IsRequiresExcludedHack = false;
21277ff29148SBen Langmuir     bool ShouldAddRequirement =
21287ff29148SBen Langmuir         shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
21297ff29148SBen Langmuir 
21307ff29148SBen Langmuir     if (IsRequiresExcludedHack)
21317ff29148SBen Langmuir       UsesRequiresExcludedHack.insert(ActiveModule);
21327ff29148SBen Langmuir 
21337ff29148SBen Langmuir     if (ShouldAddRequirement) {
21341fb5c3a6SDouglas Gregor       // Add this feature.
21357ff29148SBen Langmuir       ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
21367ff29148SBen Langmuir                                    *Map.Target);
21377ff29148SBen Langmuir     }
21381fb5c3a6SDouglas Gregor 
21391fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Comma))
21401fb5c3a6SDouglas Gregor       break;
21411fb5c3a6SDouglas Gregor 
21421fb5c3a6SDouglas Gregor     // Consume the comma.
21431fb5c3a6SDouglas Gregor     consumeToken();
21441fb5c3a6SDouglas Gregor   } while (true);
21451fb5c3a6SDouglas Gregor }
21461fb5c3a6SDouglas Gregor 
2147718292f2SDouglas Gregor /// \brief Parse a header declaration.
2148718292f2SDouglas Gregor ///
2149718292f2SDouglas Gregor ///   header-declaration:
2150306d8920SRichard Smith ///     'textual'[opt] 'header' string-literal
2151202210b3SRichard Smith ///     'private' 'textual'[opt] 'header' string-literal
2152202210b3SRichard Smith ///     'exclude' 'header' string-literal
2153202210b3SRichard Smith ///     'umbrella' 'header' string-literal
2154306d8920SRichard Smith ///
2155306d8920SRichard Smith /// FIXME: Support 'private textual header'.
2156b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
2157b53e5483SLawrence Crowl                                       SourceLocation LeadingLoc) {
2158202210b3SRichard Smith   // We've already consumed the first token.
2159202210b3SRichard Smith   ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
2160202210b3SRichard Smith   if (LeadingToken == MMToken::PrivateKeyword) {
2161202210b3SRichard Smith     Role = ModuleMap::PrivateHeader;
2162202210b3SRichard Smith     // 'private' may optionally be followed by 'textual'.
2163202210b3SRichard Smith     if (Tok.is(MMToken::TextualKeyword)) {
2164202210b3SRichard Smith       LeadingToken = Tok.Kind;
21651871ed3dSBenjamin Kramer       consumeToken();
2166202210b3SRichard Smith     }
2167202210b3SRichard Smith   }
21687ff29148SBen Langmuir 
2169202210b3SRichard Smith   if (LeadingToken == MMToken::TextualKeyword)
2170202210b3SRichard Smith     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
2171202210b3SRichard Smith 
21727ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
21737ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
21747ff29148SBen Langmuir     // Module::UsesRequiresExcludedHack).
21757ff29148SBen Langmuir     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
21767ff29148SBen Langmuir   }
21777ff29148SBen Langmuir 
2178202210b3SRichard Smith   if (LeadingToken != MMToken::HeaderKeyword) {
2179202210b3SRichard Smith     if (!Tok.is(MMToken::HeaderKeyword)) {
2180202210b3SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2181202210b3SRichard Smith           << (LeadingToken == MMToken::PrivateKeyword ? "private" :
2182202210b3SRichard Smith               LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
2183202210b3SRichard Smith               LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
2184202210b3SRichard Smith       return;
2185202210b3SRichard Smith     }
2186202210b3SRichard Smith     consumeToken();
2187202210b3SRichard Smith   }
2188718292f2SDouglas Gregor 
2189718292f2SDouglas Gregor   // Parse the header name.
2190718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2191718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2192718292f2SDouglas Gregor       << "header";
2193718292f2SDouglas Gregor     HadError = true;
2194718292f2SDouglas Gregor     return;
2195718292f2SDouglas Gregor   }
21963c1a41adSRichard Smith   Module::UnresolvedHeaderDirective Header;
21970761a8a0SDaniel Jasper   Header.FileName = Tok.getString();
21980761a8a0SDaniel Jasper   Header.FileNameLoc = consumeToken();
21991d60987fSRichard Smith   Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
2200040e1266SRichard Smith   Header.Kind =
2201040e1266SRichard Smith       (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded
2202040e1266SRichard Smith                                                : Map.headerRoleToKind(Role));
2203718292f2SDouglas Gregor 
2204524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
22051d60987fSRichard Smith   if (Header.IsUmbrella && ActiveModule->Umbrella) {
22060761a8a0SDaniel Jasper     Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2207524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2208322f633cSDouglas Gregor     HadError = true;
2209322f633cSDouglas Gregor     return;
2210322f633cSDouglas Gregor   }
2211322f633cSDouglas Gregor 
2212040e1266SRichard Smith   // If we were given stat information, parse it so we can skip looking for
2213040e1266SRichard Smith   // the file.
2214040e1266SRichard Smith   if (Tok.is(MMToken::LBrace)) {
2215040e1266SRichard Smith     SourceLocation LBraceLoc = consumeToken();
22163ec6663bSDouglas Gregor 
2217040e1266SRichard Smith     while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
2218040e1266SRichard Smith       enum Attribute { Size, ModTime, Unknown };
2219040e1266SRichard Smith       StringRef Str = Tok.getString();
2220040e1266SRichard Smith       SourceLocation Loc = consumeToken();
2221040e1266SRichard Smith       switch (llvm::StringSwitch<Attribute>(Str)
2222040e1266SRichard Smith                   .Case("size", Size)
2223040e1266SRichard Smith                   .Case("mtime", ModTime)
2224040e1266SRichard Smith                   .Default(Unknown)) {
2225040e1266SRichard Smith       case Size:
2226040e1266SRichard Smith         if (Header.Size)
2227040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2228040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2229040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2230040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2231040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2232040e1266SRichard Smith           break;
2233040e1266SRichard Smith         }
2234040e1266SRichard Smith         Header.Size = Tok.getInteger();
2235040e1266SRichard Smith         consumeToken();
2236040e1266SRichard Smith         break;
2237040e1266SRichard Smith 
2238040e1266SRichard Smith       case ModTime:
2239040e1266SRichard Smith         if (Header.ModTime)
2240040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2241040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2242040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2243040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2244040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2245040e1266SRichard Smith           break;
2246040e1266SRichard Smith         }
2247040e1266SRichard Smith         Header.ModTime = Tok.getInteger();
2248040e1266SRichard Smith         consumeToken();
2249040e1266SRichard Smith         break;
2250040e1266SRichard Smith 
2251040e1266SRichard Smith       case Unknown:
2252040e1266SRichard Smith         Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
2253040e1266SRichard Smith         skipUntil(MMToken::RBrace);
2254040e1266SRichard Smith         break;
2255040e1266SRichard Smith       }
22563ec6663bSDouglas Gregor     }
22575257fc63SDouglas Gregor 
2258040e1266SRichard Smith     if (Tok.is(MMToken::RBrace))
2259040e1266SRichard Smith       consumeToken();
2260040e1266SRichard Smith     else {
2261040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2262040e1266SRichard Smith       Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2263322f633cSDouglas Gregor       HadError = true;
2264322f633cSDouglas Gregor     }
22650101b540SHans Wennborg   }
226625d50758SRichard Smith 
2267040e1266SRichard Smith   Map.addUnresolvedHeader(ActiveModule, std::move(Header));
2268718292f2SDouglas Gregor }
2269718292f2SDouglas Gregor 
227041f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A,
227141f81994SBen Langmuir                                 const Module::Header *B) {
227241f81994SBen Langmuir   return A->NameAsWritten.compare(B->NameAsWritten);
227341f81994SBen Langmuir }
227441f81994SBen Langmuir 
2275524e33e1SDouglas Gregor /// \brief Parse an umbrella directory declaration.
2276524e33e1SDouglas Gregor ///
2277524e33e1SDouglas Gregor ///   umbrella-dir-declaration:
2278524e33e1SDouglas Gregor ///     umbrella string-literal
2279524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
2280524e33e1SDouglas Gregor   // Parse the directory name.
2281524e33e1SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2282524e33e1SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2283524e33e1SDouglas Gregor       << "umbrella";
2284524e33e1SDouglas Gregor     HadError = true;
2285524e33e1SDouglas Gregor     return;
2286524e33e1SDouglas Gregor   }
2287524e33e1SDouglas Gregor 
2288524e33e1SDouglas Gregor   std::string DirName = Tok.getString();
2289524e33e1SDouglas Gregor   SourceLocation DirNameLoc = consumeToken();
2290524e33e1SDouglas Gregor 
2291524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
2292524e33e1SDouglas Gregor   if (ActiveModule->Umbrella) {
2293524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
2294524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2295524e33e1SDouglas Gregor     HadError = true;
2296524e33e1SDouglas Gregor     return;
2297524e33e1SDouglas Gregor   }
2298524e33e1SDouglas Gregor 
2299524e33e1SDouglas Gregor   // Look for this file.
2300d2d442caSCraig Topper   const DirectoryEntry *Dir = nullptr;
2301524e33e1SDouglas Gregor   if (llvm::sys::path::is_absolute(DirName))
2302524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(DirName);
2303524e33e1SDouglas Gregor   else {
23042c1dd271SDylan Noblesmith     SmallString<128> PathName;
2305524e33e1SDouglas Gregor     PathName = Directory->getName();
2306524e33e1SDouglas Gregor     llvm::sys::path::append(PathName, DirName);
2307524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(PathName);
2308524e33e1SDouglas Gregor   }
2309524e33e1SDouglas Gregor 
2310524e33e1SDouglas Gregor   if (!Dir) {
2311a0320b97SVassil Vassilev     Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
2312524e33e1SDouglas Gregor       << DirName;
2313524e33e1SDouglas Gregor     return;
2314524e33e1SDouglas Gregor   }
2315524e33e1SDouglas Gregor 
23167ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
23177ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
23187ff29148SBen Langmuir     // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
23197ff29148SBen Langmuir     // directory is relatively expensive, in practice this only applies to the
23207ff29148SBen Langmuir     // uncommonly used Tcl module on Darwin platforms.
23217ff29148SBen Langmuir     std::error_code EC;
23227ff29148SBen Langmuir     SmallVector<Module::Header, 6> Headers;
2323b171a59bSBruno Cardoso Lopes     vfs::FileSystem &FS = *SourceMgr.getFileManager().getVirtualFileSystem();
2324b171a59bSBruno Cardoso Lopes     for (vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
23257ff29148SBen Langmuir          I != E && !EC; I.increment(EC)) {
2326b171a59bSBruno Cardoso Lopes       if (const FileEntry *FE =
2327b171a59bSBruno Cardoso Lopes               SourceMgr.getFileManager().getFile(I->getName())) {
23287ff29148SBen Langmuir 
2329b171a59bSBruno Cardoso Lopes         Module::Header Header = {I->getName(), FE};
23307ff29148SBen Langmuir         Headers.push_back(std::move(Header));
23317ff29148SBen Langmuir       }
23327ff29148SBen Langmuir     }
23337ff29148SBen Langmuir 
23347ff29148SBen Langmuir     // Sort header paths so that the pcm doesn't depend on iteration order.
233541f81994SBen Langmuir     llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
233641f81994SBen Langmuir 
23377ff29148SBen Langmuir     for (auto &Header : Headers)
23387ff29148SBen Langmuir       Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
23397ff29148SBen Langmuir     return;
23407ff29148SBen Langmuir   }
23417ff29148SBen Langmuir 
2342524e33e1SDouglas Gregor   if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
2343524e33e1SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
2344524e33e1SDouglas Gregor       << OwningModule->getFullModuleName();
2345524e33e1SDouglas Gregor     HadError = true;
2346524e33e1SDouglas Gregor     return;
2347524e33e1SDouglas Gregor   }
2348524e33e1SDouglas Gregor 
2349524e33e1SDouglas Gregor   // Record this umbrella directory.
23502b63d15fSRichard Smith   Map.setUmbrellaDir(ActiveModule, Dir, DirName);
2351524e33e1SDouglas Gregor }
2352524e33e1SDouglas Gregor 
23532b82c2a5SDouglas Gregor /// \brief Parse a module export declaration.
23542b82c2a5SDouglas Gregor ///
23552b82c2a5SDouglas Gregor ///   export-declaration:
23562b82c2a5SDouglas Gregor ///     'export' wildcard-module-id
23572b82c2a5SDouglas Gregor ///
23582b82c2a5SDouglas Gregor ///   wildcard-module-id:
23592b82c2a5SDouglas Gregor ///     identifier
23602b82c2a5SDouglas Gregor ///     '*'
23612b82c2a5SDouglas Gregor ///     identifier '.' wildcard-module-id
23622b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() {
23632b82c2a5SDouglas Gregor   assert(Tok.is(MMToken::ExportKeyword));
23642b82c2a5SDouglas Gregor   SourceLocation ExportLoc = consumeToken();
23652b82c2a5SDouglas Gregor 
23662b82c2a5SDouglas Gregor   // Parse the module-id with an optional wildcard at the end.
23672b82c2a5SDouglas Gregor   ModuleId ParsedModuleId;
23682b82c2a5SDouglas Gregor   bool Wildcard = false;
23692b82c2a5SDouglas Gregor   do {
2370306d8920SRichard Smith     // FIXME: Support string-literal module names here.
23712b82c2a5SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
23722b82c2a5SDouglas Gregor       ParsedModuleId.push_back(std::make_pair(Tok.getString(),
23732b82c2a5SDouglas Gregor                                               Tok.getLocation()));
23742b82c2a5SDouglas Gregor       consumeToken();
23752b82c2a5SDouglas Gregor 
23762b82c2a5SDouglas Gregor       if (Tok.is(MMToken::Period)) {
23772b82c2a5SDouglas Gregor         consumeToken();
23782b82c2a5SDouglas Gregor         continue;
23792b82c2a5SDouglas Gregor       }
23802b82c2a5SDouglas Gregor 
23812b82c2a5SDouglas Gregor       break;
23822b82c2a5SDouglas Gregor     }
23832b82c2a5SDouglas Gregor 
23842b82c2a5SDouglas Gregor     if(Tok.is(MMToken::Star)) {
23852b82c2a5SDouglas Gregor       Wildcard = true;
2386f5eedd05SDouglas Gregor       consumeToken();
23872b82c2a5SDouglas Gregor       break;
23882b82c2a5SDouglas Gregor     }
23892b82c2a5SDouglas Gregor 
2390ba7f2f71SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
23912b82c2a5SDouglas Gregor     HadError = true;
23922b82c2a5SDouglas Gregor     return;
23932b82c2a5SDouglas Gregor   } while (true);
23942b82c2a5SDouglas Gregor 
23952b82c2a5SDouglas Gregor   Module::UnresolvedExportDecl Unresolved = {
23962b82c2a5SDouglas Gregor     ExportLoc, ParsedModuleId, Wildcard
23972b82c2a5SDouglas Gregor   };
23982b82c2a5SDouglas Gregor   ActiveModule->UnresolvedExports.push_back(Unresolved);
23992b82c2a5SDouglas Gregor }
24002b82c2a5SDouglas Gregor 
2401f0b11de2SDouglas Gregor /// \brief Parse a module export_as declaration.
2402f0b11de2SDouglas Gregor ///
2403f0b11de2SDouglas Gregor ///   export-as-declaration:
2404f0b11de2SDouglas Gregor ///     'export_as' identifier
2405f0b11de2SDouglas Gregor void ModuleMapParser::parseExportAsDecl() {
2406f0b11de2SDouglas Gregor   assert(Tok.is(MMToken::ExportAsKeyword));
2407f0b11de2SDouglas Gregor   consumeToken();
2408f0b11de2SDouglas Gregor 
2409f0b11de2SDouglas Gregor   if (!Tok.is(MMToken::Identifier)) {
2410f0b11de2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
2411f0b11de2SDouglas Gregor     HadError = true;
2412f0b11de2SDouglas Gregor     return;
2413f0b11de2SDouglas Gregor   }
2414f0b11de2SDouglas Gregor 
2415f0b11de2SDouglas Gregor   if (ActiveModule->Parent) {
2416f0b11de2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
2417f0b11de2SDouglas Gregor     consumeToken();
2418f0b11de2SDouglas Gregor     return;
2419f0b11de2SDouglas Gregor   }
2420f0b11de2SDouglas Gregor 
2421f0b11de2SDouglas Gregor   if (!ActiveModule->ExportAsModule.empty()) {
2422f0b11de2SDouglas Gregor     if (ActiveModule->ExportAsModule == Tok.getString()) {
2423f0b11de2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
2424f0b11de2SDouglas Gregor         << ActiveModule->Name << Tok.getString();
2425f0b11de2SDouglas Gregor     } else {
2426f0b11de2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
2427f0b11de2SDouglas Gregor         << ActiveModule->Name << ActiveModule->ExportAsModule
2428f0b11de2SDouglas Gregor         << Tok.getString();
2429f0b11de2SDouglas Gregor     }
2430f0b11de2SDouglas Gregor   }
2431f0b11de2SDouglas Gregor 
2432f0b11de2SDouglas Gregor   ActiveModule->ExportAsModule = Tok.getString();
2433*a3b5f71eSBruno Cardoso Lopes   Map.addLinkAsDependency(ActiveModule);
2434*a3b5f71eSBruno Cardoso Lopes 
2435f0b11de2SDouglas Gregor   consumeToken();
2436f0b11de2SDouglas Gregor }
2437f0b11de2SDouglas Gregor 
24388f4d3ff1SRichard Smith /// \brief Parse a module use declaration.
2439ba7f2f71SDaniel Jasper ///
24408f4d3ff1SRichard Smith ///   use-declaration:
24418f4d3ff1SRichard Smith ///     'use' wildcard-module-id
2442ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() {
2443ba7f2f71SDaniel Jasper   assert(Tok.is(MMToken::UseKeyword));
24448f4d3ff1SRichard Smith   auto KWLoc = consumeToken();
2445ba7f2f71SDaniel Jasper   // Parse the module-id.
2446ba7f2f71SDaniel Jasper   ModuleId ParsedModuleId;
24473cd34c76SDaniel Jasper   parseModuleId(ParsedModuleId);
2448ba7f2f71SDaniel Jasper 
24498f4d3ff1SRichard Smith   if (ActiveModule->Parent)
24508f4d3ff1SRichard Smith     Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
24518f4d3ff1SRichard Smith   else
2452ba7f2f71SDaniel Jasper     ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
2453ba7f2f71SDaniel Jasper }
2454ba7f2f71SDaniel Jasper 
24556ddfca91SDouglas Gregor /// \brief Parse a link declaration.
24566ddfca91SDouglas Gregor ///
24576ddfca91SDouglas Gregor ///   module-declaration:
24586ddfca91SDouglas Gregor ///     'link' 'framework'[opt] string-literal
24596ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() {
24606ddfca91SDouglas Gregor   assert(Tok.is(MMToken::LinkKeyword));
24616ddfca91SDouglas Gregor   SourceLocation LinkLoc = consumeToken();
24626ddfca91SDouglas Gregor 
24636ddfca91SDouglas Gregor   // Parse the optional 'framework' keyword.
24646ddfca91SDouglas Gregor   bool IsFramework = false;
24656ddfca91SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
24666ddfca91SDouglas Gregor     consumeToken();
24676ddfca91SDouglas Gregor     IsFramework = true;
24686ddfca91SDouglas Gregor   }
24696ddfca91SDouglas Gregor 
24706ddfca91SDouglas Gregor   // Parse the library name
24716ddfca91SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
24726ddfca91SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
24736ddfca91SDouglas Gregor       << IsFramework << SourceRange(LinkLoc);
24746ddfca91SDouglas Gregor     HadError = true;
24756ddfca91SDouglas Gregor     return;
24766ddfca91SDouglas Gregor   }
24776ddfca91SDouglas Gregor 
24786ddfca91SDouglas Gregor   std::string LibraryName = Tok.getString();
24796ddfca91SDouglas Gregor   consumeToken();
24806ddfca91SDouglas Gregor   ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
24816ddfca91SDouglas Gregor                                                             IsFramework));
24826ddfca91SDouglas Gregor }
24836ddfca91SDouglas Gregor 
248435b13eceSDouglas Gregor /// \brief Parse a configuration macro declaration.
248535b13eceSDouglas Gregor ///
248635b13eceSDouglas Gregor ///   module-declaration:
248735b13eceSDouglas Gregor ///     'config_macros' attributes[opt] config-macro-list?
248835b13eceSDouglas Gregor ///
248935b13eceSDouglas Gregor ///   config-macro-list:
249035b13eceSDouglas Gregor ///     identifier (',' identifier)?
249135b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() {
249235b13eceSDouglas Gregor   assert(Tok.is(MMToken::ConfigMacros));
249335b13eceSDouglas Gregor   SourceLocation ConfigMacrosLoc = consumeToken();
249435b13eceSDouglas Gregor 
249535b13eceSDouglas Gregor   // Only top-level modules can have configuration macros.
249635b13eceSDouglas Gregor   if (ActiveModule->Parent) {
249735b13eceSDouglas Gregor     Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
249835b13eceSDouglas Gregor   }
249935b13eceSDouglas Gregor 
250035b13eceSDouglas Gregor   // Parse the optional attributes.
250135b13eceSDouglas Gregor   Attributes Attrs;
25025d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
25035d29dee0SDavide Italiano     return;
25045d29dee0SDavide Italiano 
250535b13eceSDouglas Gregor   if (Attrs.IsExhaustive && !ActiveModule->Parent) {
250635b13eceSDouglas Gregor     ActiveModule->ConfigMacrosExhaustive = true;
250735b13eceSDouglas Gregor   }
250835b13eceSDouglas Gregor 
250935b13eceSDouglas Gregor   // If we don't have an identifier, we're done.
2510306d8920SRichard Smith   // FIXME: Support macros with the same name as a keyword here.
251135b13eceSDouglas Gregor   if (!Tok.is(MMToken::Identifier))
251235b13eceSDouglas Gregor     return;
251335b13eceSDouglas Gregor 
251435b13eceSDouglas Gregor   // Consume the first identifier.
251535b13eceSDouglas Gregor   if (!ActiveModule->Parent) {
251635b13eceSDouglas Gregor     ActiveModule->ConfigMacros.push_back(Tok.getString().str());
251735b13eceSDouglas Gregor   }
251835b13eceSDouglas Gregor   consumeToken();
251935b13eceSDouglas Gregor 
252035b13eceSDouglas Gregor   do {
252135b13eceSDouglas Gregor     // If there's a comma, consume it.
252235b13eceSDouglas Gregor     if (!Tok.is(MMToken::Comma))
252335b13eceSDouglas Gregor       break;
252435b13eceSDouglas Gregor     consumeToken();
252535b13eceSDouglas Gregor 
252635b13eceSDouglas Gregor     // We expect to see a macro name here.
2527306d8920SRichard Smith     // FIXME: Support macros with the same name as a keyword here.
252835b13eceSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
252935b13eceSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
253035b13eceSDouglas Gregor       break;
253135b13eceSDouglas Gregor     }
253235b13eceSDouglas Gregor 
253335b13eceSDouglas Gregor     // Consume the macro name.
253435b13eceSDouglas Gregor     if (!ActiveModule->Parent) {
253535b13eceSDouglas Gregor       ActiveModule->ConfigMacros.push_back(Tok.getString().str());
253635b13eceSDouglas Gregor     }
253735b13eceSDouglas Gregor     consumeToken();
253835b13eceSDouglas Gregor   } while (true);
253935b13eceSDouglas Gregor }
254035b13eceSDouglas Gregor 
2541fb912657SDouglas Gregor /// \brief Format a module-id into a string.
2542fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) {
2543fb912657SDouglas Gregor   std::string result;
2544fb912657SDouglas Gregor   {
2545fb912657SDouglas Gregor     llvm::raw_string_ostream OS(result);
2546fb912657SDouglas Gregor 
2547fb912657SDouglas Gregor     for (unsigned I = 0, N = Id.size(); I != N; ++I) {
2548fb912657SDouglas Gregor       if (I)
2549fb912657SDouglas Gregor         OS << ".";
2550fb912657SDouglas Gregor       OS << Id[I].first;
2551fb912657SDouglas Gregor     }
2552fb912657SDouglas Gregor   }
2553fb912657SDouglas Gregor 
2554fb912657SDouglas Gregor   return result;
2555fb912657SDouglas Gregor }
2556fb912657SDouglas Gregor 
2557fb912657SDouglas Gregor /// \brief Parse a conflict declaration.
2558fb912657SDouglas Gregor ///
2559fb912657SDouglas Gregor ///   module-declaration:
2560fb912657SDouglas Gregor ///     'conflict' module-id ',' string-literal
2561fb912657SDouglas Gregor void ModuleMapParser::parseConflict() {
2562fb912657SDouglas Gregor   assert(Tok.is(MMToken::Conflict));
2563fb912657SDouglas Gregor   SourceLocation ConflictLoc = consumeToken();
2564fb912657SDouglas Gregor   Module::UnresolvedConflict Conflict;
2565fb912657SDouglas Gregor 
2566fb912657SDouglas Gregor   // Parse the module-id.
2567fb912657SDouglas Gregor   if (parseModuleId(Conflict.Id))
2568fb912657SDouglas Gregor     return;
2569fb912657SDouglas Gregor 
2570fb912657SDouglas Gregor   // Parse the ','.
2571fb912657SDouglas Gregor   if (!Tok.is(MMToken::Comma)) {
2572fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
2573fb912657SDouglas Gregor       << SourceRange(ConflictLoc);
2574fb912657SDouglas Gregor     return;
2575fb912657SDouglas Gregor   }
2576fb912657SDouglas Gregor   consumeToken();
2577fb912657SDouglas Gregor 
2578fb912657SDouglas Gregor   // Parse the message.
2579fb912657SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2580fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
2581fb912657SDouglas Gregor       << formatModuleId(Conflict.Id);
2582fb912657SDouglas Gregor     return;
2583fb912657SDouglas Gregor   }
2584fb912657SDouglas Gregor   Conflict.Message = Tok.getString().str();
2585fb912657SDouglas Gregor   consumeToken();
2586fb912657SDouglas Gregor 
2587fb912657SDouglas Gregor   // Add this unresolved conflict.
2588fb912657SDouglas Gregor   ActiveModule->UnresolvedConflicts.push_back(Conflict);
2589fb912657SDouglas Gregor }
2590fb912657SDouglas Gregor 
25916ddfca91SDouglas Gregor /// \brief Parse an inferred module declaration (wildcard modules).
25929194a91dSDouglas Gregor ///
25939194a91dSDouglas Gregor ///   module-declaration:
25949194a91dSDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
25959194a91dSDouglas Gregor ///       { inferred-module-member* }
25969194a91dSDouglas Gregor ///
25979194a91dSDouglas Gregor ///   inferred-module-member:
25989194a91dSDouglas Gregor ///     'export' '*'
25999194a91dSDouglas Gregor ///     'exclude' identifier
26009194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
260173441091SDouglas Gregor   assert(Tok.is(MMToken::Star));
260273441091SDouglas Gregor   SourceLocation StarLoc = consumeToken();
260373441091SDouglas Gregor   bool Failed = false;
260473441091SDouglas Gregor 
260573441091SDouglas Gregor   // Inferred modules must be submodules.
26069194a91dSDouglas Gregor   if (!ActiveModule && !Framework) {
260773441091SDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
260873441091SDouglas Gregor     Failed = true;
260973441091SDouglas Gregor   }
261073441091SDouglas Gregor 
26119194a91dSDouglas Gregor   if (ActiveModule) {
2612524e33e1SDouglas Gregor     // Inferred modules must have umbrella directories.
26134898cde4SBen Langmuir     if (!Failed && ActiveModule->IsAvailable &&
26144898cde4SBen Langmuir         !ActiveModule->getUmbrellaDir()) {
261573441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
261673441091SDouglas Gregor       Failed = true;
261773441091SDouglas Gregor     }
261873441091SDouglas Gregor 
261973441091SDouglas Gregor     // Check for redefinition of an inferred module.
2620dd005f69SDouglas Gregor     if (!Failed && ActiveModule->InferSubmodules) {
262173441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2622dd005f69SDouglas Gregor       if (ActiveModule->InferredSubmoduleLoc.isValid())
2623dd005f69SDouglas Gregor         Diags.Report(ActiveModule->InferredSubmoduleLoc,
262473441091SDouglas Gregor                      diag::note_mmap_prev_definition);
262573441091SDouglas Gregor       Failed = true;
262673441091SDouglas Gregor     }
262773441091SDouglas Gregor 
26289194a91dSDouglas Gregor     // Check for the 'framework' keyword, which is not permitted here.
26299194a91dSDouglas Gregor     if (Framework) {
26309194a91dSDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
26319194a91dSDouglas Gregor       Framework = false;
26329194a91dSDouglas Gregor     }
26339194a91dSDouglas Gregor   } else if (Explicit) {
26349194a91dSDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
26359194a91dSDouglas Gregor     Explicit = false;
26369194a91dSDouglas Gregor   }
26379194a91dSDouglas Gregor 
263873441091SDouglas Gregor   // If there were any problems with this inferred submodule, skip its body.
263973441091SDouglas Gregor   if (Failed) {
264073441091SDouglas Gregor     if (Tok.is(MMToken::LBrace)) {
264173441091SDouglas Gregor       consumeToken();
264273441091SDouglas Gregor       skipUntil(MMToken::RBrace);
264373441091SDouglas Gregor       if (Tok.is(MMToken::RBrace))
264473441091SDouglas Gregor         consumeToken();
264573441091SDouglas Gregor     }
264673441091SDouglas Gregor     HadError = true;
264773441091SDouglas Gregor     return;
264873441091SDouglas Gregor   }
264973441091SDouglas Gregor 
26509194a91dSDouglas Gregor   // Parse optional attributes.
26514442605fSBill Wendling   Attributes Attrs;
26525d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
26535d29dee0SDavide Italiano     return;
26549194a91dSDouglas Gregor 
26559194a91dSDouglas Gregor   if (ActiveModule) {
265673441091SDouglas Gregor     // Note that we have an inferred submodule.
2657dd005f69SDouglas Gregor     ActiveModule->InferSubmodules = true;
2658dd005f69SDouglas Gregor     ActiveModule->InferredSubmoduleLoc = StarLoc;
2659dd005f69SDouglas Gregor     ActiveModule->InferExplicitSubmodules = Explicit;
26609194a91dSDouglas Gregor   } else {
26619194a91dSDouglas Gregor     // We'll be inferring framework modules for this directory.
26629194a91dSDouglas Gregor     Map.InferredDirectories[Directory].InferModules = true;
2663c1d88ea5SBen Langmuir     Map.InferredDirectories[Directory].Attrs = Attrs;
2664beee15e7SBen Langmuir     Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
2665131daca0SRichard Smith     // FIXME: Handle the 'framework' keyword.
26669194a91dSDouglas Gregor   }
266773441091SDouglas Gregor 
266873441091SDouglas Gregor   // Parse the opening brace.
266973441091SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
267073441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
267173441091SDouglas Gregor     HadError = true;
267273441091SDouglas Gregor     return;
267373441091SDouglas Gregor   }
267473441091SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
267573441091SDouglas Gregor 
267673441091SDouglas Gregor   // Parse the body of the inferred submodule.
267773441091SDouglas Gregor   bool Done = false;
267873441091SDouglas Gregor   do {
267973441091SDouglas Gregor     switch (Tok.Kind) {
268073441091SDouglas Gregor     case MMToken::EndOfFile:
268173441091SDouglas Gregor     case MMToken::RBrace:
268273441091SDouglas Gregor       Done = true;
268373441091SDouglas Gregor       break;
268473441091SDouglas Gregor 
2685afd1b1c9SEugene Zelenko     case MMToken::ExcludeKeyword:
26869194a91dSDouglas Gregor       if (ActiveModule) {
26879194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2688d2d442caSCraig Topper           << (ActiveModule != nullptr);
26899194a91dSDouglas Gregor         consumeToken();
26909194a91dSDouglas Gregor         break;
26919194a91dSDouglas Gregor       }
26929194a91dSDouglas Gregor 
26939194a91dSDouglas Gregor       consumeToken();
2694306d8920SRichard Smith       // FIXME: Support string-literal module names here.
26959194a91dSDouglas Gregor       if (!Tok.is(MMToken::Identifier)) {
26969194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
26979194a91dSDouglas Gregor         break;
26989194a91dSDouglas Gregor       }
26999194a91dSDouglas Gregor 
27009194a91dSDouglas Gregor       Map.InferredDirectories[Directory].ExcludedModules
27019194a91dSDouglas Gregor         .push_back(Tok.getString());
27029194a91dSDouglas Gregor       consumeToken();
27039194a91dSDouglas Gregor       break;
27049194a91dSDouglas Gregor 
27059194a91dSDouglas Gregor     case MMToken::ExportKeyword:
27069194a91dSDouglas Gregor       if (!ActiveModule) {
27079194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2708d2d442caSCraig Topper           << (ActiveModule != nullptr);
27099194a91dSDouglas Gregor         consumeToken();
27109194a91dSDouglas Gregor         break;
27119194a91dSDouglas Gregor       }
27129194a91dSDouglas Gregor 
271373441091SDouglas Gregor       consumeToken();
271473441091SDouglas Gregor       if (Tok.is(MMToken::Star))
2715dd005f69SDouglas Gregor         ActiveModule->InferExportWildcard = true;
271673441091SDouglas Gregor       else
271773441091SDouglas Gregor         Diags.Report(Tok.getLocation(),
271873441091SDouglas Gregor                      diag::err_mmap_expected_export_wildcard);
271973441091SDouglas Gregor       consumeToken();
272073441091SDouglas Gregor       break;
272173441091SDouglas Gregor 
272273441091SDouglas Gregor     case MMToken::ExplicitKeyword:
272373441091SDouglas Gregor     case MMToken::ModuleKeyword:
272473441091SDouglas Gregor     case MMToken::HeaderKeyword:
2725b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
272673441091SDouglas Gregor     case MMToken::UmbrellaKeyword:
272773441091SDouglas Gregor     default:
27289194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2729d2d442caSCraig Topper           << (ActiveModule != nullptr);
273073441091SDouglas Gregor       consumeToken();
273173441091SDouglas Gregor       break;
273273441091SDouglas Gregor     }
273373441091SDouglas Gregor   } while (!Done);
273473441091SDouglas Gregor 
273573441091SDouglas Gregor   if (Tok.is(MMToken::RBrace))
273673441091SDouglas Gregor     consumeToken();
273773441091SDouglas Gregor   else {
273873441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
273973441091SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
274073441091SDouglas Gregor     HadError = true;
274173441091SDouglas Gregor   }
274273441091SDouglas Gregor }
274373441091SDouglas Gregor 
27449194a91dSDouglas Gregor /// \brief Parse optional attributes.
27459194a91dSDouglas Gregor ///
27469194a91dSDouglas Gregor ///   attributes:
27479194a91dSDouglas Gregor ///     attribute attributes
27489194a91dSDouglas Gregor ///     attribute
27499194a91dSDouglas Gregor ///
27509194a91dSDouglas Gregor ///   attribute:
27519194a91dSDouglas Gregor ///     [ identifier ]
27529194a91dSDouglas Gregor ///
27539194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes.
27549194a91dSDouglas Gregor ///
27559194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise.
27564442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
27579194a91dSDouglas Gregor   bool HadError = false;
27589194a91dSDouglas Gregor 
27599194a91dSDouglas Gregor   while (Tok.is(MMToken::LSquare)) {
27609194a91dSDouglas Gregor     // Consume the '['.
27619194a91dSDouglas Gregor     SourceLocation LSquareLoc = consumeToken();
27629194a91dSDouglas Gregor 
27639194a91dSDouglas Gregor     // Check whether we have an attribute name here.
27649194a91dSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
27659194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
27669194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
27679194a91dSDouglas Gregor       if (Tok.is(MMToken::RSquare))
27689194a91dSDouglas Gregor         consumeToken();
27699194a91dSDouglas Gregor       HadError = true;
27709194a91dSDouglas Gregor     }
27719194a91dSDouglas Gregor 
27729194a91dSDouglas Gregor     // Decode the attribute name.
27739194a91dSDouglas Gregor     AttributeKind Attribute
27749194a91dSDouglas Gregor       = llvm::StringSwitch<AttributeKind>(Tok.getString())
277535b13eceSDouglas Gregor           .Case("exhaustive", AT_exhaustive)
277677944868SRichard Smith           .Case("extern_c", AT_extern_c)
2777ed84df00SBruno Cardoso Lopes           .Case("no_undeclared_includes", AT_no_undeclared_includes)
27789194a91dSDouglas Gregor           .Case("system", AT_system)
27799194a91dSDouglas Gregor           .Default(AT_unknown);
27809194a91dSDouglas Gregor     switch (Attribute) {
27819194a91dSDouglas Gregor     case AT_unknown:
27829194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
27839194a91dSDouglas Gregor         << Tok.getString();
27849194a91dSDouglas Gregor       break;
27859194a91dSDouglas Gregor 
27869194a91dSDouglas Gregor     case AT_system:
27879194a91dSDouglas Gregor       Attrs.IsSystem = true;
27889194a91dSDouglas Gregor       break;
278935b13eceSDouglas Gregor 
279077944868SRichard Smith     case AT_extern_c:
279177944868SRichard Smith       Attrs.IsExternC = true;
279277944868SRichard Smith       break;
279377944868SRichard Smith 
279435b13eceSDouglas Gregor     case AT_exhaustive:
279535b13eceSDouglas Gregor       Attrs.IsExhaustive = true;
279635b13eceSDouglas Gregor       break;
2797ed84df00SBruno Cardoso Lopes 
2798ed84df00SBruno Cardoso Lopes     case AT_no_undeclared_includes:
2799ed84df00SBruno Cardoso Lopes       Attrs.NoUndeclaredIncludes = true;
2800ed84df00SBruno Cardoso Lopes       break;
28019194a91dSDouglas Gregor     }
28029194a91dSDouglas Gregor     consumeToken();
28039194a91dSDouglas Gregor 
28049194a91dSDouglas Gregor     // Consume the ']'.
28059194a91dSDouglas Gregor     if (!Tok.is(MMToken::RSquare)) {
28069194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
28079194a91dSDouglas Gregor       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
28089194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
28099194a91dSDouglas Gregor       HadError = true;
28109194a91dSDouglas Gregor     }
28119194a91dSDouglas Gregor 
28129194a91dSDouglas Gregor     if (Tok.is(MMToken::RSquare))
28139194a91dSDouglas Gregor       consumeToken();
28149194a91dSDouglas Gregor   }
28159194a91dSDouglas Gregor 
28169194a91dSDouglas Gregor   return HadError;
28179194a91dSDouglas Gregor }
28189194a91dSDouglas Gregor 
2819718292f2SDouglas Gregor /// \brief Parse a module map file.
2820718292f2SDouglas Gregor ///
2821718292f2SDouglas Gregor ///   module-map-file:
2822718292f2SDouglas Gregor ///     module-declaration*
2823718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
2824718292f2SDouglas Gregor   do {
2825718292f2SDouglas Gregor     switch (Tok.Kind) {
2826718292f2SDouglas Gregor     case MMToken::EndOfFile:
2827718292f2SDouglas Gregor       return HadError;
2828718292f2SDouglas Gregor 
2829e7ab3669SDouglas Gregor     case MMToken::ExplicitKeyword:
283097292843SDaniel Jasper     case MMToken::ExternKeyword:
2831718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
2832755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
2833718292f2SDouglas Gregor       parseModuleDecl();
2834718292f2SDouglas Gregor       break;
2835718292f2SDouglas Gregor 
28361fb5c3a6SDouglas Gregor     case MMToken::Comma:
283735b13eceSDouglas Gregor     case MMToken::ConfigMacros:
2838fb912657SDouglas Gregor     case MMToken::Conflict:
2839a3feee2aSRichard Smith     case MMToken::Exclaim:
284059527666SDouglas Gregor     case MMToken::ExcludeKeyword:
28412b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
2842f0b11de2SDouglas Gregor     case MMToken::ExportAsKeyword:
2843718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
2844718292f2SDouglas Gregor     case MMToken::Identifier:
2845718292f2SDouglas Gregor     case MMToken::LBrace:
28466ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
2847a686e1b0SDouglas Gregor     case MMToken::LSquare:
28482b82c2a5SDouglas Gregor     case MMToken::Period:
2849b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
2850718292f2SDouglas Gregor     case MMToken::RBrace:
2851a686e1b0SDouglas Gregor     case MMToken::RSquare:
28521fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
28532b82c2a5SDouglas Gregor     case MMToken::Star:
2854718292f2SDouglas Gregor     case MMToken::StringLiteral:
2855040e1266SRichard Smith     case MMToken::IntegerLiteral:
2856b8afebe2SRichard Smith     case MMToken::TextualKeyword:
2857718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
2858ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
2859718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
2860718292f2SDouglas Gregor       HadError = true;
2861718292f2SDouglas Gregor       consumeToken();
2862718292f2SDouglas Gregor       break;
2863718292f2SDouglas Gregor     }
2864718292f2SDouglas Gregor   } while (true);
2865718292f2SDouglas Gregor }
2866718292f2SDouglas Gregor 
28679acb99e3SRichard Smith bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
2868c192d194SBruno Cardoso Lopes                                    const DirectoryEntry *Dir, FileID ID,
28698128f332SRichard Smith                                    unsigned *Offset,
2870ae6df27eSRichard Smith                                    SourceLocation ExternModuleLoc) {
28718128f332SRichard Smith   assert(Target && "Missing target information");
28724ddf2221SDouglas Gregor   llvm::DenseMap<const FileEntry *, bool>::iterator Known
28734ddf2221SDouglas Gregor     = ParsedModuleMap.find(File);
28744ddf2221SDouglas Gregor   if (Known != ParsedModuleMap.end())
28754ddf2221SDouglas Gregor     return Known->second;
28764ddf2221SDouglas Gregor 
28778128f332SRichard Smith   // If the module map file wasn't already entered, do so now.
28788128f332SRichard Smith   if (ID.isInvalid()) {
2879f3f84616SRichard Smith     auto FileCharacter =
2880f3f84616SRichard Smith         IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
28818128f332SRichard Smith     ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
28828128f332SRichard Smith   }
28838128f332SRichard Smith 
28848128f332SRichard Smith   assert(Target && "Missing target information");
28851f76c4e8SManuel Klimek   const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID);
2886718292f2SDouglas Gregor   if (!Buffer)
28874ddf2221SDouglas Gregor     return ParsedModuleMap[File] = true;
28888128f332SRichard Smith   assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
28898128f332SRichard Smith          "invalid buffer offset");
2890718292f2SDouglas Gregor 
2891718292f2SDouglas Gregor   // Parse this module map file.
28928128f332SRichard Smith   Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
28938128f332SRichard Smith           Buffer->getBufferStart(),
28948128f332SRichard Smith           Buffer->getBufferStart() + (Offset ? *Offset : 0),
28958128f332SRichard Smith           Buffer->getBufferEnd());
28962a6edb30SRichard Smith   SourceLocation Start = L.getSourceLocation();
2897beee15e7SBen Langmuir   ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
2898c192d194SBruno Cardoso Lopes                          IsSystem);
2899718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
29004ddf2221SDouglas Gregor   ParsedModuleMap[File] = Result;
29012a6edb30SRichard Smith 
29028128f332SRichard Smith   if (Offset) {
29038128f332SRichard Smith     auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
29048128f332SRichard Smith     assert(Loc.first == ID && "stopped in a different file?");
29058128f332SRichard Smith     *Offset = Loc.second;
29068128f332SRichard Smith   }
29078128f332SRichard Smith 
29082a6edb30SRichard Smith   // Notify callbacks that we parsed it.
29092a6edb30SRichard Smith   for (const auto &Cb : Callbacks)
29102a6edb30SRichard Smith     Cb->moduleMapFileRead(Start, *File, IsSystem);
29118587dfd9SBruno Cardoso Lopes 
2912718292f2SDouglas Gregor   return Result;
2913718292f2SDouglas Gregor }
2914