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 
57a3b5f71eSBruno Cardoso Lopes void ModuleMap::resolveLinkAsDependencies(Module *Mod) {
58a3b5f71eSBruno Cardoso Lopes   auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name);
59a3b5f71eSBruno Cardoso Lopes   if (PendingLinkAs != PendingLinkAsModule.end()) {
60a3b5f71eSBruno Cardoso Lopes     for (auto &Name : PendingLinkAs->second) {
61a3b5f71eSBruno Cardoso Lopes       auto *M = findModule(Name.getKey());
62a3b5f71eSBruno Cardoso Lopes       if (M)
63a3b5f71eSBruno Cardoso Lopes         M->UseExportAsModuleLinkName = true;
64a3b5f71eSBruno Cardoso Lopes     }
65a3b5f71eSBruno Cardoso Lopes   }
66a3b5f71eSBruno Cardoso Lopes }
67a3b5f71eSBruno Cardoso Lopes 
68a3b5f71eSBruno Cardoso Lopes void ModuleMap::addLinkAsDependency(Module *Mod) {
69a3b5f71eSBruno Cardoso Lopes   if (findModule(Mod->ExportAsModule))
70a3b5f71eSBruno Cardoso Lopes     Mod->UseExportAsModuleLinkName = true;
71a3b5f71eSBruno Cardoso Lopes   else
72a3b5f71eSBruno Cardoso Lopes     PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name);
73a3b5f71eSBruno Cardoso Lopes }
74a3b5f71eSBruno Cardoso Lopes 
75040e1266SRichard Smith Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
76040e1266SRichard Smith   switch ((int)Role) {
77040e1266SRichard Smith   default: llvm_unreachable("unknown header role");
78040e1266SRichard Smith   case NormalHeader:
79040e1266SRichard Smith     return Module::HK_Normal;
80040e1266SRichard Smith   case PrivateHeader:
81040e1266SRichard Smith     return Module::HK_Private;
82040e1266SRichard Smith   case TextualHeader:
83040e1266SRichard Smith     return Module::HK_Textual;
84040e1266SRichard Smith   case PrivateHeader | TextualHeader:
85040e1266SRichard Smith     return Module::HK_PrivateTextual;
86040e1266SRichard Smith   }
87040e1266SRichard Smith }
88040e1266SRichard Smith 
89040e1266SRichard Smith ModuleMap::ModuleHeaderRole
90040e1266SRichard Smith ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
91040e1266SRichard Smith   switch ((int)Kind) {
92040e1266SRichard Smith   case Module::HK_Normal:
93040e1266SRichard Smith     return NormalHeader;
94040e1266SRichard Smith   case Module::HK_Private:
95040e1266SRichard Smith     return PrivateHeader;
96040e1266SRichard Smith   case Module::HK_Textual:
97040e1266SRichard Smith     return TextualHeader;
98040e1266SRichard Smith   case Module::HK_PrivateTextual:
99040e1266SRichard Smith     return ModuleHeaderRole(PrivateHeader | TextualHeader);
100040e1266SRichard Smith   case Module::HK_Excluded:
101040e1266SRichard Smith     llvm_unreachable("unexpected header kind");
102040e1266SRichard Smith   }
103040e1266SRichard Smith   llvm_unreachable("unknown header kind");
104040e1266SRichard Smith }
105040e1266SRichard Smith 
1062b82c2a5SDouglas Gregor Module::ExportDecl
1072b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod,
1082b82c2a5SDouglas Gregor                          const Module::UnresolvedExportDecl &Unresolved,
109e4412640SArgyrios Kyrtzidis                          bool Complain) const {
110f5eedd05SDouglas Gregor   // We may have just a wildcard.
111f5eedd05SDouglas Gregor   if (Unresolved.Id.empty()) {
112f5eedd05SDouglas Gregor     assert(Unresolved.Wildcard && "Invalid unresolved export");
113d2d442caSCraig Topper     return Module::ExportDecl(nullptr, true);
114f5eedd05SDouglas Gregor   }
115f5eedd05SDouglas Gregor 
116fb912657SDouglas Gregor   // Resolve the module-id.
117fb912657SDouglas Gregor   Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
118fb912657SDouglas Gregor   if (!Context)
119afd1b1c9SEugene Zelenko     return {};
120fb912657SDouglas Gregor 
121fb912657SDouglas Gregor   return Module::ExportDecl(Context, Unresolved.Wildcard);
122fb912657SDouglas Gregor }
123fb912657SDouglas Gregor 
124fb912657SDouglas Gregor Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
125fb912657SDouglas Gregor                                    bool Complain) const {
1262b82c2a5SDouglas Gregor   // Find the starting module.
127fb912657SDouglas Gregor   Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
1282b82c2a5SDouglas Gregor   if (!Context) {
1292b82c2a5SDouglas Gregor     if (Complain)
1300761a8a0SDaniel Jasper       Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
131fb912657SDouglas Gregor       << Id[0].first << Mod->getFullModuleName();
1322b82c2a5SDouglas Gregor 
133d2d442caSCraig Topper     return nullptr;
1342b82c2a5SDouglas Gregor   }
1352b82c2a5SDouglas Gregor 
1362b82c2a5SDouglas Gregor   // Dig into the module path.
137fb912657SDouglas Gregor   for (unsigned I = 1, N = Id.size(); I != N; ++I) {
138fb912657SDouglas Gregor     Module *Sub = lookupModuleQualified(Id[I].first, Context);
1392b82c2a5SDouglas Gregor     if (!Sub) {
1402b82c2a5SDouglas Gregor       if (Complain)
1410761a8a0SDaniel Jasper         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
142fb912657SDouglas Gregor         << Id[I].first << Context->getFullModuleName()
143fb912657SDouglas Gregor         << SourceRange(Id[0].second, Id[I-1].second);
1442b82c2a5SDouglas Gregor 
145d2d442caSCraig Topper       return nullptr;
1462b82c2a5SDouglas Gregor     }
1472b82c2a5SDouglas Gregor 
1482b82c2a5SDouglas Gregor     Context = Sub;
1492b82c2a5SDouglas Gregor   }
1502b82c2a5SDouglas Gregor 
151fb912657SDouglas Gregor   return Context;
1522b82c2a5SDouglas Gregor }
1532b82c2a5SDouglas Gregor 
1549fc8faf9SAdrian Prantl /// Append to \p Paths the set of paths needed to get to the
1551d60987fSRichard Smith /// subframework in which the given module lives.
1561d60987fSRichard Smith static void appendSubframeworkPaths(Module *Mod,
1571d60987fSRichard Smith                                     SmallVectorImpl<char> &Path) {
1581d60987fSRichard Smith   // Collect the framework names from the given module to the top-level module.
1591d60987fSRichard Smith   SmallVector<StringRef, 2> Paths;
1601d60987fSRichard Smith   for (; Mod; Mod = Mod->Parent) {
1611d60987fSRichard Smith     if (Mod->IsFramework)
1621d60987fSRichard Smith       Paths.push_back(Mod->Name);
1631d60987fSRichard Smith   }
1641d60987fSRichard Smith 
1651d60987fSRichard Smith   if (Paths.empty())
1661d60987fSRichard Smith     return;
1671d60987fSRichard Smith 
1681d60987fSRichard Smith   // Add Frameworks/Name.framework for each subframework.
1691d60987fSRichard Smith   for (unsigned I = Paths.size() - 1; I != 0; --I)
1701d60987fSRichard Smith     llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework");
1711d60987fSRichard Smith }
1721d60987fSRichard Smith 
1739f6020bcSBruno Cardoso Lopes const FileEntry *ModuleMap::findHeader(
1749f6020bcSBruno Cardoso Lopes     Module *M, const Module::UnresolvedHeaderDirective &Header,
1759f6020bcSBruno Cardoso Lopes     SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) {
1769f6020bcSBruno Cardoso Lopes   // Search for the header file within the module's home directory.
1779f6020bcSBruno Cardoso Lopes   auto *Directory = M->Directory;
1789f6020bcSBruno Cardoso Lopes   SmallString<128> FullPathName(Directory->getName());
1799f6020bcSBruno Cardoso Lopes 
180040e1266SRichard Smith   auto GetFile = [&](StringRef Filename) -> const FileEntry * {
181040e1266SRichard Smith     auto *File = SourceMgr.getFileManager().getFile(Filename);
182040e1266SRichard Smith     if (!File ||
183040e1266SRichard Smith         (Header.Size && File->getSize() != *Header.Size) ||
184040e1266SRichard Smith         (Header.ModTime && File->getModificationTime() != *Header.ModTime))
185040e1266SRichard Smith       return nullptr;
186040e1266SRichard Smith     return File;
187040e1266SRichard Smith   };
188040e1266SRichard Smith 
1899f6020bcSBruno Cardoso Lopes   auto GetFrameworkFile = [&]() -> const FileEntry * {
1901d60987fSRichard Smith     unsigned FullPathLength = FullPathName.size();
1911d60987fSRichard Smith     appendSubframeworkPaths(M, RelativePathName);
1921d60987fSRichard Smith     unsigned RelativePathLength = RelativePathName.size();
1931d60987fSRichard Smith 
1941d60987fSRichard Smith     // Check whether this file is in the public headers.
1951d60987fSRichard Smith     llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
1961d60987fSRichard Smith     llvm::sys::path::append(FullPathName, RelativePathName);
197040e1266SRichard Smith     if (auto *File = GetFile(FullPathName))
1981d60987fSRichard Smith       return File;
1991d60987fSRichard Smith 
2001d60987fSRichard Smith     // Check whether this file is in the private headers.
2011d60987fSRichard Smith     // Ideally, private modules in the form 'FrameworkName.Private' should
2021d60987fSRichard Smith     // be defined as 'module FrameworkName.Private', and not as
2031d60987fSRichard Smith     // 'framework module FrameworkName.Private', since a 'Private.Framework'
2041d60987fSRichard Smith     // does not usually exist. However, since both are currently widely used
2051d60987fSRichard Smith     // for private modules, make sure we find the right path in both cases.
2061d60987fSRichard Smith     if (M->IsFramework && M->Name == "Private")
2071d60987fSRichard Smith       RelativePathName.clear();
2081d60987fSRichard Smith     else
2091d60987fSRichard Smith       RelativePathName.resize(RelativePathLength);
2101d60987fSRichard Smith     FullPathName.resize(FullPathLength);
2111d60987fSRichard Smith     llvm::sys::path::append(RelativePathName, "PrivateHeaders",
2121d60987fSRichard Smith                             Header.FileName);
2131d60987fSRichard Smith     llvm::sys::path::append(FullPathName, RelativePathName);
214040e1266SRichard Smith     return GetFile(FullPathName);
2159f6020bcSBruno Cardoso Lopes   };
2169f6020bcSBruno Cardoso Lopes 
2179f6020bcSBruno Cardoso Lopes   if (llvm::sys::path::is_absolute(Header.FileName)) {
2189f6020bcSBruno Cardoso Lopes     RelativePathName.clear();
2199f6020bcSBruno Cardoso Lopes     RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
2209f6020bcSBruno Cardoso Lopes     return GetFile(Header.FileName);
2211d60987fSRichard Smith   }
2221d60987fSRichard Smith 
2239f6020bcSBruno Cardoso Lopes   if (M->isPartOfFramework())
2249f6020bcSBruno Cardoso Lopes     return GetFrameworkFile();
2259f6020bcSBruno Cardoso Lopes 
2261d60987fSRichard Smith   // Lookup for normal headers.
2271d60987fSRichard Smith   llvm::sys::path::append(RelativePathName, Header.FileName);
2281d60987fSRichard Smith   llvm::sys::path::append(FullPathName, RelativePathName);
2299f6020bcSBruno Cardoso Lopes   auto *NormalHdrFile = GetFile(FullPathName);
2309f6020bcSBruno Cardoso Lopes 
2319f6020bcSBruno Cardoso Lopes   if (M && !NormalHdrFile && Directory->getName().endswith(".framework")) {
2329f6020bcSBruno Cardoso Lopes     // The lack of 'framework' keyword in a module declaration it's a simple
2339f6020bcSBruno Cardoso Lopes     // mistake we can diagnose when the header exists within the proper
2349f6020bcSBruno Cardoso Lopes     // framework style path.
2359f6020bcSBruno Cardoso Lopes     FullPathName.assign(Directory->getName());
2369f6020bcSBruno Cardoso Lopes     RelativePathName.clear();
237*d101b5d7SErich Keane     if (GetFrameworkFile()) {
2389f6020bcSBruno Cardoso Lopes       Diags.Report(Header.FileNameLoc,
2399f6020bcSBruno Cardoso Lopes                    diag::warn_mmap_incomplete_framework_module_declaration)
2409f6020bcSBruno Cardoso Lopes           << Header.FileName << M->getFullModuleName();
2419f6020bcSBruno Cardoso Lopes       NeedsFramework = true;
2429f6020bcSBruno Cardoso Lopes     }
2439f6020bcSBruno Cardoso Lopes     return nullptr;
2449f6020bcSBruno Cardoso Lopes   }
2459f6020bcSBruno Cardoso Lopes 
2469f6020bcSBruno Cardoso Lopes   return NormalHdrFile;
2471d60987fSRichard Smith }
2481d60987fSRichard Smith 
249040e1266SRichard Smith void ModuleMap::resolveHeader(Module *Mod,
2509f6020bcSBruno Cardoso Lopes                               const Module::UnresolvedHeaderDirective &Header,
2519f6020bcSBruno Cardoso Lopes                               bool &NeedsFramework) {
252040e1266SRichard Smith   SmallString<128> RelativePathName;
2539f6020bcSBruno Cardoso Lopes   if (const FileEntry *File =
2549f6020bcSBruno Cardoso Lopes           findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
255040e1266SRichard Smith     if (Header.IsUmbrella) {
256040e1266SRichard Smith       const DirectoryEntry *UmbrellaDir = File->getDir();
257040e1266SRichard Smith       if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
258040e1266SRichard Smith         Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
259040e1266SRichard Smith           << UmbrellaMod->getFullModuleName();
260040e1266SRichard Smith       else
261040e1266SRichard Smith         // Record this umbrella header.
262040e1266SRichard Smith         setUmbrellaHeader(Mod, File, RelativePathName.str());
263040e1266SRichard Smith     } else {
264040e1266SRichard Smith       Module::Header H = {RelativePathName.str(), File};
265040e1266SRichard Smith       if (Header.Kind == Module::HK_Excluded)
266040e1266SRichard Smith         excludeHeader(Mod, H);
267040e1266SRichard Smith       else
268040e1266SRichard Smith         addHeader(Mod, H, headerKindToRole(Header.Kind));
269040e1266SRichard Smith     }
270040e1266SRichard Smith   } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
271040e1266SRichard Smith     // There's a builtin header but no corresponding on-disk header. Assume
272040e1266SRichard Smith     // this was supposed to modularize the builtin header alone.
273040e1266SRichard Smith   } else if (Header.Kind == Module::HK_Excluded) {
274040e1266SRichard Smith     // Ignore missing excluded header files. They're optional anyway.
275040e1266SRichard Smith   } else {
276040e1266SRichard Smith     // If we find a module that has a missing header, we mark this module as
277040e1266SRichard Smith     // unavailable and store the header directive for displaying diagnostics.
278040e1266SRichard Smith     Mod->MissingHeaders.push_back(Header);
279040e1266SRichard Smith     // A missing header with stat information doesn't make the module
280040e1266SRichard Smith     // unavailable; this keeps our behavior consistent as headers are lazily
281040e1266SRichard Smith     // resolved. (Such a module still can't be built though, except from
282040e1266SRichard Smith     // preprocessed source.)
283040e1266SRichard Smith     if (!Header.Size && !Header.ModTime)
284040e1266SRichard Smith       Mod->markUnavailable();
285040e1266SRichard Smith   }
286040e1266SRichard Smith }
287040e1266SRichard Smith 
288040e1266SRichard Smith bool ModuleMap::resolveAsBuiltinHeader(
289040e1266SRichard Smith     Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
290040e1266SRichard Smith   if (Header.Kind == Module::HK_Excluded ||
291040e1266SRichard Smith       llvm::sys::path::is_absolute(Header.FileName) ||
292040e1266SRichard Smith       Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
293040e1266SRichard Smith       !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
294040e1266SRichard Smith       !isBuiltinHeader(Header.FileName))
295040e1266SRichard Smith     return false;
2961d60987fSRichard Smith 
2971d60987fSRichard Smith   // This is a system module with a top-level header. This header
2981d60987fSRichard Smith   // may have a counterpart (or replacement) in the set of headers
2991d60987fSRichard Smith   // supplied by Clang. Find that builtin header.
300040e1266SRichard Smith   SmallString<128> Path;
301040e1266SRichard Smith   llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
302040e1266SRichard Smith   auto *File = SourceMgr.getFileManager().getFile(Path);
303040e1266SRichard Smith   if (!File)
304040e1266SRichard Smith     return false;
305040e1266SRichard Smith 
306040e1266SRichard Smith   auto Role = headerKindToRole(Header.Kind);
307040e1266SRichard Smith   Module::Header H = {Path.str(), File};
308040e1266SRichard Smith   addHeader(Mod, H, Role);
309040e1266SRichard Smith   return true;
3101d60987fSRichard Smith }
3111d60987fSRichard Smith 
3120761a8a0SDaniel Jasper ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
313b146baabSArgyrios Kyrtzidis                      const LangOptions &LangOpts, const TargetInfo *Target,
314b146baabSArgyrios Kyrtzidis                      HeaderSearch &HeaderInfo)
3150761a8a0SDaniel Jasper     : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
316056bf77fSRichard Smith       HeaderInfo(HeaderInfo) {
3170414b857SRichard Smith   MMapLangOpts.LineComment = true;
3180414b857SRichard Smith }
319718292f2SDouglas Gregor 
320718292f2SDouglas Gregor ModuleMap::~ModuleMap() {
32121668754SDavide Italiano   for (auto &M : Modules)
32221668754SDavide Italiano     delete M.getValue();
3238587dfd9SBruno Cardoso Lopes   for (auto *M : ShadowModules)
3248587dfd9SBruno Cardoso Lopes     delete M;
325718292f2SDouglas Gregor }
326718292f2SDouglas Gregor 
32789929282SDouglas Gregor void ModuleMap::setTarget(const TargetInfo &Target) {
32889929282SDouglas Gregor   assert((!this->Target || this->Target == &Target) &&
32989929282SDouglas Gregor          "Improper target override");
33089929282SDouglas Gregor   this->Target = &Target;
33189929282SDouglas Gregor }
33289929282SDouglas Gregor 
3339fc8faf9SAdrian Prantl /// "Sanitize" a filename so that it can be used as an identifier.
334056396aeSDouglas Gregor static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
335056396aeSDouglas Gregor                                               SmallVectorImpl<char> &Buffer) {
336056396aeSDouglas Gregor   if (Name.empty())
337056396aeSDouglas Gregor     return Name;
338056396aeSDouglas Gregor 
339a7d03840SJordan Rose   if (!isValidIdentifier(Name)) {
340056396aeSDouglas Gregor     // If we don't already have something with the form of an identifier,
341056396aeSDouglas Gregor     // create a buffer with the sanitized name.
342056396aeSDouglas Gregor     Buffer.clear();
343a7d03840SJordan Rose     if (isDigit(Name[0]))
344056396aeSDouglas Gregor       Buffer.push_back('_');
345056396aeSDouglas Gregor     Buffer.reserve(Buffer.size() + Name.size());
346056396aeSDouglas Gregor     for (unsigned I = 0, N = Name.size(); I != N; ++I) {
347a7d03840SJordan Rose       if (isIdentifierBody(Name[I]))
348056396aeSDouglas Gregor         Buffer.push_back(Name[I]);
349056396aeSDouglas Gregor       else
350056396aeSDouglas Gregor         Buffer.push_back('_');
351056396aeSDouglas Gregor     }
352056396aeSDouglas Gregor 
353056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
354056396aeSDouglas Gregor   }
355056396aeSDouglas Gregor 
356056396aeSDouglas Gregor   while (llvm::StringSwitch<bool>(Name)
357056396aeSDouglas Gregor #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
358056396aeSDouglas Gregor #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
359056396aeSDouglas Gregor #include "clang/Basic/TokenKinds.def"
360056396aeSDouglas Gregor            .Default(false)) {
361056396aeSDouglas Gregor     if (Name.data() != Buffer.data())
362056396aeSDouglas Gregor       Buffer.append(Name.begin(), Name.end());
363056396aeSDouglas Gregor     Buffer.push_back('_');
364056396aeSDouglas Gregor     Name = StringRef(Buffer.data(), Buffer.size());
365056396aeSDouglas Gregor   }
366056396aeSDouglas Gregor 
367056396aeSDouglas Gregor   return Name;
368056396aeSDouglas Gregor }
369056396aeSDouglas Gregor 
3709fc8faf9SAdrian Prantl /// Determine whether the given file name is the name of a builtin
37134d52749SDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system
37234d52749SDouglas Gregor /// headers.
373ba1b5c98SBruno Cardoso Lopes bool ModuleMap::isBuiltinHeader(StringRef FileName) {
37434d52749SDouglas Gregor   return llvm::StringSwitch<bool>(FileName)
37534d52749SDouglas Gregor            .Case("float.h", true)
37634d52749SDouglas Gregor            .Case("iso646.h", true)
37734d52749SDouglas Gregor            .Case("limits.h", true)
37834d52749SDouglas Gregor            .Case("stdalign.h", true)
37934d52749SDouglas Gregor            .Case("stdarg.h", true)
3803c4b1290SBen Langmuir            .Case("stdatomic.h", true)
38134d52749SDouglas Gregor            .Case("stdbool.h", true)
38234d52749SDouglas Gregor            .Case("stddef.h", true)
38334d52749SDouglas Gregor            .Case("stdint.h", true)
38434d52749SDouglas Gregor            .Case("tgmath.h", true)
38534d52749SDouglas Gregor            .Case("unwind.h", true)
38634d52749SDouglas Gregor            .Default(false);
38734d52749SDouglas Gregor }
38834d52749SDouglas Gregor 
38992669ee4SDaniel Jasper ModuleMap::HeadersMap::iterator
39092669ee4SDaniel Jasper ModuleMap::findKnownHeader(const FileEntry *File) {
391040e1266SRichard Smith   resolveHeaderDirectives(File);
39259527666SDouglas Gregor   HeadersMap::iterator Known = Headers.find(File);
39347972afdSRichard Smith   if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
39447972afdSRichard Smith       Known == Headers.end() && File->getDir() == BuiltinIncludeDir &&
395ba1b5c98SBruno Cardoso Lopes       ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()))) {
3964eaf0a6cSDaniel Jasper     HeaderInfo.loadTopLevelSystemModules();
39792669ee4SDaniel Jasper     return Headers.find(File);
3984eaf0a6cSDaniel Jasper   }
39992669ee4SDaniel Jasper   return Known;
40092669ee4SDaniel Jasper }
40192669ee4SDaniel Jasper 
4024469138eSBen Langmuir ModuleMap::KnownHeader
4034469138eSBen Langmuir ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
4044469138eSBen Langmuir                     SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
40547972afdSRichard Smith   if (UmbrellaDirs.empty())
406afd1b1c9SEugene Zelenko     return {};
40747972afdSRichard Smith 
4084469138eSBen Langmuir   const DirectoryEntry *Dir = File->getDir();
4094469138eSBen Langmuir   assert(Dir && "file in no directory");
4104469138eSBen Langmuir 
4114469138eSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
4124469138eSBen Langmuir   // frameworks moving from top-level frameworks to embedded frameworks tend
4134469138eSBen Langmuir   // to be symlinked from the top-level location to the embedded location,
4144469138eSBen Langmuir   // and we need to resolve lookups as if we had found the embedded location.
4154469138eSBen Langmuir   StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
4164469138eSBen Langmuir 
4174469138eSBen Langmuir   // Keep walking up the directory hierarchy, looking for a directory with
4184469138eSBen Langmuir   // an umbrella header.
4194469138eSBen Langmuir   do {
4204469138eSBen Langmuir     auto KnownDir = UmbrellaDirs.find(Dir);
4214469138eSBen Langmuir     if (KnownDir != UmbrellaDirs.end())
4224469138eSBen Langmuir       return KnownHeader(KnownDir->second, NormalHeader);
4234469138eSBen Langmuir 
4244469138eSBen Langmuir     IntermediateDirs.push_back(Dir);
4254469138eSBen Langmuir 
4264469138eSBen Langmuir     // Retrieve our parent path.
4274469138eSBen Langmuir     DirName = llvm::sys::path::parent_path(DirName);
4284469138eSBen Langmuir     if (DirName.empty())
4294469138eSBen Langmuir       break;
4304469138eSBen Langmuir 
4314469138eSBen Langmuir     // Resolve the parent path to a directory entry.
4324469138eSBen Langmuir     Dir = SourceMgr.getFileManager().getDirectory(DirName);
4334469138eSBen Langmuir   } while (Dir);
434afd1b1c9SEugene Zelenko   return {};
4354469138eSBen Langmuir }
4364469138eSBen Langmuir 
43792669ee4SDaniel Jasper static bool violatesPrivateInclude(Module *RequestingModule,
43892669ee4SDaniel Jasper                                    const FileEntry *IncFileEnt,
4394eb8393cSRichard Smith                                    ModuleMap::KnownHeader Header) {
44092669ee4SDaniel Jasper #ifndef NDEBUG
4414eb8393cSRichard Smith   if (Header.getRole() & ModuleMap::PrivateHeader) {
44292669ee4SDaniel Jasper     // Check for consistency between the module header role
44392669ee4SDaniel Jasper     // as obtained from the lookup and as obtained from the module.
44492669ee4SDaniel Jasper     // This check is not cheap, so enable it only for debugging.
4452708e520SRichard Smith     bool IsPrivate = false;
4462708e520SRichard Smith     SmallVectorImpl<Module::Header> *HeaderList[] = {
4474eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_Private],
4484eb8393cSRichard Smith         &Header.getModule()->Headers[Module::HK_PrivateTextual]};
4492708e520SRichard Smith     for (auto *Hs : HeaderList)
4502708e520SRichard Smith       IsPrivate |=
4512708e520SRichard Smith           std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) {
4523c1a41adSRichard Smith             return H.Entry == IncFileEnt;
4532708e520SRichard Smith           }) != Hs->end();
4544eb8393cSRichard Smith     assert(IsPrivate && "inconsistent headers and roles");
45500bc95ecSRichard Smith   }
45692669ee4SDaniel Jasper #endif
4574eb8393cSRichard Smith   return !Header.isAccessibleFrom(RequestingModule);
45892669ee4SDaniel Jasper }
45992669ee4SDaniel Jasper 
46071e1a64fSBen Langmuir static Module *getTopLevelOrNull(Module *M) {
46171e1a64fSBen Langmuir   return M ? M->getTopLevelModule() : nullptr;
46271e1a64fSBen Langmuir }
46371e1a64fSBen Langmuir 
46492669ee4SDaniel Jasper void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
4658d4e90b3SRichard Smith                                         bool RequestingModuleIsModuleInterface,
46692669ee4SDaniel Jasper                                         SourceLocation FilenameLoc,
46792669ee4SDaniel Jasper                                         StringRef Filename,
46892669ee4SDaniel Jasper                                         const FileEntry *File) {
46992669ee4SDaniel Jasper   // No errors for indirect modules. This may be a bit of a problem for modules
47092669ee4SDaniel Jasper   // with no source files.
47171e1a64fSBen Langmuir   if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
47292669ee4SDaniel Jasper     return;
47392669ee4SDaniel Jasper 
474040e1266SRichard Smith   if (RequestingModule) {
47592669ee4SDaniel Jasper     resolveUses(RequestingModule, /*Complain=*/false);
476040e1266SRichard Smith     resolveHeaderDirectives(RequestingModule);
477040e1266SRichard Smith   }
47892669ee4SDaniel Jasper 
47971e1a64fSBen Langmuir   bool Excluded = false;
480d2d442caSCraig Topper   Module *Private = nullptr;
481d2d442caSCraig Topper   Module *NotUsed = nullptr;
48271e1a64fSBen Langmuir 
48371e1a64fSBen Langmuir   HeadersMap::iterator Known = findKnownHeader(File);
48471e1a64fSBen Langmuir   if (Known != Headers.end()) {
48571e1a64fSBen Langmuir     for (const KnownHeader &Header : Known->second) {
48692669ee4SDaniel Jasper       // Remember private headers for later printing of a diagnostic.
4874eb8393cSRichard Smith       if (violatesPrivateInclude(RequestingModule, File, Header)) {
48871e1a64fSBen Langmuir         Private = Header.getModule();
48992669ee4SDaniel Jasper         continue;
49092669ee4SDaniel Jasper       }
49192669ee4SDaniel Jasper 
49292669ee4SDaniel Jasper       // If uses need to be specified explicitly, we are only allowed to return
49392669ee4SDaniel Jasper       // modules that are explicitly used by the requesting module.
49492669ee4SDaniel Jasper       if (RequestingModule && LangOpts.ModulesDeclUse &&
4958f4d3ff1SRichard Smith           !RequestingModule->directlyUses(Header.getModule())) {
49671e1a64fSBen Langmuir         NotUsed = Header.getModule();
49792669ee4SDaniel Jasper         continue;
49892669ee4SDaniel Jasper       }
49992669ee4SDaniel Jasper 
50092669ee4SDaniel Jasper       // We have found a module that we can happily use.
50192669ee4SDaniel Jasper       return;
50292669ee4SDaniel Jasper     }
503feb54b6dSRichard Smith 
504feb54b6dSRichard Smith     Excluded = true;
50571e1a64fSBen Langmuir   }
50692669ee4SDaniel Jasper 
50792669ee4SDaniel Jasper   // We have found a header, but it is private.
508d2d442caSCraig Topper   if (Private) {
50911152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
51092669ee4SDaniel Jasper         << Filename;
51192669ee4SDaniel Jasper     return;
51292669ee4SDaniel Jasper   }
51392669ee4SDaniel Jasper 
51492669ee4SDaniel Jasper   // We have found a module, but we don't use it.
515d2d442caSCraig Topper   if (NotUsed) {
51611152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5174ea330c8SDaniel Jasper         << RequestingModule->getTopLevelModule()->Name << Filename;
51892669ee4SDaniel Jasper     return;
51992669ee4SDaniel Jasper   }
52092669ee4SDaniel Jasper 
52171e1a64fSBen Langmuir   if (Excluded || isHeaderInUmbrellaDirs(File))
52271e1a64fSBen Langmuir     return;
52371e1a64fSBen Langmuir 
52471e1a64fSBen Langmuir   // At this point, only non-modular includes remain.
52571e1a64fSBen Langmuir 
52671e1a64fSBen Langmuir   if (LangOpts.ModulesStrictDeclUse) {
52711152dd5SRichard Smith     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5284ea330c8SDaniel Jasper         << RequestingModule->getTopLevelModule()->Name << Filename;
529a67e4d32SManman Ren   } else if (RequestingModule && RequestingModuleIsModuleInterface &&
530a67e4d32SManman Ren              LangOpts.isCompilingModule()) {
531a67e4d32SManman Ren     // Do not diagnose when we are not compiling a module.
53271e1a64fSBen Langmuir     diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
53371e1a64fSBen Langmuir         diag::warn_non_modular_include_in_framework_module :
53471e1a64fSBen Langmuir         diag::warn_non_modular_include_in_module;
53570a7738fSManman Ren     Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
53670a7738fSManman Ren         << File->getName();
53771e1a64fSBen Langmuir   }
53892669ee4SDaniel Jasper }
53992669ee4SDaniel Jasper 
540ec87a50aSRichard Smith static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
541ec87a50aSRichard Smith                                 const ModuleMap::KnownHeader &Old) {
5428b7c0398SSean Silva   // Prefer available modules.
5438b7c0398SSean Silva   if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
5448b7c0398SSean Silva     return true;
5458b7c0398SSean Silva 
546ec87a50aSRichard Smith   // Prefer a public header over a private header.
547ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::PrivateHeader) !=
548ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::PrivateHeader))
549ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::PrivateHeader);
550ec87a50aSRichard Smith 
551ec87a50aSRichard Smith   // Prefer a non-textual header over a textual header.
552ec87a50aSRichard Smith   if ((New.getRole() & ModuleMap::TextualHeader) !=
553ec87a50aSRichard Smith       (Old.getRole() & ModuleMap::TextualHeader))
554ec87a50aSRichard Smith     return !(New.getRole() & ModuleMap::TextualHeader);
555ec87a50aSRichard Smith 
556ec87a50aSRichard Smith   // Don't have a reason to choose between these. Just keep the first one.
557ec87a50aSRichard Smith   return false;
558ec87a50aSRichard Smith }
559ec87a50aSRichard Smith 
560ed84df00SBruno Cardoso Lopes ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
561ed84df00SBruno Cardoso Lopes                                                       bool AllowTextual) {
562306d8920SRichard Smith   auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
563ed84df00SBruno Cardoso Lopes     if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
564afd1b1c9SEugene Zelenko       return {};
565306d8920SRichard Smith     return R;
566306d8920SRichard Smith   };
567306d8920SRichard Smith 
5684881e8b2SSean Silva   HeadersMap::iterator Known = findKnownHeader(File);
5691fb5c3a6SDouglas Gregor   if (Known != Headers.end()) {
570202210b3SRichard Smith     ModuleMap::KnownHeader Result;
57197da9178SDaniel Jasper     // Iterate over all modules that 'File' is part of to find the best fit.
5724881e8b2SSean Silva     for (KnownHeader &H : Known->second) {
5737e82e019SRichard Smith       // Prefer a header from the source module over all others.
5747e82e019SRichard Smith       if (H.getModule()->getTopLevelModule() == SourceModule)
5752f633e7cSRichard Smith         return MakeResult(H);
5764881e8b2SSean Silva       if (!Result || isBetterKnownHeader(H, Result))
5774881e8b2SSean Silva         Result = H;
57897da9178SDaniel Jasper     }
579306d8920SRichard Smith     return MakeResult(Result);
5801fb5c3a6SDouglas Gregor   }
581ab0c8a84SDouglas Gregor 
582386bb073SRichard Smith   return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
583386bb073SRichard Smith }
584386bb073SRichard Smith 
585386bb073SRichard Smith ModuleMap::KnownHeader
586386bb073SRichard Smith ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
587386bb073SRichard Smith   assert(!Headers.count(File) && "already have a module for this header");
588386bb073SRichard Smith 
589f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
5904469138eSBen Langmuir   KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
5914469138eSBen Langmuir   if (H) {
5924469138eSBen Langmuir     Module *Result = H.getModule();
593930a85ccSDouglas Gregor 
594930a85ccSDouglas Gregor     // Search up the module stack until we find a module with an umbrella
59573141fa9SDouglas Gregor     // directory.
596930a85ccSDouglas Gregor     Module *UmbrellaModule = Result;
59773141fa9SDouglas Gregor     while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
598930a85ccSDouglas Gregor       UmbrellaModule = UmbrellaModule->Parent;
599930a85ccSDouglas Gregor 
600930a85ccSDouglas Gregor     if (UmbrellaModule->InferSubmodules) {
6019d6448b1SBen Langmuir       const FileEntry *UmbrellaModuleMap =
6029d6448b1SBen Langmuir           getModuleMapFileForUniquing(UmbrellaModule);
6039d6448b1SBen Langmuir 
604a89c5ac4SDouglas Gregor       // Infer submodules for each of the directories we found between
605a89c5ac4SDouglas Gregor       // the directory of the umbrella header and the directory where
606a89c5ac4SDouglas Gregor       // the actual header is located.
6079458f82dSDouglas Gregor       bool Explicit = UmbrellaModule->InferExplicitSubmodules;
6089458f82dSDouglas Gregor 
6097033127bSDouglas Gregor       for (unsigned I = SkippedDirs.size(); I != 0; --I) {
610a89c5ac4SDouglas Gregor         // Find or create the module that corresponds to this directory name.
611056396aeSDouglas Gregor         SmallString<32> NameBuf;
612056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
6134469138eSBen Langmuir             llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
6149d6448b1SBen Langmuir         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6159d6448b1SBen Langmuir                                     Explicit).first;
6169d6448b1SBen Langmuir         InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
617ffbafa2aSBen Langmuir         Result->IsInferred = true;
618a89c5ac4SDouglas Gregor 
619a89c5ac4SDouglas Gregor         // Associate the module and the directory.
620a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I-1]] = Result;
621a89c5ac4SDouglas Gregor 
622a89c5ac4SDouglas Gregor         // If inferred submodules export everything they import, add a
623a89c5ac4SDouglas Gregor         // wildcard to the set of exports.
624930a85ccSDouglas Gregor         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
625d2d442caSCraig Topper           Result->Exports.push_back(Module::ExportDecl(nullptr, true));
626a89c5ac4SDouglas Gregor       }
627a89c5ac4SDouglas Gregor 
628a89c5ac4SDouglas Gregor       // Infer a submodule with the same name as this header file.
629056396aeSDouglas Gregor       SmallString<32> NameBuf;
630056396aeSDouglas Gregor       StringRef Name = sanitizeFilenameAsIdentifier(
631056396aeSDouglas Gregor                          llvm::sys::path::stem(File->getName()), NameBuf);
6329d6448b1SBen Langmuir       Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6339d6448b1SBen Langmuir                                   Explicit).first;
6349d6448b1SBen Langmuir       InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
635ffbafa2aSBen Langmuir       Result->IsInferred = true;
6363c5305c1SArgyrios Kyrtzidis       Result->addTopHeader(File);
637a89c5ac4SDouglas Gregor 
638a89c5ac4SDouglas Gregor       // If inferred submodules export everything they import, add a
639a89c5ac4SDouglas Gregor       // wildcard to the set of exports.
640930a85ccSDouglas Gregor       if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
641d2d442caSCraig Topper         Result->Exports.push_back(Module::ExportDecl(nullptr, true));
642a89c5ac4SDouglas Gregor     } else {
643a89c5ac4SDouglas Gregor       // Record each of the directories we stepped through as being part of
644a89c5ac4SDouglas Gregor       // the module we found, since the umbrella header covers them all.
645a89c5ac4SDouglas Gregor       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
646a89c5ac4SDouglas Gregor         UmbrellaDirs[SkippedDirs[I]] = Result;
647a89c5ac4SDouglas Gregor     }
648a89c5ac4SDouglas Gregor 
649386bb073SRichard Smith     KnownHeader Header(Result, NormalHeader);
650386bb073SRichard Smith     Headers[File].push_back(Header);
651386bb073SRichard Smith     return Header;
652a89c5ac4SDouglas Gregor   }
653a89c5ac4SDouglas Gregor 
654afd1b1c9SEugene Zelenko   return {};
655ab0c8a84SDouglas Gregor }
656ab0c8a84SDouglas Gregor 
657386bb073SRichard Smith ArrayRef<ModuleMap::KnownHeader>
658386bb073SRichard Smith ModuleMap::findAllModulesForHeader(const FileEntry *File) const {
659040e1266SRichard Smith   resolveHeaderDirectives(File);
660386bb073SRichard Smith   auto It = Headers.find(File);
661386bb073SRichard Smith   if (It == Headers.end())
662386bb073SRichard Smith     return None;
663386bb073SRichard Smith   return It->second;
664386bb073SRichard Smith }
665386bb073SRichard Smith 
666e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
667d2d442caSCraig Topper   return isHeaderUnavailableInModule(Header, nullptr);
66850996ce1SRichard Smith }
66950996ce1SRichard Smith 
67062bcd925SDmitri Gribenko bool
67162bcd925SDmitri Gribenko ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
67262bcd925SDmitri Gribenko                                        const Module *RequestingModule) const {
673040e1266SRichard Smith   resolveHeaderDirectives(Header);
674e4412640SArgyrios Kyrtzidis   HeadersMap::const_iterator Known = Headers.find(Header);
67597da9178SDaniel Jasper   if (Known != Headers.end()) {
67697da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator
67797da9178SDaniel Jasper              I = Known->second.begin(),
67897da9178SDaniel Jasper              E = Known->second.end();
67997da9178SDaniel Jasper          I != E; ++I) {
680052d95a6SBruno Cardoso Lopes 
681052d95a6SBruno Cardoso Lopes       if (I->isAvailable() &&
682052d95a6SBruno Cardoso Lopes           (!RequestingModule ||
683052d95a6SBruno Cardoso Lopes            I->getModule()->isSubModuleOf(RequestingModule))) {
684052d95a6SBruno Cardoso Lopes         // When no requesting module is available, the caller is looking if a
685052d95a6SBruno Cardoso Lopes         // header is part a module by only looking into the module map. This is
686052d95a6SBruno Cardoso Lopes         // done by warn_uncovered_module_header checks; don't consider textual
687052d95a6SBruno Cardoso Lopes         // headers part of it in this mode, otherwise we get misleading warnings
688052d95a6SBruno Cardoso Lopes         // that a umbrella header is not including a textual header.
689052d95a6SBruno Cardoso Lopes         if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
690052d95a6SBruno Cardoso Lopes           continue;
69197da9178SDaniel Jasper         return false;
69297da9178SDaniel Jasper       }
693052d95a6SBruno Cardoso Lopes     }
69497da9178SDaniel Jasper     return true;
69597da9178SDaniel Jasper   }
6961fb5c3a6SDouglas Gregor 
6971fb5c3a6SDouglas Gregor   const DirectoryEntry *Dir = Header->getDir();
698f857950dSDmitri Gribenko   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
6991fb5c3a6SDouglas Gregor   StringRef DirName = Dir->getName();
7001fb5c3a6SDouglas Gregor 
70150996ce1SRichard Smith   auto IsUnavailable = [&](const Module *M) {
70250996ce1SRichard Smith     return !M->isAvailable() && (!RequestingModule ||
70350996ce1SRichard Smith                                  M->isSubModuleOf(RequestingModule));
70450996ce1SRichard Smith   };
70550996ce1SRichard Smith 
7061fb5c3a6SDouglas Gregor   // Keep walking up the directory hierarchy, looking for a directory with
7071fb5c3a6SDouglas Gregor   // an umbrella header.
7081fb5c3a6SDouglas Gregor   do {
709e4412640SArgyrios Kyrtzidis     llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
7101fb5c3a6SDouglas Gregor       = UmbrellaDirs.find(Dir);
7111fb5c3a6SDouglas Gregor     if (KnownDir != UmbrellaDirs.end()) {
7121fb5c3a6SDouglas Gregor       Module *Found = KnownDir->second;
71350996ce1SRichard Smith       if (IsUnavailable(Found))
7141fb5c3a6SDouglas Gregor         return true;
7151fb5c3a6SDouglas Gregor 
7161fb5c3a6SDouglas Gregor       // Search up the module stack until we find a module with an umbrella
7171fb5c3a6SDouglas Gregor       // directory.
7181fb5c3a6SDouglas Gregor       Module *UmbrellaModule = Found;
7191fb5c3a6SDouglas Gregor       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
7201fb5c3a6SDouglas Gregor         UmbrellaModule = UmbrellaModule->Parent;
7211fb5c3a6SDouglas Gregor 
7221fb5c3a6SDouglas Gregor       if (UmbrellaModule->InferSubmodules) {
7231fb5c3a6SDouglas Gregor         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
7241fb5c3a6SDouglas Gregor           // Find or create the module that corresponds to this directory name.
725056396aeSDouglas Gregor           SmallString<32> NameBuf;
726056396aeSDouglas Gregor           StringRef Name = sanitizeFilenameAsIdentifier(
727056396aeSDouglas Gregor                              llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
728056396aeSDouglas Gregor                              NameBuf);
7291fb5c3a6SDouglas Gregor           Found = lookupModuleQualified(Name, Found);
7301fb5c3a6SDouglas Gregor           if (!Found)
7311fb5c3a6SDouglas Gregor             return false;
73250996ce1SRichard Smith           if (IsUnavailable(Found))
7331fb5c3a6SDouglas Gregor             return true;
7341fb5c3a6SDouglas Gregor         }
7351fb5c3a6SDouglas Gregor 
7361fb5c3a6SDouglas Gregor         // Infer a submodule with the same name as this header file.
737056396aeSDouglas Gregor         SmallString<32> NameBuf;
738056396aeSDouglas Gregor         StringRef Name = sanitizeFilenameAsIdentifier(
739056396aeSDouglas Gregor                            llvm::sys::path::stem(Header->getName()),
740056396aeSDouglas Gregor                            NameBuf);
7411fb5c3a6SDouglas Gregor         Found = lookupModuleQualified(Name, Found);
7421fb5c3a6SDouglas Gregor         if (!Found)
7431fb5c3a6SDouglas Gregor           return false;
7441fb5c3a6SDouglas Gregor       }
7451fb5c3a6SDouglas Gregor 
74650996ce1SRichard Smith       return IsUnavailable(Found);
7471fb5c3a6SDouglas Gregor     }
7481fb5c3a6SDouglas Gregor 
7491fb5c3a6SDouglas Gregor     SkippedDirs.push_back(Dir);
7501fb5c3a6SDouglas Gregor 
7511fb5c3a6SDouglas Gregor     // Retrieve our parent path.
7521fb5c3a6SDouglas Gregor     DirName = llvm::sys::path::parent_path(DirName);
7531fb5c3a6SDouglas Gregor     if (DirName.empty())
7541fb5c3a6SDouglas Gregor       break;
7551fb5c3a6SDouglas Gregor 
7561fb5c3a6SDouglas Gregor     // Resolve the parent path to a directory entry.
7571f76c4e8SManuel Klimek     Dir = SourceMgr.getFileManager().getDirectory(DirName);
7581fb5c3a6SDouglas Gregor   } while (Dir);
7591fb5c3a6SDouglas Gregor 
7601fb5c3a6SDouglas Gregor   return false;
7611fb5c3a6SDouglas Gregor }
7621fb5c3a6SDouglas Gregor 
763e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const {
764e4412640SArgyrios Kyrtzidis   llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
76588bdfb0eSDouglas Gregor   if (Known != Modules.end())
76688bdfb0eSDouglas Gregor     return Known->getValue();
76788bdfb0eSDouglas Gregor 
768d2d442caSCraig Topper   return nullptr;
76988bdfb0eSDouglas Gregor }
77088bdfb0eSDouglas Gregor 
771e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
772e4412640SArgyrios Kyrtzidis                                            Module *Context) const {
7732b82c2a5SDouglas Gregor   for(; Context; Context = Context->Parent) {
7742b82c2a5SDouglas Gregor     if (Module *Sub = lookupModuleQualified(Name, Context))
7752b82c2a5SDouglas Gregor       return Sub;
7762b82c2a5SDouglas Gregor   }
7772b82c2a5SDouglas Gregor 
7782b82c2a5SDouglas Gregor   return findModule(Name);
7792b82c2a5SDouglas Gregor }
7802b82c2a5SDouglas Gregor 
781e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
7822b82c2a5SDouglas Gregor   if (!Context)
7832b82c2a5SDouglas Gregor     return findModule(Name);
7842b82c2a5SDouglas Gregor 
785eb90e830SDouglas Gregor   return Context->findSubmodule(Name);
7862b82c2a5SDouglas Gregor }
7872b82c2a5SDouglas Gregor 
788c192d194SBruno Cardoso Lopes std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
789c192d194SBruno Cardoso Lopes                                                         Module *Parent,
790c192d194SBruno Cardoso Lopes                                                         bool IsFramework,
791c192d194SBruno Cardoso Lopes                                                         bool IsExplicit) {
79269021974SDouglas Gregor   // Try to find an existing module with this name.
793eb90e830SDouglas Gregor   if (Module *Sub = lookupModuleQualified(Name, Parent))
794eb90e830SDouglas Gregor     return std::make_pair(Sub, false);
79569021974SDouglas Gregor 
79669021974SDouglas Gregor   // Create a new module with this name.
7979ffe5a35SDavid Blaikie   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
7989ffe5a35SDavid Blaikie                               IsExplicit, NumCreatedModules++);
7996f722b4eSArgyrios Kyrtzidis   if (!Parent) {
8007e82e019SRichard Smith     if (LangOpts.CurrentModule == Name)
8017e82e019SRichard Smith       SourceModule = Result;
80269021974SDouglas Gregor     Modules[Name] = Result;
803c192d194SBruno Cardoso Lopes     ModuleScopeIDs[Result] = CurrentModuleScopeID;
8046f722b4eSArgyrios Kyrtzidis   }
80569021974SDouglas Gregor   return std::make_pair(Result, true);
80669021974SDouglas Gregor }
80769021974SDouglas Gregor 
808dd8b5337SRichard Smith Module *ModuleMap::createGlobalModuleForInterfaceUnit(SourceLocation Loc) {
809056bf77fSRichard Smith   assert(!PendingGlobalModule && "created multiple global modules");
810056bf77fSRichard Smith   PendingGlobalModule.reset(
811056bf77fSRichard Smith       new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
812056bf77fSRichard Smith                  /*IsExplicit*/ true, NumCreatedModules++));
813056bf77fSRichard Smith   PendingGlobalModule->Kind = Module::GlobalModuleFragment;
814056bf77fSRichard Smith   return PendingGlobalModule.get();
815dd8b5337SRichard Smith }
816dd8b5337SRichard Smith 
817bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
818dd8b5337SRichard Smith                                                 StringRef Name,
819dd8b5337SRichard Smith                                                 Module *GlobalModule) {
820bbcc9f04SRichard Smith   assert(LangOpts.CurrentModule == Name && "module name mismatch");
821bbcc9f04SRichard Smith   assert(!Modules[Name] && "redefining existing module");
822bbcc9f04SRichard Smith 
823bbcc9f04SRichard Smith   auto *Result =
824bbcc9f04SRichard Smith       new Module(Name, Loc, nullptr, /*IsFramework*/ false,
825bbcc9f04SRichard Smith                  /*IsExplicit*/ false, NumCreatedModules++);
826145e15a3SRichard Smith   Result->Kind = Module::ModuleInterfaceUnit;
827bbcc9f04SRichard Smith   Modules[Name] = SourceModule = Result;
828bbcc9f04SRichard Smith 
829dd8b5337SRichard Smith   // Reparent the current global module fragment as a submodule of this module.
830056bf77fSRichard Smith   assert(GlobalModule == PendingGlobalModule.get() &&
831056bf77fSRichard Smith          "unexpected global module");
832dd8b5337SRichard Smith   GlobalModule->setParent(Result);
833056bf77fSRichard Smith   PendingGlobalModule.release(); // now owned by parent
834dd8b5337SRichard Smith 
835bbcc9f04SRichard Smith   // Mark the main source file as being within the newly-created module so that
836bbcc9f04SRichard Smith   // declarations and macros are properly visibility-restricted to it.
837bbcc9f04SRichard Smith   auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
838bbcc9f04SRichard Smith   assert(MainFile && "no input file for module interface");
839bbcc9f04SRichard Smith   Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader));
840bbcc9f04SRichard Smith 
841bbcc9f04SRichard Smith   return Result;
842bbcc9f04SRichard Smith }
843bbcc9f04SRichard Smith 
8449fc8faf9SAdrian Prantl /// For a framework module, infer the framework against which we
84511dfe6feSDouglas Gregor /// should link.
84611dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
84711dfe6feSDouglas Gregor                                FileManager &FileMgr) {
84811dfe6feSDouglas Gregor   assert(Mod->IsFramework && "Can only infer linking for framework modules");
84911dfe6feSDouglas Gregor   assert(!Mod->isSubFramework() &&
85011dfe6feSDouglas Gregor          "Can only infer linking for top-level frameworks");
85111dfe6feSDouglas Gregor 
85211dfe6feSDouglas Gregor   SmallString<128> LibName;
85311dfe6feSDouglas Gregor   LibName += FrameworkDir->getName();
85411dfe6feSDouglas Gregor   llvm::sys::path::append(LibName, Mod->Name);
8558aaae5a9SJuergen Ributzka 
8568aaae5a9SJuergen Ributzka   // The library name of a framework has more than one possible extension since
8578aaae5a9SJuergen Ributzka   // the introduction of the text-based dynamic library format. We need to check
8588aaae5a9SJuergen Ributzka   // for both before we give up.
8598013e81dSBenjamin Kramer   for (const char *extension : {"", ".tbd"}) {
8608aaae5a9SJuergen Ributzka     llvm::sys::path::replace_extension(LibName, extension);
86111dfe6feSDouglas Gregor     if (FileMgr.getFile(LibName)) {
86211dfe6feSDouglas Gregor       Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
86311dfe6feSDouglas Gregor                                                        /*IsFramework=*/true));
8648aaae5a9SJuergen Ributzka       return;
8658aaae5a9SJuergen Ributzka     }
86611dfe6feSDouglas Gregor   }
86711dfe6feSDouglas Gregor }
86811dfe6feSDouglas Gregor 
869a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
870a525400dSBen Langmuir                                         bool IsSystem, Module *Parent) {
871c1d88ea5SBen Langmuir   Attributes Attrs;
872c1d88ea5SBen Langmuir   Attrs.IsSystem = IsSystem;
873a525400dSBen Langmuir   return inferFrameworkModule(FrameworkDir, Attrs, Parent);
874c1d88ea5SBen Langmuir }
875c1d88ea5SBen Langmuir 
876a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
877c1d88ea5SBen Langmuir                                         Attributes Attrs, Module *Parent) {
878a525400dSBen Langmuir   // Note: as an egregious but useful hack we use the real path here, because
879a525400dSBen Langmuir   // we might be looking at an embedded framework that symlinks out to a
880a525400dSBen Langmuir   // top-level framework, and we need to infer as if we were naming the
881a525400dSBen Langmuir   // top-level framework.
882a525400dSBen Langmuir   StringRef FrameworkDirName =
883a525400dSBen Langmuir       SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
884a525400dSBen Langmuir 
885a525400dSBen Langmuir   // In case this is a case-insensitive filesystem, use the canonical
886a525400dSBen Langmuir   // directory name as the ModuleName, since modules are case-sensitive.
887a525400dSBen Langmuir   // FIXME: we should be able to give a fix-it hint for the correct spelling.
888a525400dSBen Langmuir   SmallString<32> ModuleNameStorage;
889a525400dSBen Langmuir   StringRef ModuleName = sanitizeFilenameAsIdentifier(
890a525400dSBen Langmuir       llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
891c1d88ea5SBen Langmuir 
89256c64013SDouglas Gregor   // Check whether we've already found this module.
893e89dbc1dSDouglas Gregor   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
894e89dbc1dSDouglas Gregor     return Mod;
895e89dbc1dSDouglas Gregor 
8961f76c4e8SManuel Klimek   FileManager &FileMgr = SourceMgr.getFileManager();
89756c64013SDouglas Gregor 
8989194a91dSDouglas Gregor   // If the framework has a parent path from which we're allowed to infer
8999194a91dSDouglas Gregor   // a framework module, do so.
900beee15e7SBen Langmuir   const FileEntry *ModuleMapFile = nullptr;
9019194a91dSDouglas Gregor   if (!Parent) {
9024ddf2221SDouglas Gregor     // Determine whether we're allowed to infer a module map.
9039194a91dSDouglas Gregor     bool canInfer = false;
9044ddf2221SDouglas Gregor     if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
9059194a91dSDouglas Gregor       // Figure out the parent path.
9064ddf2221SDouglas Gregor       StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
9079194a91dSDouglas Gregor       if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) {
9089194a91dSDouglas Gregor         // Check whether we have already looked into the parent directory
9099194a91dSDouglas Gregor         // for a module map.
910e4412640SArgyrios Kyrtzidis         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
9119194a91dSDouglas Gregor           inferred = InferredDirectories.find(ParentDir);
9129194a91dSDouglas Gregor         if (inferred == InferredDirectories.end()) {
9139194a91dSDouglas Gregor           // We haven't looked here before. Load a module map, if there is
9149194a91dSDouglas Gregor           // one.
915984e1df7SBen Langmuir           bool IsFrameworkDir = Parent.endswith(".framework");
916984e1df7SBen Langmuir           if (const FileEntry *ModMapFile =
917984e1df7SBen Langmuir                 HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) {
918c1d88ea5SBen Langmuir             parseModuleMapFile(ModMapFile, Attrs.IsSystem, ParentDir);
9199194a91dSDouglas Gregor             inferred = InferredDirectories.find(ParentDir);
9209194a91dSDouglas Gregor           }
9219194a91dSDouglas Gregor 
9229194a91dSDouglas Gregor           if (inferred == InferredDirectories.end())
9239194a91dSDouglas Gregor             inferred = InferredDirectories.insert(
9249194a91dSDouglas Gregor                          std::make_pair(ParentDir, InferredDirectory())).first;
9259194a91dSDouglas Gregor         }
9269194a91dSDouglas Gregor 
9279194a91dSDouglas Gregor         if (inferred->second.InferModules) {
9289194a91dSDouglas Gregor           // We're allowed to infer for this directory, but make sure it's okay
9299194a91dSDouglas Gregor           // to infer this particular module.
9304ddf2221SDouglas Gregor           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
9319194a91dSDouglas Gregor           canInfer = std::find(inferred->second.ExcludedModules.begin(),
9329194a91dSDouglas Gregor                                inferred->second.ExcludedModules.end(),
9339194a91dSDouglas Gregor                                Name) == inferred->second.ExcludedModules.end();
9349194a91dSDouglas Gregor 
935c1d88ea5SBen Langmuir           Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
936c1d88ea5SBen Langmuir           Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
937c1d88ea5SBen Langmuir           Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
938ed84df00SBruno Cardoso Lopes           Attrs.NoUndeclaredIncludes |=
939ed84df00SBruno Cardoso Lopes               inferred->second.Attrs.NoUndeclaredIncludes;
940beee15e7SBen Langmuir           ModuleMapFile = inferred->second.ModuleMapFile;
9419194a91dSDouglas Gregor         }
9429194a91dSDouglas Gregor       }
9439194a91dSDouglas Gregor     }
9449194a91dSDouglas Gregor 
9459194a91dSDouglas Gregor     // If we're not allowed to infer a framework module, don't.
9469194a91dSDouglas Gregor     if (!canInfer)
947d2d442caSCraig Topper       return nullptr;
948beee15e7SBen Langmuir   } else
9499d6448b1SBen Langmuir     ModuleMapFile = getModuleMapFileForUniquing(Parent);
9509194a91dSDouglas Gregor 
9519194a91dSDouglas Gregor 
95256c64013SDouglas Gregor   // Look for an umbrella header.
9532c1dd271SDylan Noblesmith   SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
95417381a06SBenjamin Kramer   llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
955e89dbc1dSDouglas Gregor   const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
95656c64013SDouglas Gregor 
95756c64013SDouglas Gregor   // FIXME: If there's no umbrella header, we could probably scan the
95856c64013SDouglas Gregor   // framework to load *everything*. But, it's not clear that this is a good
95956c64013SDouglas Gregor   // idea.
96056c64013SDouglas Gregor   if (!UmbrellaHeader)
961d2d442caSCraig Topper     return nullptr;
96256c64013SDouglas Gregor 
9639d6448b1SBen Langmuir   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
964a7e2cc68SRichard Smith                               /*IsFramework=*/true, /*IsExplicit=*/false,
965a7e2cc68SRichard Smith                               NumCreatedModules++);
9669d6448b1SBen Langmuir   InferredModuleAllowedBy[Result] = ModuleMapFile;
9679d6448b1SBen Langmuir   Result->IsInferred = true;
9687e82e019SRichard Smith   if (!Parent) {
9697e82e019SRichard Smith     if (LangOpts.CurrentModule == ModuleName)
970ba7f2f71SDaniel Jasper       SourceModule = Result;
9717e82e019SRichard Smith     Modules[ModuleName] = Result;
972c192d194SBruno Cardoso Lopes     ModuleScopeIDs[Result] = CurrentModuleScopeID;
973ba7f2f71SDaniel Jasper   }
974c1d88ea5SBen Langmuir 
975c1d88ea5SBen Langmuir   Result->IsSystem |= Attrs.IsSystem;
976c1d88ea5SBen Langmuir   Result->IsExternC |= Attrs.IsExternC;
977c1d88ea5SBen Langmuir   Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
978ed84df00SBruno Cardoso Lopes   Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
9792b63d15fSRichard Smith   Result->Directory = FrameworkDir;
980a686e1b0SDouglas Gregor 
981322f633cSDouglas Gregor   // umbrella header "umbrella-header-name"
9822b63d15fSRichard Smith   //
9832b63d15fSRichard Smith   // The "Headers/" component of the name is implied because this is
9842b63d15fSRichard Smith   // a framework module.
9852b63d15fSRichard Smith   setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h");
986d8bd7537SDouglas Gregor 
987d8bd7537SDouglas Gregor   // export *
988d2d442caSCraig Topper   Result->Exports.push_back(Module::ExportDecl(nullptr, true));
989d8bd7537SDouglas Gregor 
990a89c5ac4SDouglas Gregor   // module * { export * }
991a89c5ac4SDouglas Gregor   Result->InferSubmodules = true;
992a89c5ac4SDouglas Gregor   Result->InferExportWildcard = true;
993a89c5ac4SDouglas Gregor 
994e89dbc1dSDouglas Gregor   // Look for subframeworks.
995c080917eSRafael Espindola   std::error_code EC;
9962c1dd271SDylan Noblesmith   SmallString<128> SubframeworksDirName
997ddaa69cbSDouglas Gregor     = StringRef(FrameworkDir->getName());
998e89dbc1dSDouglas Gregor   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
9992d4d8cb3SBenjamin Kramer   llvm::sys::path::native(SubframeworksDirName);
1000b171a59bSBruno Cardoso Lopes   vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
1001b171a59bSBruno Cardoso Lopes   for (vfs::directory_iterator Dir = FS.dir_begin(SubframeworksDirName, EC),
1002b171a59bSBruno Cardoso Lopes                                DirEnd;
1003e89dbc1dSDouglas Gregor        Dir != DirEnd && !EC; Dir.increment(EC)) {
1004b171a59bSBruno Cardoso Lopes     if (!StringRef(Dir->getName()).endswith(".framework"))
1005e89dbc1dSDouglas Gregor       continue;
1006f2161a70SDouglas Gregor 
1007b171a59bSBruno Cardoso Lopes     if (const DirectoryEntry *SubframeworkDir =
1008b171a59bSBruno Cardoso Lopes             FileMgr.getDirectory(Dir->getName())) {
100907c22b78SDouglas Gregor       // Note: as an egregious but useful hack, we use the real path here and
101007c22b78SDouglas Gregor       // check whether it is actually a subdirectory of the parent directory.
101107c22b78SDouglas Gregor       // This will not be the case if the 'subframework' is actually a symlink
101207c22b78SDouglas Gregor       // out to a top-level framework.
1013e00c8b20SDouglas Gregor       StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir);
101407c22b78SDouglas Gregor       bool FoundParent = false;
101507c22b78SDouglas Gregor       do {
101607c22b78SDouglas Gregor         // Get the parent directory name.
101707c22b78SDouglas Gregor         SubframeworkDirName
101807c22b78SDouglas Gregor           = llvm::sys::path::parent_path(SubframeworkDirName);
101907c22b78SDouglas Gregor         if (SubframeworkDirName.empty())
102007c22b78SDouglas Gregor           break;
102107c22b78SDouglas Gregor 
102207c22b78SDouglas Gregor         if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) {
102307c22b78SDouglas Gregor           FoundParent = true;
102407c22b78SDouglas Gregor           break;
102507c22b78SDouglas Gregor         }
102607c22b78SDouglas Gregor       } while (true);
102707c22b78SDouglas Gregor 
102807c22b78SDouglas Gregor       if (!FoundParent)
102907c22b78SDouglas Gregor         continue;
103007c22b78SDouglas Gregor 
1031e89dbc1dSDouglas Gregor       // FIXME: Do we want to warn about subframeworks without umbrella headers?
1032a525400dSBen Langmuir       inferFrameworkModule(SubframeworkDir, Attrs, Result);
1033e89dbc1dSDouglas Gregor     }
1034e89dbc1dSDouglas Gregor   }
1035e89dbc1dSDouglas Gregor 
103611dfe6feSDouglas Gregor   // If the module is a top-level framework, automatically link against the
103711dfe6feSDouglas Gregor   // framework.
103811dfe6feSDouglas Gregor   if (!Result->isSubFramework()) {
103911dfe6feSDouglas Gregor     inferFrameworkLink(Result, FrameworkDir, FileMgr);
104011dfe6feSDouglas Gregor   }
104111dfe6feSDouglas Gregor 
104256c64013SDouglas Gregor   return Result;
104356c64013SDouglas Gregor }
104456c64013SDouglas Gregor 
10458587dfd9SBruno Cardoso Lopes Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
10468587dfd9SBruno Cardoso Lopes                                         Module *ShadowingModule) {
10478587dfd9SBruno Cardoso Lopes 
10488587dfd9SBruno Cardoso Lopes   // Create a new module with this name.
10498587dfd9SBruno Cardoso Lopes   Module *Result =
10508587dfd9SBruno Cardoso Lopes       new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
10518587dfd9SBruno Cardoso Lopes                  /*IsExplicit=*/false, NumCreatedModules++);
10528587dfd9SBruno Cardoso Lopes   Result->ShadowingModule = ShadowingModule;
10538587dfd9SBruno Cardoso Lopes   Result->IsAvailable = false;
1054c192d194SBruno Cardoso Lopes   ModuleScopeIDs[Result] = CurrentModuleScopeID;
10558587dfd9SBruno Cardoso Lopes   ShadowModules.push_back(Result);
10568587dfd9SBruno Cardoso Lopes 
10578587dfd9SBruno Cardoso Lopes   return Result;
10588587dfd9SBruno Cardoso Lopes }
10598587dfd9SBruno Cardoso Lopes 
10602b63d15fSRichard Smith void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
10612b63d15fSRichard Smith                                   Twine NameAsWritten) {
106297da9178SDaniel Jasper   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
106373141fa9SDouglas Gregor   Mod->Umbrella = UmbrellaHeader;
10642b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
10657033127bSDouglas Gregor   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
1066b3a0fa48SBruno Cardoso Lopes 
1067b3a0fa48SBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1068b3a0fa48SBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1069b3a0fa48SBruno Cardoso Lopes     Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
1070a89c5ac4SDouglas Gregor }
1071a89c5ac4SDouglas Gregor 
10722b63d15fSRichard Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
10732b63d15fSRichard Smith                                Twine NameAsWritten) {
1074524e33e1SDouglas Gregor   Mod->Umbrella = UmbrellaDir;
10752b63d15fSRichard Smith   Mod->UmbrellaAsWritten = NameAsWritten.str();
1076524e33e1SDouglas Gregor   UmbrellaDirs[UmbrellaDir] = Mod;
1077524e33e1SDouglas Gregor }
1078524e33e1SDouglas Gregor 
1079040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod,
10809f6020bcSBruno Cardoso Lopes                                     Module::UnresolvedHeaderDirective Header,
10819f6020bcSBruno Cardoso Lopes                                     bool &NeedsFramework) {
1082040e1266SRichard Smith   // If there is a builtin counterpart to this file, add it now so it can
1083040e1266SRichard Smith   // wrap the system header.
1084040e1266SRichard Smith   if (resolveAsBuiltinHeader(Mod, Header)) {
1085040e1266SRichard Smith     // If we have both a builtin and system version of the file, the
1086040e1266SRichard Smith     // builtin version may want to inject macros into the system header, so
1087040e1266SRichard Smith     // force the system header to be treated as a textual header in this
1088040e1266SRichard Smith     // case.
1089040e1266SRichard Smith     Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
1090040e1266SRichard Smith         headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
1091040e1266SRichard Smith     Header.HasBuiltinHeader = true;
10923c1a41adSRichard Smith   }
1093040e1266SRichard Smith 
1094040e1266SRichard Smith   // If possible, don't stat the header until we need to. This requires the
1095040e1266SRichard Smith   // user to have provided us with some stat information about the file.
1096040e1266SRichard Smith   // FIXME: Add support for lazily stat'ing umbrella headers and excluded
1097040e1266SRichard Smith   // headers.
1098040e1266SRichard Smith   if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
1099040e1266SRichard Smith       Header.Kind != Module::HK_Excluded) {
1100040e1266SRichard Smith     // We expect more variation in mtime than size, so if we're given both,
1101040e1266SRichard Smith     // use the mtime as the key.
1102040e1266SRichard Smith     if (Header.ModTime)
1103040e1266SRichard Smith       LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
1104040e1266SRichard Smith     else
1105040e1266SRichard Smith       LazyHeadersBySize[*Header.Size].push_back(Mod);
1106040e1266SRichard Smith     Mod->UnresolvedHeaders.push_back(Header);
1107040e1266SRichard Smith     return;
1108040e1266SRichard Smith   }
1109040e1266SRichard Smith 
1110040e1266SRichard Smith   // We don't have stat information or can't defer looking this file up.
1111040e1266SRichard Smith   // Perform the lookup now.
11129f6020bcSBruno Cardoso Lopes   resolveHeader(Mod, Header, NeedsFramework);
1113040e1266SRichard Smith }
1114040e1266SRichard Smith 
1115040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
1116040e1266SRichard Smith   auto BySize = LazyHeadersBySize.find(File->getSize());
1117040e1266SRichard Smith   if (BySize != LazyHeadersBySize.end()) {
1118040e1266SRichard Smith     for (auto *M : BySize->second)
1119040e1266SRichard Smith       resolveHeaderDirectives(M);
1120040e1266SRichard Smith     LazyHeadersBySize.erase(BySize);
1121040e1266SRichard Smith   }
1122040e1266SRichard Smith 
1123040e1266SRichard Smith   auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
1124040e1266SRichard Smith   if (ByModTime != LazyHeadersByModTime.end()) {
1125040e1266SRichard Smith     for (auto *M : ByModTime->second)
1126040e1266SRichard Smith       resolveHeaderDirectives(M);
1127040e1266SRichard Smith     LazyHeadersByModTime.erase(ByModTime);
1128040e1266SRichard Smith   }
1129040e1266SRichard Smith }
1130040e1266SRichard Smith 
1131040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(Module *Mod) const {
11329f6020bcSBruno Cardoso Lopes   bool NeedsFramework = false;
1133040e1266SRichard Smith   for (auto &Header : Mod->UnresolvedHeaders)
1134040e1266SRichard Smith     // This operation is logically const; we're just changing how we represent
1135040e1266SRichard Smith     // the header information for this file.
11369f6020bcSBruno Cardoso Lopes     const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework);
1137040e1266SRichard Smith   Mod->UnresolvedHeaders.clear();
11380e98d938SNAKAMURA Takumi }
1139202210b3SRichard Smith 
11403c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header,
1141d8879c85SRichard Smith                           ModuleHeaderRole Role, bool Imported) {
1142386bb073SRichard Smith   KnownHeader KH(Mod, Role);
11433c1a41adSRichard Smith 
1144386bb073SRichard Smith   // Only add each header to the headers list once.
1145386bb073SRichard Smith   // FIXME: Should we diagnose if a header is listed twice in the
1146386bb073SRichard Smith   // same module definition?
1147386bb073SRichard Smith   auto &HeaderList = Headers[Header.Entry];
1148386bb073SRichard Smith   for (auto H : HeaderList)
1149386bb073SRichard Smith     if (H == KH)
1150386bb073SRichard Smith       return;
1151386bb073SRichard Smith 
1152386bb073SRichard Smith   HeaderList.push_back(KH);
11531ec383c7SPiotr Padlewski   Mod->Headers[headerRoleToKind(Role)].push_back(Header);
1154386bb073SRichard Smith 
11557e82e019SRichard Smith   bool isCompilingModuleHeader =
1156bbcc9f04SRichard Smith       LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
1157d8879c85SRichard Smith   if (!Imported || isCompilingModuleHeader) {
1158d8879c85SRichard Smith     // When we import HeaderFileInfo, the external source is expected to
1159d8879c85SRichard Smith     // set the isModuleHeader flag itself.
1160d8879c85SRichard Smith     HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
1161d8879c85SRichard Smith                                     isCompilingModuleHeader);
1162d8879c85SRichard Smith   }
1163e62cfd7cSBruno Cardoso Lopes 
1164e62cfd7cSBruno Cardoso Lopes   // Notify callbacks that we just added a new header.
1165e62cfd7cSBruno Cardoso Lopes   for (const auto &Cb : Callbacks)
1166f0841790SBruno Cardoso Lopes     Cb->moduleMapAddHeader(Header.Entry->getName());
1167a89c5ac4SDouglas Gregor }
1168a89c5ac4SDouglas Gregor 
11693c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
1170feb54b6dSRichard Smith   // Add this as a known header so we won't implicitly add it to any
1171feb54b6dSRichard Smith   // umbrella directory module.
1172feb54b6dSRichard Smith   // FIXME: Should we only exclude it from umbrella modules within the
1173feb54b6dSRichard Smith   // specified module?
11743c1a41adSRichard Smith   (void) Headers[Header.Entry];
11753c1a41adSRichard Smith 
11763c1a41adSRichard Smith   Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
1177feb54b6dSRichard Smith }
1178feb54b6dSRichard Smith 
1179514b636aSDouglas Gregor const FileEntry *
11804b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const {
11811f76c4e8SManuel Klimek   if (Module->DefinitionLoc.isInvalid())
1182d2d442caSCraig Topper     return nullptr;
1183514b636aSDouglas Gregor 
11841f76c4e8SManuel Klimek   return SourceMgr.getFileEntryForID(
11851f76c4e8SManuel Klimek            SourceMgr.getFileID(Module->DefinitionLoc));
1186514b636aSDouglas Gregor }
1187514b636aSDouglas Gregor 
11884b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
11899d6448b1SBen Langmuir   if (M->IsInferred) {
11909d6448b1SBen Langmuir     assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
11919d6448b1SBen Langmuir     return InferredModuleAllowedBy.find(M)->second;
11929d6448b1SBen Langmuir   }
11939d6448b1SBen Langmuir   return getContainingModuleMapFile(M);
11949d6448b1SBen Langmuir }
11959d6448b1SBen Langmuir 
11969d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
11979d6448b1SBen Langmuir   assert(M->IsInferred && "module not inferred");
11989d6448b1SBen Langmuir   InferredModuleAllowedBy[M] = ModMap;
11999d6448b1SBen Langmuir }
12009d6448b1SBen Langmuir 
1201cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() {
1202718292f2SDouglas Gregor   llvm::errs() << "Modules:";
1203718292f2SDouglas Gregor   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1204718292f2SDouglas Gregor                                         MEnd = Modules.end();
1205718292f2SDouglas Gregor        M != MEnd; ++M)
1206d28d1b8dSDouglas Gregor     M->getValue()->print(llvm::errs(), 2);
1207718292f2SDouglas Gregor 
1208718292f2SDouglas Gregor   llvm::errs() << "Headers:";
120959527666SDouglas Gregor   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1210718292f2SDouglas Gregor        H != HEnd; ++H) {
121197da9178SDaniel Jasper     llvm::errs() << "  \"" << H->first->getName() << "\" -> ";
121297da9178SDaniel Jasper     for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
121397da9178SDaniel Jasper                                                       E = H->second.end();
121497da9178SDaniel Jasper          I != E; ++I) {
121597da9178SDaniel Jasper       if (I != H->second.begin())
121697da9178SDaniel Jasper         llvm::errs() << ",";
121797da9178SDaniel Jasper       llvm::errs() << I->getModule()->getFullModuleName();
121897da9178SDaniel Jasper     }
121997da9178SDaniel Jasper     llvm::errs() << "\n";
1220718292f2SDouglas Gregor   }
1221718292f2SDouglas Gregor }
1222718292f2SDouglas Gregor 
12232b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
122442413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedExports);
122542413141SRichard Smith   Mod->UnresolvedExports.clear();
122642413141SRichard Smith   for (auto &UE : Unresolved) {
122742413141SRichard Smith     Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
1228f5eedd05SDouglas Gregor     if (Export.getPointer() || Export.getInt())
12292b82c2a5SDouglas Gregor       Mod->Exports.push_back(Export);
12302b82c2a5SDouglas Gregor     else
123142413141SRichard Smith       Mod->UnresolvedExports.push_back(UE);
12322b82c2a5SDouglas Gregor   }
123342413141SRichard Smith   return !Mod->UnresolvedExports.empty();
12342b82c2a5SDouglas Gregor }
12352b82c2a5SDouglas Gregor 
1236ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
123742413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedDirectUses);
123842413141SRichard Smith   Mod->UnresolvedDirectUses.clear();
123942413141SRichard Smith   for (auto &UDU : Unresolved) {
124042413141SRichard Smith     Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
1241ba7f2f71SDaniel Jasper     if (DirectUse)
1242ba7f2f71SDaniel Jasper       Mod->DirectUses.push_back(DirectUse);
1243ba7f2f71SDaniel Jasper     else
124442413141SRichard Smith       Mod->UnresolvedDirectUses.push_back(UDU);
1245ba7f2f71SDaniel Jasper   }
124642413141SRichard Smith   return !Mod->UnresolvedDirectUses.empty();
1247ba7f2f71SDaniel Jasper }
1248ba7f2f71SDaniel Jasper 
1249fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
125042413141SRichard Smith   auto Unresolved = std::move(Mod->UnresolvedConflicts);
125142413141SRichard Smith   Mod->UnresolvedConflicts.clear();
125242413141SRichard Smith   for (auto &UC : Unresolved) {
125342413141SRichard Smith     if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1254fb912657SDouglas Gregor       Module::Conflict Conflict;
1255fb912657SDouglas Gregor       Conflict.Other = OtherMod;
125642413141SRichard Smith       Conflict.Message = UC.Message;
1257fb912657SDouglas Gregor       Mod->Conflicts.push_back(Conflict);
125842413141SRichard Smith     } else
125942413141SRichard Smith       Mod->UnresolvedConflicts.push_back(UC);
1260fb912657SDouglas Gregor   }
126142413141SRichard Smith   return !Mod->UnresolvedConflicts.empty();
1262fb912657SDouglas Gregor }
1263fb912657SDouglas Gregor 
1264718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1265718292f2SDouglas Gregor // Module map file parser
1266718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1267718292f2SDouglas Gregor 
1268718292f2SDouglas Gregor namespace clang {
1269afd1b1c9SEugene Zelenko 
12709fc8faf9SAdrian Prantl   /// A token in a module map file.
1271718292f2SDouglas Gregor   struct MMToken {
1272718292f2SDouglas Gregor     enum TokenKind {
12731fb5c3a6SDouglas Gregor       Comma,
127435b13eceSDouglas Gregor       ConfigMacros,
1275fb912657SDouglas Gregor       Conflict,
1276718292f2SDouglas Gregor       EndOfFile,
1277718292f2SDouglas Gregor       HeaderKeyword,
1278718292f2SDouglas Gregor       Identifier,
1279a3feee2aSRichard Smith       Exclaim,
128059527666SDouglas Gregor       ExcludeKeyword,
1281718292f2SDouglas Gregor       ExplicitKeyword,
12822b82c2a5SDouglas Gregor       ExportKeyword,
1283f0b11de2SDouglas Gregor       ExportAsKeyword,
128497292843SDaniel Jasper       ExternKeyword,
1285755b2055SDouglas Gregor       FrameworkKeyword,
12866ddfca91SDouglas Gregor       LinkKeyword,
1287718292f2SDouglas Gregor       ModuleKeyword,
12882b82c2a5SDouglas Gregor       Period,
1289b53e5483SLawrence Crowl       PrivateKeyword,
1290718292f2SDouglas Gregor       UmbrellaKeyword,
1291ba7f2f71SDaniel Jasper       UseKeyword,
12921fb5c3a6SDouglas Gregor       RequiresKeyword,
12932b82c2a5SDouglas Gregor       Star,
1294718292f2SDouglas Gregor       StringLiteral,
1295040e1266SRichard Smith       IntegerLiteral,
1296306d8920SRichard Smith       TextualKeyword,
1297718292f2SDouglas Gregor       LBrace,
1298a686e1b0SDouglas Gregor       RBrace,
1299a686e1b0SDouglas Gregor       LSquare,
1300a686e1b0SDouglas Gregor       RSquare
1301718292f2SDouglas Gregor     } Kind;
1302718292f2SDouglas Gregor 
1303718292f2SDouglas Gregor     unsigned Location;
1304718292f2SDouglas Gregor     unsigned StringLength;
1305040e1266SRichard Smith     union {
1306040e1266SRichard Smith       // If Kind != IntegerLiteral.
1307718292f2SDouglas Gregor       const char *StringData;
1308afd1b1c9SEugene Zelenko 
1309040e1266SRichard Smith       // If Kind == IntegerLiteral.
1310040e1266SRichard Smith       uint64_t IntegerValue;
1311040e1266SRichard Smith     };
1312718292f2SDouglas Gregor 
1313718292f2SDouglas Gregor     void clear() {
1314718292f2SDouglas Gregor       Kind = EndOfFile;
1315718292f2SDouglas Gregor       Location = 0;
1316718292f2SDouglas Gregor       StringLength = 0;
1317d2d442caSCraig Topper       StringData = nullptr;
1318718292f2SDouglas Gregor     }
1319718292f2SDouglas Gregor 
1320718292f2SDouglas Gregor     bool is(TokenKind K) const { return Kind == K; }
1321718292f2SDouglas Gregor 
1322718292f2SDouglas Gregor     SourceLocation getLocation() const {
1323718292f2SDouglas Gregor       return SourceLocation::getFromRawEncoding(Location);
1324718292f2SDouglas Gregor     }
1325718292f2SDouglas Gregor 
1326040e1266SRichard Smith     uint64_t getInteger() const {
1327040e1266SRichard Smith       return Kind == IntegerLiteral ? IntegerValue : 0;
1328040e1266SRichard Smith     }
1329040e1266SRichard Smith 
1330718292f2SDouglas Gregor     StringRef getString() const {
1331040e1266SRichard Smith       return Kind == IntegerLiteral ? StringRef()
1332040e1266SRichard Smith                                     : StringRef(StringData, StringLength);
1333718292f2SDouglas Gregor     }
1334718292f2SDouglas Gregor   };
1335718292f2SDouglas Gregor 
1336718292f2SDouglas Gregor   class ModuleMapParser {
1337718292f2SDouglas Gregor     Lexer &L;
1338718292f2SDouglas Gregor     SourceManager &SourceMgr;
1339bc10b9fbSDouglas Gregor 
13409fc8faf9SAdrian Prantl     /// Default target information, used only for string literal
1341bc10b9fbSDouglas Gregor     /// parsing.
1342bc10b9fbSDouglas Gregor     const TargetInfo *Target;
1343bc10b9fbSDouglas Gregor 
1344718292f2SDouglas Gregor     DiagnosticsEngine &Diags;
1345718292f2SDouglas Gregor     ModuleMap &Map;
1346718292f2SDouglas Gregor 
13479fc8faf9SAdrian Prantl     /// The current module map file.
1348beee15e7SBen Langmuir     const FileEntry *ModuleMapFile;
1349beee15e7SBen Langmuir 
13509f6020bcSBruno Cardoso Lopes     /// Source location of most recent parsed module declaration
13519f6020bcSBruno Cardoso Lopes     SourceLocation CurrModuleDeclLoc;
13529f6020bcSBruno Cardoso Lopes 
13539fc8faf9SAdrian Prantl     /// The directory that file names in this module map file should
13549acb99e3SRichard Smith     /// be resolved relative to.
13555257fc63SDouglas Gregor     const DirectoryEntry *Directory;
13565257fc63SDouglas Gregor 
13579fc8faf9SAdrian Prantl     /// Whether this module map is in a system header directory.
1358963c5535SDouglas Gregor     bool IsSystem;
1359963c5535SDouglas Gregor 
13609fc8faf9SAdrian Prantl     /// Whether an error occurred.
1361afd1b1c9SEugene Zelenko     bool HadError = false;
1362718292f2SDouglas Gregor 
13639fc8faf9SAdrian Prantl     /// Stores string data for the various string literals referenced
1364718292f2SDouglas Gregor     /// during parsing.
1365718292f2SDouglas Gregor     llvm::BumpPtrAllocator StringData;
1366718292f2SDouglas Gregor 
13679fc8faf9SAdrian Prantl     /// The current token.
1368718292f2SDouglas Gregor     MMToken Tok;
1369718292f2SDouglas Gregor 
13709fc8faf9SAdrian Prantl     /// The active module.
1371afd1b1c9SEugene Zelenko     Module *ActiveModule = nullptr;
1372718292f2SDouglas Gregor 
13739fc8faf9SAdrian Prantl     /// Whether a module uses the 'requires excluded' hack to mark its
13747ff29148SBen Langmuir     /// contents as 'textual'.
13757ff29148SBen Langmuir     ///
13767ff29148SBen Langmuir     /// On older Darwin SDK versions, 'requires excluded' is used to mark the
13777ff29148SBen Langmuir     /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
13787ff29148SBen Langmuir     /// non-modular headers.  For backwards compatibility, we continue to
13797ff29148SBen Langmuir     /// support this idiom for just these modules, and map the headers to
13807ff29148SBen Langmuir     /// 'textual' to match the original intent.
13817ff29148SBen Langmuir     llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
13827ff29148SBen Langmuir 
13839fc8faf9SAdrian Prantl     /// Consume the current token and return its location.
1384718292f2SDouglas Gregor     SourceLocation consumeToken();
1385718292f2SDouglas Gregor 
13869fc8faf9SAdrian Prantl     /// Skip tokens until we reach the a token with the given kind
1387718292f2SDouglas Gregor     /// (or the end of the file).
1388718292f2SDouglas Gregor     void skipUntil(MMToken::TokenKind K);
1389718292f2SDouglas Gregor 
1390afd1b1c9SEugene Zelenko     using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
1391afd1b1c9SEugene Zelenko 
1392e7ab3669SDouglas Gregor     bool parseModuleId(ModuleId &Id);
1393718292f2SDouglas Gregor     void parseModuleDecl();
139497292843SDaniel Jasper     void parseExternModuleDecl();
13951fb5c3a6SDouglas Gregor     void parseRequiresDecl();
1396afd1b1c9SEugene Zelenko     void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
1397524e33e1SDouglas Gregor     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
13982b82c2a5SDouglas Gregor     void parseExportDecl();
1399f0b11de2SDouglas Gregor     void parseExportAsDecl();
1400ba7f2f71SDaniel Jasper     void parseUseDecl();
14016ddfca91SDouglas Gregor     void parseLinkDecl();
140235b13eceSDouglas Gregor     void parseConfigMacros();
1403fb912657SDouglas Gregor     void parseConflict();
14049194a91dSDouglas Gregor     void parseInferredModuleDecl(bool Framework, bool Explicit);
1405c1d88ea5SBen Langmuir 
1406afd1b1c9SEugene Zelenko     using Attributes = ModuleMap::Attributes;
1407afd1b1c9SEugene Zelenko 
14084442605fSBill Wendling     bool parseOptionalAttributes(Attributes &Attrs);
1409718292f2SDouglas Gregor 
1410718292f2SDouglas Gregor   public:
1411718292f2SDouglas Gregor     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
14128587dfd9SBruno Cardoso Lopes                              const TargetInfo *Target, DiagnosticsEngine &Diags,
14138587dfd9SBruno Cardoso Lopes                              ModuleMap &Map, const FileEntry *ModuleMapFile,
1414c192d194SBruno Cardoso Lopes                              const DirectoryEntry *Directory, bool IsSystem)
1415bc10b9fbSDouglas Gregor         : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
1416beee15e7SBen Langmuir           ModuleMapFile(ModuleMapFile), Directory(Directory),
1417c192d194SBruno Cardoso Lopes           IsSystem(IsSystem) {
1418718292f2SDouglas Gregor       Tok.clear();
1419718292f2SDouglas Gregor       consumeToken();
1420718292f2SDouglas Gregor     }
1421718292f2SDouglas Gregor 
1422718292f2SDouglas Gregor     bool parseModuleMapFile();
14238128f332SRichard Smith 
14248128f332SRichard Smith     bool terminatedByDirective() { return false; }
14258128f332SRichard Smith     SourceLocation getLocation() { return Tok.getLocation(); }
1426718292f2SDouglas Gregor   };
1427afd1b1c9SEugene Zelenko 
1428afd1b1c9SEugene Zelenko } // namespace clang
1429718292f2SDouglas Gregor 
1430718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
1431718292f2SDouglas Gregor   SourceLocation Result = Tok.getLocation();
1432718292f2SDouglas Gregor 
14338128f332SRichard Smith retry:
14348128f332SRichard Smith   Tok.clear();
1435718292f2SDouglas Gregor   Token LToken;
1436718292f2SDouglas Gregor   L.LexFromRawLexer(LToken);
1437718292f2SDouglas Gregor   Tok.Location = LToken.getLocation().getRawEncoding();
1438718292f2SDouglas Gregor   switch (LToken.getKind()) {
14392d57cea2SAlp Toker   case tok::raw_identifier: {
14402d57cea2SAlp Toker     StringRef RI = LToken.getRawIdentifier();
14412d57cea2SAlp Toker     Tok.StringData = RI.data();
14422d57cea2SAlp Toker     Tok.StringLength = RI.size();
14432d57cea2SAlp Toker     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
144435b13eceSDouglas Gregor                  .Case("config_macros", MMToken::ConfigMacros)
1445fb912657SDouglas Gregor                  .Case("conflict", MMToken::Conflict)
144659527666SDouglas Gregor                  .Case("exclude", MMToken::ExcludeKeyword)
1447718292f2SDouglas Gregor                  .Case("explicit", MMToken::ExplicitKeyword)
14482b82c2a5SDouglas Gregor                  .Case("export", MMToken::ExportKeyword)
1449f0b11de2SDouglas Gregor                  .Case("export_as", MMToken::ExportAsKeyword)
145097292843SDaniel Jasper                  .Case("extern", MMToken::ExternKeyword)
1451755b2055SDouglas Gregor                  .Case("framework", MMToken::FrameworkKeyword)
145235b13eceSDouglas Gregor                  .Case("header", MMToken::HeaderKeyword)
14536ddfca91SDouglas Gregor                  .Case("link", MMToken::LinkKeyword)
1454718292f2SDouglas Gregor                  .Case("module", MMToken::ModuleKeyword)
1455b53e5483SLawrence Crowl                  .Case("private", MMToken::PrivateKeyword)
14561fb5c3a6SDouglas Gregor                  .Case("requires", MMToken::RequiresKeyword)
1457306d8920SRichard Smith                  .Case("textual", MMToken::TextualKeyword)
1458718292f2SDouglas Gregor                  .Case("umbrella", MMToken::UmbrellaKeyword)
1459ba7f2f71SDaniel Jasper                  .Case("use", MMToken::UseKeyword)
1460718292f2SDouglas Gregor                  .Default(MMToken::Identifier);
1461718292f2SDouglas Gregor     break;
14622d57cea2SAlp Toker   }
1463718292f2SDouglas Gregor 
14641fb5c3a6SDouglas Gregor   case tok::comma:
14651fb5c3a6SDouglas Gregor     Tok.Kind = MMToken::Comma;
14661fb5c3a6SDouglas Gregor     break;
14671fb5c3a6SDouglas Gregor 
1468718292f2SDouglas Gregor   case tok::eof:
1469718292f2SDouglas Gregor     Tok.Kind = MMToken::EndOfFile;
1470718292f2SDouglas Gregor     break;
1471718292f2SDouglas Gregor 
1472718292f2SDouglas Gregor   case tok::l_brace:
1473718292f2SDouglas Gregor     Tok.Kind = MMToken::LBrace;
1474718292f2SDouglas Gregor     break;
1475718292f2SDouglas Gregor 
1476a686e1b0SDouglas Gregor   case tok::l_square:
1477a686e1b0SDouglas Gregor     Tok.Kind = MMToken::LSquare;
1478a686e1b0SDouglas Gregor     break;
1479a686e1b0SDouglas Gregor 
14802b82c2a5SDouglas Gregor   case tok::period:
14812b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Period;
14822b82c2a5SDouglas Gregor     break;
14832b82c2a5SDouglas Gregor 
1484718292f2SDouglas Gregor   case tok::r_brace:
1485718292f2SDouglas Gregor     Tok.Kind = MMToken::RBrace;
1486718292f2SDouglas Gregor     break;
1487718292f2SDouglas Gregor 
1488a686e1b0SDouglas Gregor   case tok::r_square:
1489a686e1b0SDouglas Gregor     Tok.Kind = MMToken::RSquare;
1490a686e1b0SDouglas Gregor     break;
1491a686e1b0SDouglas Gregor 
14922b82c2a5SDouglas Gregor   case tok::star:
14932b82c2a5SDouglas Gregor     Tok.Kind = MMToken::Star;
14942b82c2a5SDouglas Gregor     break;
14952b82c2a5SDouglas Gregor 
1496a3feee2aSRichard Smith   case tok::exclaim:
1497a3feee2aSRichard Smith     Tok.Kind = MMToken::Exclaim;
1498a3feee2aSRichard Smith     break;
1499a3feee2aSRichard Smith 
1500718292f2SDouglas Gregor   case tok::string_literal: {
1501d67aea28SRichard Smith     if (LToken.hasUDSuffix()) {
1502d67aea28SRichard Smith       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
1503d67aea28SRichard Smith       HadError = true;
1504d67aea28SRichard Smith       goto retry;
1505d67aea28SRichard Smith     }
1506d67aea28SRichard Smith 
1507718292f2SDouglas Gregor     // Parse the string literal.
1508718292f2SDouglas Gregor     LangOptions LangOpts;
15099d5583efSCraig Topper     StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
1510718292f2SDouglas Gregor     if (StringLiteral.hadError)
1511718292f2SDouglas Gregor       goto retry;
1512718292f2SDouglas Gregor 
1513718292f2SDouglas Gregor     // Copy the string literal into our string data allocator.
1514718292f2SDouglas Gregor     unsigned Length = StringLiteral.GetStringLength();
1515718292f2SDouglas Gregor     char *Saved = StringData.Allocate<char>(Length + 1);
1516718292f2SDouglas Gregor     memcpy(Saved, StringLiteral.GetString().data(), Length);
1517718292f2SDouglas Gregor     Saved[Length] = 0;
1518718292f2SDouglas Gregor 
1519718292f2SDouglas Gregor     // Form the token.
1520718292f2SDouglas Gregor     Tok.Kind = MMToken::StringLiteral;
1521718292f2SDouglas Gregor     Tok.StringData = Saved;
1522718292f2SDouglas Gregor     Tok.StringLength = Length;
1523718292f2SDouglas Gregor     break;
1524718292f2SDouglas Gregor   }
1525718292f2SDouglas Gregor 
1526040e1266SRichard Smith   case tok::numeric_constant: {
1527040e1266SRichard Smith     // We don't support any suffixes or other complications.
1528040e1266SRichard Smith     SmallString<32> SpellingBuffer;
1529040e1266SRichard Smith     SpellingBuffer.resize(LToken.getLength() + 1);
1530040e1266SRichard Smith     const char *Start = SpellingBuffer.data();
1531040e1266SRichard Smith     unsigned Length =
1532040e1266SRichard Smith         Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts());
1533040e1266SRichard Smith     uint64_t Value;
1534040e1266SRichard Smith     if (StringRef(Start, Length).getAsInteger(0, Value)) {
1535040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1536040e1266SRichard Smith       HadError = true;
1537040e1266SRichard Smith       goto retry;
1538040e1266SRichard Smith     }
1539040e1266SRichard Smith 
1540040e1266SRichard Smith     Tok.Kind = MMToken::IntegerLiteral;
1541040e1266SRichard Smith     Tok.IntegerValue = Value;
1542040e1266SRichard Smith     break;
1543040e1266SRichard Smith   }
1544040e1266SRichard Smith 
1545718292f2SDouglas Gregor   case tok::comment:
1546718292f2SDouglas Gregor     goto retry;
1547718292f2SDouglas Gregor 
15488128f332SRichard Smith   case tok::hash:
15498128f332SRichard Smith     // A module map can be terminated prematurely by
15508128f332SRichard Smith     //   #pragma clang module contents
15518128f332SRichard Smith     // When building the module, we'll treat the rest of the file as the
15528128f332SRichard Smith     // contents of the module.
15538128f332SRichard Smith     {
15548128f332SRichard Smith       auto NextIsIdent = [&](StringRef Str) -> bool {
15558128f332SRichard Smith         L.LexFromRawLexer(LToken);
15568128f332SRichard Smith         return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
15578128f332SRichard Smith                LToken.getRawIdentifier() == Str;
15588128f332SRichard Smith       };
15598128f332SRichard Smith       if (NextIsIdent("pragma") && NextIsIdent("clang") &&
15608128f332SRichard Smith           NextIsIdent("module") && NextIsIdent("contents")) {
15618128f332SRichard Smith         Tok.Kind = MMToken::EndOfFile;
15628128f332SRichard Smith         break;
15638128f332SRichard Smith       }
15648128f332SRichard Smith     }
15658128f332SRichard Smith     LLVM_FALLTHROUGH;
15668128f332SRichard Smith 
1567718292f2SDouglas Gregor   default:
15688128f332SRichard Smith     Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1569718292f2SDouglas Gregor     HadError = true;
1570718292f2SDouglas Gregor     goto retry;
1571718292f2SDouglas Gregor   }
1572718292f2SDouglas Gregor 
1573718292f2SDouglas Gregor   return Result;
1574718292f2SDouglas Gregor }
1575718292f2SDouglas Gregor 
1576718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
1577718292f2SDouglas Gregor   unsigned braceDepth = 0;
1578a686e1b0SDouglas Gregor   unsigned squareDepth = 0;
1579718292f2SDouglas Gregor   do {
1580718292f2SDouglas Gregor     switch (Tok.Kind) {
1581718292f2SDouglas Gregor     case MMToken::EndOfFile:
1582718292f2SDouglas Gregor       return;
1583718292f2SDouglas Gregor 
1584718292f2SDouglas Gregor     case MMToken::LBrace:
1585a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1586718292f2SDouglas Gregor         return;
1587718292f2SDouglas Gregor 
1588718292f2SDouglas Gregor       ++braceDepth;
1589718292f2SDouglas Gregor       break;
1590718292f2SDouglas Gregor 
1591a686e1b0SDouglas Gregor     case MMToken::LSquare:
1592a686e1b0SDouglas Gregor       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1593a686e1b0SDouglas Gregor         return;
1594a686e1b0SDouglas Gregor 
1595a686e1b0SDouglas Gregor       ++squareDepth;
1596a686e1b0SDouglas Gregor       break;
1597a686e1b0SDouglas Gregor 
1598718292f2SDouglas Gregor     case MMToken::RBrace:
1599718292f2SDouglas Gregor       if (braceDepth > 0)
1600718292f2SDouglas Gregor         --braceDepth;
1601718292f2SDouglas Gregor       else if (Tok.is(K))
1602718292f2SDouglas Gregor         return;
1603718292f2SDouglas Gregor       break;
1604718292f2SDouglas Gregor 
1605a686e1b0SDouglas Gregor     case MMToken::RSquare:
1606a686e1b0SDouglas Gregor       if (squareDepth > 0)
1607a686e1b0SDouglas Gregor         --squareDepth;
1608a686e1b0SDouglas Gregor       else if (Tok.is(K))
1609a686e1b0SDouglas Gregor         return;
1610a686e1b0SDouglas Gregor       break;
1611a686e1b0SDouglas Gregor 
1612718292f2SDouglas Gregor     default:
1613a686e1b0SDouglas Gregor       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
1614718292f2SDouglas Gregor         return;
1615718292f2SDouglas Gregor       break;
1616718292f2SDouglas Gregor     }
1617718292f2SDouglas Gregor 
1618718292f2SDouglas Gregor    consumeToken();
1619718292f2SDouglas Gregor   } while (true);
1620718292f2SDouglas Gregor }
1621718292f2SDouglas Gregor 
16229fc8faf9SAdrian Prantl /// Parse a module-id.
1623e7ab3669SDouglas Gregor ///
1624e7ab3669SDouglas Gregor ///   module-id:
1625e7ab3669SDouglas Gregor ///     identifier
1626e7ab3669SDouglas Gregor ///     identifier '.' module-id
1627e7ab3669SDouglas Gregor ///
1628e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise.
1629e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) {
1630e7ab3669SDouglas Gregor   Id.clear();
1631e7ab3669SDouglas Gregor   do {
16323cd34c76SDaniel Jasper     if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1633e7ab3669SDouglas Gregor       Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
1634e7ab3669SDouglas Gregor       consumeToken();
1635e7ab3669SDouglas Gregor     } else {
1636e7ab3669SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1637e7ab3669SDouglas Gregor       return true;
1638e7ab3669SDouglas Gregor     }
1639e7ab3669SDouglas Gregor 
1640e7ab3669SDouglas Gregor     if (!Tok.is(MMToken::Period))
1641e7ab3669SDouglas Gregor       break;
1642e7ab3669SDouglas Gregor 
1643e7ab3669SDouglas Gregor     consumeToken();
1644e7ab3669SDouglas Gregor   } while (true);
1645e7ab3669SDouglas Gregor 
1646e7ab3669SDouglas Gregor   return false;
1647e7ab3669SDouglas Gregor }
1648e7ab3669SDouglas Gregor 
1649a686e1b0SDouglas Gregor namespace {
1650afd1b1c9SEugene Zelenko 
16519fc8faf9SAdrian Prantl   /// Enumerates the known attributes.
1652a686e1b0SDouglas Gregor   enum AttributeKind {
16539fc8faf9SAdrian Prantl     /// An unknown attribute.
1654a686e1b0SDouglas Gregor     AT_unknown,
1655afd1b1c9SEugene Zelenko 
16569fc8faf9SAdrian Prantl     /// The 'system' attribute.
165735b13eceSDouglas Gregor     AT_system,
1658afd1b1c9SEugene Zelenko 
16599fc8faf9SAdrian Prantl     /// The 'extern_c' attribute.
166077944868SRichard Smith     AT_extern_c,
1661afd1b1c9SEugene Zelenko 
16629fc8faf9SAdrian Prantl     /// The 'exhaustive' attribute.
1663ed84df00SBruno Cardoso Lopes     AT_exhaustive,
1664afd1b1c9SEugene Zelenko 
16659fc8faf9SAdrian Prantl     /// The 'no_undeclared_includes' attribute.
1666ed84df00SBruno Cardoso Lopes     AT_no_undeclared_includes
1667a686e1b0SDouglas Gregor   };
1668afd1b1c9SEugene Zelenko 
1669afd1b1c9SEugene Zelenko } // namespace
1670a686e1b0SDouglas Gregor 
167129729919SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra
167229729919SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH
167329729919SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written
167429729919SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
167529729919SBruno Cardoso Lopes static void diagnosePrivateModules(const ModuleMap &Map,
167629729919SBruno Cardoso Lopes                                    DiagnosticsEngine &Diags,
16777d29486dSBruno Cardoso Lopes                                    const Module *ActiveModule,
16787d29486dSBruno Cardoso Lopes                                    SourceLocation InlineParent) {
167929729919SBruno Cardoso Lopes 
168029729919SBruno Cardoso Lopes   auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
16817d29486dSBruno Cardoso Lopes                              const Module *M, SourceRange ReplLoc) {
168229729919SBruno Cardoso Lopes     auto D = Diags.Report(ActiveModule->DefinitionLoc,
168329729919SBruno Cardoso Lopes                           diag::note_mmap_rename_top_level_private_module);
168429729919SBruno Cardoso Lopes     D << BadName << M->Name;
16857d29486dSBruno Cardoso Lopes     D << FixItHint::CreateReplacement(ReplLoc, Canonical);
168629729919SBruno Cardoso Lopes   };
168729729919SBruno Cardoso Lopes 
168829729919SBruno Cardoso Lopes   for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
168929729919SBruno Cardoso Lopes     auto const *M = E->getValue();
169029729919SBruno Cardoso Lopes     if (M->Directory != ActiveModule->Directory)
169129729919SBruno Cardoso Lopes       continue;
169229729919SBruno Cardoso Lopes 
169329729919SBruno Cardoso Lopes     SmallString<128> FullName(ActiveModule->getFullModuleName());
169429729919SBruno Cardoso Lopes     if (!FullName.startswith(M->Name) && !FullName.endswith("Private"))
169529729919SBruno Cardoso Lopes       continue;
169629729919SBruno Cardoso Lopes     SmallString<128> Canonical(M->Name);
169729729919SBruno Cardoso Lopes     Canonical.append("_Private");
169829729919SBruno Cardoso Lopes 
169929729919SBruno Cardoso Lopes     // Foo.Private -> Foo_Private
170029729919SBruno Cardoso Lopes     if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
170129729919SBruno Cardoso Lopes         M->Name == ActiveModule->Parent->Name) {
170229729919SBruno Cardoso Lopes       Diags.Report(ActiveModule->DefinitionLoc,
170329729919SBruno Cardoso Lopes                    diag::warn_mmap_mismatched_private_submodule)
170429729919SBruno Cardoso Lopes           << FullName;
17057d29486dSBruno Cardoso Lopes       GenNoteAndFixIt(FullName, Canonical, M,
17067d29486dSBruno Cardoso Lopes                       SourceRange(InlineParent, ActiveModule->DefinitionLoc));
170729729919SBruno Cardoso Lopes       continue;
170829729919SBruno Cardoso Lopes     }
170929729919SBruno Cardoso Lopes 
171029729919SBruno Cardoso Lopes     // FooPrivate and whatnots -> Foo_Private
171129729919SBruno Cardoso Lopes     if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
171229729919SBruno Cardoso Lopes         ActiveModule->Name != Canonical) {
171329729919SBruno Cardoso Lopes       Diags.Report(ActiveModule->DefinitionLoc,
171429729919SBruno Cardoso Lopes                    diag::warn_mmap_mismatched_private_module_name)
171529729919SBruno Cardoso Lopes           << ActiveModule->Name;
17167d29486dSBruno Cardoso Lopes       GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
17177d29486dSBruno Cardoso Lopes                       SourceRange(ActiveModule->DefinitionLoc));
171829729919SBruno Cardoso Lopes     }
171929729919SBruno Cardoso Lopes   }
172029729919SBruno Cardoso Lopes }
172129729919SBruno Cardoso Lopes 
17229fc8faf9SAdrian Prantl /// Parse a module declaration.
1723718292f2SDouglas Gregor ///
1724718292f2SDouglas Gregor ///   module-declaration:
172597292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
1726a686e1b0SDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1727a686e1b0SDouglas Gregor ///       { module-member* }
1728a686e1b0SDouglas Gregor ///
1729718292f2SDouglas Gregor ///   module-member:
17301fb5c3a6SDouglas Gregor ///     requires-declaration
1731718292f2SDouglas Gregor ///     header-declaration
1732e7ab3669SDouglas Gregor ///     submodule-declaration
17332b82c2a5SDouglas Gregor ///     export-declaration
1734f0b11de2SDouglas Gregor ///     export-as-declaration
17356ddfca91SDouglas Gregor ///     link-declaration
173673441091SDouglas Gregor ///
173773441091SDouglas Gregor ///   submodule-declaration:
173873441091SDouglas Gregor ///     module-declaration
173973441091SDouglas Gregor ///     inferred-submodule-declaration
1740718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
1741755b2055SDouglas Gregor   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
174297292843SDaniel Jasper          Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
174397292843SDaniel Jasper   if (Tok.is(MMToken::ExternKeyword)) {
174497292843SDaniel Jasper     parseExternModuleDecl();
174597292843SDaniel Jasper     return;
174697292843SDaniel Jasper   }
174797292843SDaniel Jasper 
1748f2161a70SDouglas Gregor   // Parse 'explicit' or 'framework' keyword, if present.
1749e7ab3669SDouglas Gregor   SourceLocation ExplicitLoc;
1750718292f2SDouglas Gregor   bool Explicit = false;
1751f2161a70SDouglas Gregor   bool Framework = false;
1752755b2055SDouglas Gregor 
1753f2161a70SDouglas Gregor   // Parse 'explicit' keyword, if present.
1754f2161a70SDouglas Gregor   if (Tok.is(MMToken::ExplicitKeyword)) {
1755e7ab3669SDouglas Gregor     ExplicitLoc = consumeToken();
1756f2161a70SDouglas Gregor     Explicit = true;
1757f2161a70SDouglas Gregor   }
1758f2161a70SDouglas Gregor 
1759f2161a70SDouglas Gregor   // Parse 'framework' keyword, if present.
1760755b2055SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
1761755b2055SDouglas Gregor     consumeToken();
1762755b2055SDouglas Gregor     Framework = true;
1763755b2055SDouglas Gregor   }
1764718292f2SDouglas Gregor 
1765718292f2SDouglas Gregor   // Parse 'module' keyword.
1766718292f2SDouglas Gregor   if (!Tok.is(MMToken::ModuleKeyword)) {
1767d6343c99SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1768718292f2SDouglas Gregor     consumeToken();
1769718292f2SDouglas Gregor     HadError = true;
1770718292f2SDouglas Gregor     return;
1771718292f2SDouglas Gregor   }
17729f6020bcSBruno Cardoso Lopes   CurrModuleDeclLoc = consumeToken(); // 'module' keyword
1773718292f2SDouglas Gregor 
177473441091SDouglas Gregor   // If we have a wildcard for the module name, this is an inferred submodule.
177573441091SDouglas Gregor   // Parse it.
177673441091SDouglas Gregor   if (Tok.is(MMToken::Star))
17779194a91dSDouglas Gregor     return parseInferredModuleDecl(Framework, Explicit);
177873441091SDouglas Gregor 
1779718292f2SDouglas Gregor   // Parse the module name.
1780e7ab3669SDouglas Gregor   ModuleId Id;
1781e7ab3669SDouglas Gregor   if (parseModuleId(Id)) {
1782718292f2SDouglas Gregor     HadError = true;
1783718292f2SDouglas Gregor     return;
1784718292f2SDouglas Gregor   }
1785e7ab3669SDouglas Gregor 
1786e7ab3669SDouglas Gregor   if (ActiveModule) {
1787e7ab3669SDouglas Gregor     if (Id.size() > 1) {
1788e7ab3669SDouglas Gregor       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1789e7ab3669SDouglas Gregor         << SourceRange(Id.front().second, Id.back().second);
1790e7ab3669SDouglas Gregor 
1791e7ab3669SDouglas Gregor       HadError = true;
1792e7ab3669SDouglas Gregor       return;
1793e7ab3669SDouglas Gregor     }
1794e7ab3669SDouglas Gregor   } else if (Id.size() == 1 && Explicit) {
1795e7ab3669SDouglas Gregor     // Top-level modules can't be explicit.
1796e7ab3669SDouglas Gregor     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1797e7ab3669SDouglas Gregor     Explicit = false;
1798e7ab3669SDouglas Gregor     ExplicitLoc = SourceLocation();
1799e7ab3669SDouglas Gregor     HadError = true;
1800e7ab3669SDouglas Gregor   }
1801e7ab3669SDouglas Gregor 
1802e7ab3669SDouglas Gregor   Module *PreviousActiveModule = ActiveModule;
18037d29486dSBruno Cardoso Lopes   SourceLocation LastInlineParentLoc = SourceLocation();
1804e7ab3669SDouglas Gregor   if (Id.size() > 1) {
1805e7ab3669SDouglas Gregor     // This module map defines a submodule. Go find the module of which it
1806e7ab3669SDouglas Gregor     // is a submodule.
1807d2d442caSCraig Topper     ActiveModule = nullptr;
18084b8a9e95SBen Langmuir     const Module *TopLevelModule = nullptr;
1809e7ab3669SDouglas Gregor     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1810e7ab3669SDouglas Gregor       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
18114b8a9e95SBen Langmuir         if (I == 0)
18124b8a9e95SBen Langmuir           TopLevelModule = Next;
1813e7ab3669SDouglas Gregor         ActiveModule = Next;
18147d29486dSBruno Cardoso Lopes         LastInlineParentLoc = Id[I].second;
1815e7ab3669SDouglas Gregor         continue;
1816e7ab3669SDouglas Gregor       }
1817e7ab3669SDouglas Gregor 
1818e7ab3669SDouglas Gregor       if (ActiveModule) {
1819e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
18205b5d21eaSRichard Smith           << Id[I].first
18215b5d21eaSRichard Smith           << ActiveModule->getTopLevelModule()->getFullModuleName();
1822e7ab3669SDouglas Gregor       } else {
1823e7ab3669SDouglas Gregor         Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1824e7ab3669SDouglas Gregor       }
1825e7ab3669SDouglas Gregor       HadError = true;
1826e7ab3669SDouglas Gregor       return;
1827e7ab3669SDouglas Gregor     }
18284b8a9e95SBen Langmuir 
18294b8a9e95SBen Langmuir     if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
18304b8a9e95SBen Langmuir       assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
18314b8a9e95SBen Langmuir              "submodule defined in same file as 'module *' that allowed its "
18324b8a9e95SBen Langmuir              "top-level module");
18334b8a9e95SBen Langmuir       Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
18344b8a9e95SBen Langmuir     }
1835e7ab3669SDouglas Gregor   }
1836e7ab3669SDouglas Gregor 
1837e7ab3669SDouglas Gregor   StringRef ModuleName = Id.back().first;
1838e7ab3669SDouglas Gregor   SourceLocation ModuleNameLoc = Id.back().second;
1839718292f2SDouglas Gregor 
1840a686e1b0SDouglas Gregor   // Parse the optional attribute list.
18414442605fSBill Wendling   Attributes Attrs;
18425d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
18435d29dee0SDavide Italiano     return;
18445d29dee0SDavide Italiano 
1845718292f2SDouglas Gregor   // Parse the opening brace.
1846718292f2SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
1847718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1848718292f2SDouglas Gregor       << ModuleName;
1849718292f2SDouglas Gregor     HadError = true;
1850718292f2SDouglas Gregor     return;
1851718292f2SDouglas Gregor   }
1852718292f2SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
1853718292f2SDouglas Gregor 
1854718292f2SDouglas Gregor   // Determine whether this (sub)module has already been defined.
18558587dfd9SBruno Cardoso Lopes   Module *ShadowingModule = nullptr;
1856eb90e830SDouglas Gregor   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
18574a3751ffSRichard Smith     // We might see a (re)definition of a module that we already have a
18584a3751ffSRichard Smith     // definition for in two cases:
18594a3751ffSRichard Smith     //  - If we loaded one definition from an AST file and we've just found a
18604a3751ffSRichard Smith     //    corresponding definition in a module map file, or
18614a3751ffSRichard Smith     bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
18624a3751ffSRichard Smith     //  - If we're building a (preprocessed) module and we've just loaded the
18634a3751ffSRichard Smith     //    module map file from which it was created.
18644a3751ffSRichard Smith     bool ParsedAsMainInput =
18654a3751ffSRichard Smith         Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
18664a3751ffSRichard Smith         Map.LangOpts.CurrentModule == ModuleName &&
18674a3751ffSRichard Smith         SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
18684a3751ffSRichard Smith             SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
18694a3751ffSRichard Smith     if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
1870fcc54a3bSDouglas Gregor       // Skip the module definition.
1871fcc54a3bSDouglas Gregor       skipUntil(MMToken::RBrace);
1872fcc54a3bSDouglas Gregor       if (Tok.is(MMToken::RBrace))
1873fcc54a3bSDouglas Gregor         consumeToken();
1874fcc54a3bSDouglas Gregor       else {
1875fcc54a3bSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1876fcc54a3bSDouglas Gregor         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1877fcc54a3bSDouglas Gregor         HadError = true;
1878fcc54a3bSDouglas Gregor       }
1879fcc54a3bSDouglas Gregor       return;
1880fcc54a3bSDouglas Gregor     }
1881fcc54a3bSDouglas Gregor 
1882c192d194SBruno Cardoso Lopes     if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
18838587dfd9SBruno Cardoso Lopes       ShadowingModule = Existing;
18848587dfd9SBruno Cardoso Lopes     } else {
18858587dfd9SBruno Cardoso Lopes       // This is not a shawdowed module decl, it is an illegal redefinition.
1886718292f2SDouglas Gregor       Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1887718292f2SDouglas Gregor           << ModuleName;
1888eb90e830SDouglas Gregor       Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1889718292f2SDouglas Gregor 
1890718292f2SDouglas Gregor       // Skip the module definition.
1891718292f2SDouglas Gregor       skipUntil(MMToken::RBrace);
1892718292f2SDouglas Gregor       if (Tok.is(MMToken::RBrace))
1893718292f2SDouglas Gregor         consumeToken();
1894718292f2SDouglas Gregor 
1895718292f2SDouglas Gregor       HadError = true;
1896718292f2SDouglas Gregor       return;
1897718292f2SDouglas Gregor     }
18988587dfd9SBruno Cardoso Lopes   }
1899718292f2SDouglas Gregor 
1900718292f2SDouglas Gregor   // Start defining this module.
19018587dfd9SBruno Cardoso Lopes   if (ShadowingModule) {
19028587dfd9SBruno Cardoso Lopes     ActiveModule =
19038587dfd9SBruno Cardoso Lopes         Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
19048587dfd9SBruno Cardoso Lopes   } else {
1905c192d194SBruno Cardoso Lopes     ActiveModule =
1906c192d194SBruno Cardoso Lopes         Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
19078587dfd9SBruno Cardoso Lopes             .first;
19088587dfd9SBruno Cardoso Lopes   }
19098587dfd9SBruno Cardoso Lopes 
1910eb90e830SDouglas Gregor   ActiveModule->DefinitionLoc = ModuleNameLoc;
1911963c5535SDouglas Gregor   if (Attrs.IsSystem || IsSystem)
1912a686e1b0SDouglas Gregor     ActiveModule->IsSystem = true;
191377944868SRichard Smith   if (Attrs.IsExternC)
191477944868SRichard Smith     ActiveModule->IsExternC = true;
1915ed84df00SBruno Cardoso Lopes   if (Attrs.NoUndeclaredIncludes ||
1916ed84df00SBruno Cardoso Lopes       (!ActiveModule->Parent && ModuleName == "Darwin"))
1917ed84df00SBruno Cardoso Lopes     ActiveModule->NoUndeclaredIncludes = true;
19183c1a41adSRichard Smith   ActiveModule->Directory = Directory;
1919718292f2SDouglas Gregor 
192090b0a1fcSJordan Rose   StringRef MapFileName(ModuleMapFile->getName());
192190b0a1fcSJordan Rose   if (MapFileName.endswith("module.private.modulemap") ||
192290b0a1fcSJordan Rose       MapFileName.endswith("module_private.map")) {
192390b0a1fcSJordan Rose     ActiveModule->ModuleMapIsPrivate = true;
192490b0a1fcSJordan Rose   }
192529729919SBruno Cardoso Lopes 
192629729919SBruno Cardoso Lopes   // Private modules named as FooPrivate, Foo.Private or similar are likely a
192729729919SBruno Cardoso Lopes   // user error; provide warnings, notes and fixits to direct users to use
192829729919SBruno Cardoso Lopes   // Foo_Private instead.
192929729919SBruno Cardoso Lopes   SourceLocation StartLoc =
193029729919SBruno Cardoso Lopes       SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
193129729919SBruno Cardoso Lopes   if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
193229729919SBruno Cardoso Lopes       !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
193329729919SBruno Cardoso Lopes                        StartLoc) &&
193429729919SBruno Cardoso Lopes       !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
193529729919SBruno Cardoso Lopes                        StartLoc) &&
193690b0a1fcSJordan Rose       ActiveModule->ModuleMapIsPrivate)
19377d29486dSBruno Cardoso Lopes     diagnosePrivateModules(Map, Diags, ActiveModule, LastInlineParentLoc);
19384d867640SGraydon Hoare 
1939718292f2SDouglas Gregor   bool Done = false;
1940718292f2SDouglas Gregor   do {
1941718292f2SDouglas Gregor     switch (Tok.Kind) {
1942718292f2SDouglas Gregor     case MMToken::EndOfFile:
1943718292f2SDouglas Gregor     case MMToken::RBrace:
1944718292f2SDouglas Gregor       Done = true;
1945718292f2SDouglas Gregor       break;
1946718292f2SDouglas Gregor 
194735b13eceSDouglas Gregor     case MMToken::ConfigMacros:
194835b13eceSDouglas Gregor       parseConfigMacros();
194935b13eceSDouglas Gregor       break;
195035b13eceSDouglas Gregor 
1951fb912657SDouglas Gregor     case MMToken::Conflict:
1952fb912657SDouglas Gregor       parseConflict();
1953fb912657SDouglas Gregor       break;
1954fb912657SDouglas Gregor 
1955718292f2SDouglas Gregor     case MMToken::ExplicitKeyword:
195697292843SDaniel Jasper     case MMToken::ExternKeyword:
1957f2161a70SDouglas Gregor     case MMToken::FrameworkKeyword:
1958718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
1959718292f2SDouglas Gregor       parseModuleDecl();
1960718292f2SDouglas Gregor       break;
1961718292f2SDouglas Gregor 
19622b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
19632b82c2a5SDouglas Gregor       parseExportDecl();
19642b82c2a5SDouglas Gregor       break;
19652b82c2a5SDouglas Gregor 
1966f0b11de2SDouglas Gregor     case MMToken::ExportAsKeyword:
1967f0b11de2SDouglas Gregor       parseExportAsDecl();
1968f0b11de2SDouglas Gregor       break;
1969f0b11de2SDouglas Gregor 
1970ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
1971ba7f2f71SDaniel Jasper       parseUseDecl();
1972ba7f2f71SDaniel Jasper       break;
1973ba7f2f71SDaniel Jasper 
19741fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
19751fb5c3a6SDouglas Gregor       parseRequiresDecl();
19761fb5c3a6SDouglas Gregor       break;
19771fb5c3a6SDouglas Gregor 
1978202210b3SRichard Smith     case MMToken::TextualKeyword:
1979202210b3SRichard Smith       parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
1980306d8920SRichard Smith       break;
1981306d8920SRichard Smith 
1982524e33e1SDouglas Gregor     case MMToken::UmbrellaKeyword: {
1983524e33e1SDouglas Gregor       SourceLocation UmbrellaLoc = consumeToken();
1984524e33e1SDouglas Gregor       if (Tok.is(MMToken::HeaderKeyword))
1985b53e5483SLawrence Crowl         parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
1986524e33e1SDouglas Gregor       else
1987524e33e1SDouglas Gregor         parseUmbrellaDirDecl(UmbrellaLoc);
1988718292f2SDouglas Gregor       break;
1989524e33e1SDouglas Gregor     }
1990718292f2SDouglas Gregor 
1991202210b3SRichard Smith     case MMToken::ExcludeKeyword:
1992202210b3SRichard Smith       parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
199359527666SDouglas Gregor       break;
199459527666SDouglas Gregor 
1995202210b3SRichard Smith     case MMToken::PrivateKeyword:
1996202210b3SRichard Smith       parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
1997b53e5483SLawrence Crowl       break;
1998b53e5483SLawrence Crowl 
1999322f633cSDouglas Gregor     case MMToken::HeaderKeyword:
2000202210b3SRichard Smith       parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
2001718292f2SDouglas Gregor       break;
2002718292f2SDouglas Gregor 
20036ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
20046ddfca91SDouglas Gregor       parseLinkDecl();
20056ddfca91SDouglas Gregor       break;
20066ddfca91SDouglas Gregor 
2007718292f2SDouglas Gregor     default:
2008718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
2009718292f2SDouglas Gregor       consumeToken();
2010718292f2SDouglas Gregor       break;
2011718292f2SDouglas Gregor     }
2012718292f2SDouglas Gregor   } while (!Done);
2013718292f2SDouglas Gregor 
2014718292f2SDouglas Gregor   if (Tok.is(MMToken::RBrace))
2015718292f2SDouglas Gregor     consumeToken();
2016718292f2SDouglas Gregor   else {
2017718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2018718292f2SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2019718292f2SDouglas Gregor     HadError = true;
2020718292f2SDouglas Gregor   }
2021718292f2SDouglas Gregor 
202211dfe6feSDouglas Gregor   // If the active module is a top-level framework, and there are no link
202311dfe6feSDouglas Gregor   // libraries, automatically link against the framework.
202411dfe6feSDouglas Gregor   if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
202511dfe6feSDouglas Gregor       ActiveModule->LinkLibraries.empty()) {
202611dfe6feSDouglas Gregor     inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
202711dfe6feSDouglas Gregor   }
202811dfe6feSDouglas Gregor 
2029ec8c9752SBen Langmuir   // If the module meets all requirements but is still unavailable, mark the
2030ec8c9752SBen Langmuir   // whole tree as unavailable to prevent it from building.
2031ec8c9752SBen Langmuir   if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement &&
2032ec8c9752SBen Langmuir       ActiveModule->Parent) {
2033ec8c9752SBen Langmuir     ActiveModule->getTopLevelModule()->markUnavailable();
2034ec8c9752SBen Langmuir     ActiveModule->getTopLevelModule()->MissingHeaders.append(
2035ec8c9752SBen Langmuir       ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
2036ec8c9752SBen Langmuir   }
2037ec8c9752SBen Langmuir 
2038e7ab3669SDouglas Gregor   // We're done parsing this module. Pop back to the previous module.
2039e7ab3669SDouglas Gregor   ActiveModule = PreviousActiveModule;
2040718292f2SDouglas Gregor }
2041718292f2SDouglas Gregor 
20429fc8faf9SAdrian Prantl /// Parse an extern module declaration.
204397292843SDaniel Jasper ///
204497292843SDaniel Jasper ///   extern module-declaration:
204597292843SDaniel Jasper ///     'extern' 'module' module-id string-literal
204697292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() {
204797292843SDaniel Jasper   assert(Tok.is(MMToken::ExternKeyword));
2048ae6df27eSRichard Smith   SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
204997292843SDaniel Jasper 
205097292843SDaniel Jasper   // Parse 'module' keyword.
205197292843SDaniel Jasper   if (!Tok.is(MMToken::ModuleKeyword)) {
205297292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
205397292843SDaniel Jasper     consumeToken();
205497292843SDaniel Jasper     HadError = true;
205597292843SDaniel Jasper     return;
205697292843SDaniel Jasper   }
205797292843SDaniel Jasper   consumeToken(); // 'module' keyword
205897292843SDaniel Jasper 
205997292843SDaniel Jasper   // Parse the module name.
206097292843SDaniel Jasper   ModuleId Id;
206197292843SDaniel Jasper   if (parseModuleId(Id)) {
206297292843SDaniel Jasper     HadError = true;
206397292843SDaniel Jasper     return;
206497292843SDaniel Jasper   }
206597292843SDaniel Jasper 
206697292843SDaniel Jasper   // Parse the referenced module map file name.
206797292843SDaniel Jasper   if (!Tok.is(MMToken::StringLiteral)) {
206897292843SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
206997292843SDaniel Jasper     HadError = true;
207097292843SDaniel Jasper     return;
207197292843SDaniel Jasper   }
207297292843SDaniel Jasper   std::string FileName = Tok.getString();
207397292843SDaniel Jasper   consumeToken(); // filename
207497292843SDaniel Jasper 
207597292843SDaniel Jasper   StringRef FileNameRef = FileName;
207697292843SDaniel Jasper   SmallString<128> ModuleMapFileName;
207797292843SDaniel Jasper   if (llvm::sys::path::is_relative(FileNameRef)) {
207897292843SDaniel Jasper     ModuleMapFileName += Directory->getName();
207997292843SDaniel Jasper     llvm::sys::path::append(ModuleMapFileName, FileName);
208092e1b62dSYaron Keren     FileNameRef = ModuleMapFileName;
208197292843SDaniel Jasper   }
208297292843SDaniel Jasper   if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef))
20839acb99e3SRichard Smith     Map.parseModuleMapFile(
20849acb99e3SRichard Smith         File, /*IsSystem=*/false,
20859acb99e3SRichard Smith         Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
20869acb99e3SRichard Smith             ? Directory
20878128f332SRichard Smith             : File->getDir(),
2088c192d194SBruno Cardoso Lopes         FileID(), nullptr, ExternLoc);
208997292843SDaniel Jasper }
209097292843SDaniel Jasper 
20917ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M.
20927ff29148SBen Langmuir ///
20937ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system
20947ff29148SBen Langmuir /// module map files:
20957ff29148SBen Langmuir ///
20967ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which
20977ff29148SBen Langmuir ///    should really be mapped to 'textual' now that we have this feature.  We
20987ff29148SBen Langmuir ///    drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
20997ff29148SBen Langmuir ///    true.  Later, this bit will be used to map all the headers inside this
21007ff29148SBen Langmuir ///    module to 'textual'.
21017ff29148SBen Langmuir ///
21027ff29148SBen Langmuir ///    This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
21037ff29148SBen Langmuir ///
21047ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc.  This requirement
21057ff29148SBen Langmuir ///    was never correct and causes issues now that we check it, so drop it.
21067ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature,
21077ff29148SBen Langmuir                                  bool &IsRequiresExcludedHack) {
21088013e81dSBenjamin Kramer   if (Feature == "excluded" &&
21098013e81dSBenjamin Kramer       (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
21108013e81dSBenjamin Kramer        M->fullModuleNameIs({"Tcl", "Private"}))) {
21117ff29148SBen Langmuir     IsRequiresExcludedHack = true;
21127ff29148SBen Langmuir     return false;
21138013e81dSBenjamin Kramer   } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
21147ff29148SBen Langmuir     return false;
21157ff29148SBen Langmuir   }
21167ff29148SBen Langmuir 
21177ff29148SBen Langmuir   return true;
21187ff29148SBen Langmuir }
21197ff29148SBen Langmuir 
21209fc8faf9SAdrian Prantl /// Parse a requires declaration.
21211fb5c3a6SDouglas Gregor ///
21221fb5c3a6SDouglas Gregor ///   requires-declaration:
21231fb5c3a6SDouglas Gregor ///     'requires' feature-list
21241fb5c3a6SDouglas Gregor ///
21251fb5c3a6SDouglas Gregor ///   feature-list:
2126a3feee2aSRichard Smith ///     feature ',' feature-list
2127a3feee2aSRichard Smith ///     feature
2128a3feee2aSRichard Smith ///
2129a3feee2aSRichard Smith ///   feature:
2130a3feee2aSRichard Smith ///     '!'[opt] identifier
21311fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() {
21321fb5c3a6SDouglas Gregor   assert(Tok.is(MMToken::RequiresKeyword));
21331fb5c3a6SDouglas Gregor 
21341fb5c3a6SDouglas Gregor   // Parse 'requires' keyword.
21351fb5c3a6SDouglas Gregor   consumeToken();
21361fb5c3a6SDouglas Gregor 
21371fb5c3a6SDouglas Gregor   // Parse the feature-list.
21381fb5c3a6SDouglas Gregor   do {
2139a3feee2aSRichard Smith     bool RequiredState = true;
2140a3feee2aSRichard Smith     if (Tok.is(MMToken::Exclaim)) {
2141a3feee2aSRichard Smith       RequiredState = false;
2142a3feee2aSRichard Smith       consumeToken();
2143a3feee2aSRichard Smith     }
2144a3feee2aSRichard Smith 
21451fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
21461fb5c3a6SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
21471fb5c3a6SDouglas Gregor       HadError = true;
21481fb5c3a6SDouglas Gregor       return;
21491fb5c3a6SDouglas Gregor     }
21501fb5c3a6SDouglas Gregor 
21511fb5c3a6SDouglas Gregor     // Consume the feature name.
21521fb5c3a6SDouglas Gregor     std::string Feature = Tok.getString();
21531fb5c3a6SDouglas Gregor     consumeToken();
21541fb5c3a6SDouglas Gregor 
21557ff29148SBen Langmuir     bool IsRequiresExcludedHack = false;
21567ff29148SBen Langmuir     bool ShouldAddRequirement =
21577ff29148SBen Langmuir         shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
21587ff29148SBen Langmuir 
21597ff29148SBen Langmuir     if (IsRequiresExcludedHack)
21607ff29148SBen Langmuir       UsesRequiresExcludedHack.insert(ActiveModule);
21617ff29148SBen Langmuir 
21627ff29148SBen Langmuir     if (ShouldAddRequirement) {
21631fb5c3a6SDouglas Gregor       // Add this feature.
21647ff29148SBen Langmuir       ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
21657ff29148SBen Langmuir                                    *Map.Target);
21667ff29148SBen Langmuir     }
21671fb5c3a6SDouglas Gregor 
21681fb5c3a6SDouglas Gregor     if (!Tok.is(MMToken::Comma))
21691fb5c3a6SDouglas Gregor       break;
21701fb5c3a6SDouglas Gregor 
21711fb5c3a6SDouglas Gregor     // Consume the comma.
21721fb5c3a6SDouglas Gregor     consumeToken();
21731fb5c3a6SDouglas Gregor   } while (true);
21741fb5c3a6SDouglas Gregor }
21751fb5c3a6SDouglas Gregor 
21769fc8faf9SAdrian Prantl /// Parse a header declaration.
2177718292f2SDouglas Gregor ///
2178718292f2SDouglas Gregor ///   header-declaration:
2179306d8920SRichard Smith ///     'textual'[opt] 'header' string-literal
2180202210b3SRichard Smith ///     'private' 'textual'[opt] 'header' string-literal
2181202210b3SRichard Smith ///     'exclude' 'header' string-literal
2182202210b3SRichard Smith ///     'umbrella' 'header' string-literal
2183306d8920SRichard Smith ///
2184306d8920SRichard Smith /// FIXME: Support 'private textual header'.
2185b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
2186b53e5483SLawrence Crowl                                       SourceLocation LeadingLoc) {
2187202210b3SRichard Smith   // We've already consumed the first token.
2188202210b3SRichard Smith   ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
2189202210b3SRichard Smith   if (LeadingToken == MMToken::PrivateKeyword) {
2190202210b3SRichard Smith     Role = ModuleMap::PrivateHeader;
2191202210b3SRichard Smith     // 'private' may optionally be followed by 'textual'.
2192202210b3SRichard Smith     if (Tok.is(MMToken::TextualKeyword)) {
2193202210b3SRichard Smith       LeadingToken = Tok.Kind;
21941871ed3dSBenjamin Kramer       consumeToken();
2195202210b3SRichard Smith     }
2196202210b3SRichard Smith   }
21977ff29148SBen Langmuir 
2198202210b3SRichard Smith   if (LeadingToken == MMToken::TextualKeyword)
2199202210b3SRichard Smith     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
2200202210b3SRichard Smith 
22017ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
22027ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
22037ff29148SBen Langmuir     // Module::UsesRequiresExcludedHack).
22047ff29148SBen Langmuir     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
22057ff29148SBen Langmuir   }
22067ff29148SBen Langmuir 
2207202210b3SRichard Smith   if (LeadingToken != MMToken::HeaderKeyword) {
2208202210b3SRichard Smith     if (!Tok.is(MMToken::HeaderKeyword)) {
2209202210b3SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2210202210b3SRichard Smith           << (LeadingToken == MMToken::PrivateKeyword ? "private" :
2211202210b3SRichard Smith               LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
2212202210b3SRichard Smith               LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
2213202210b3SRichard Smith       return;
2214202210b3SRichard Smith     }
2215202210b3SRichard Smith     consumeToken();
2216202210b3SRichard Smith   }
2217718292f2SDouglas Gregor 
2218718292f2SDouglas Gregor   // Parse the header name.
2219718292f2SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2220718292f2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2221718292f2SDouglas Gregor       << "header";
2222718292f2SDouglas Gregor     HadError = true;
2223718292f2SDouglas Gregor     return;
2224718292f2SDouglas Gregor   }
22253c1a41adSRichard Smith   Module::UnresolvedHeaderDirective Header;
22260761a8a0SDaniel Jasper   Header.FileName = Tok.getString();
22270761a8a0SDaniel Jasper   Header.FileNameLoc = consumeToken();
22281d60987fSRichard Smith   Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
2229040e1266SRichard Smith   Header.Kind =
2230040e1266SRichard Smith       (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded
2231040e1266SRichard Smith                                                : Map.headerRoleToKind(Role));
2232718292f2SDouglas Gregor 
2233524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
22341d60987fSRichard Smith   if (Header.IsUmbrella && ActiveModule->Umbrella) {
22350761a8a0SDaniel Jasper     Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2236524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2237322f633cSDouglas Gregor     HadError = true;
2238322f633cSDouglas Gregor     return;
2239322f633cSDouglas Gregor   }
2240322f633cSDouglas Gregor 
2241040e1266SRichard Smith   // If we were given stat information, parse it so we can skip looking for
2242040e1266SRichard Smith   // the file.
2243040e1266SRichard Smith   if (Tok.is(MMToken::LBrace)) {
2244040e1266SRichard Smith     SourceLocation LBraceLoc = consumeToken();
22453ec6663bSDouglas Gregor 
2246040e1266SRichard Smith     while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
2247040e1266SRichard Smith       enum Attribute { Size, ModTime, Unknown };
2248040e1266SRichard Smith       StringRef Str = Tok.getString();
2249040e1266SRichard Smith       SourceLocation Loc = consumeToken();
2250040e1266SRichard Smith       switch (llvm::StringSwitch<Attribute>(Str)
2251040e1266SRichard Smith                   .Case("size", Size)
2252040e1266SRichard Smith                   .Case("mtime", ModTime)
2253040e1266SRichard Smith                   .Default(Unknown)) {
2254040e1266SRichard Smith       case Size:
2255040e1266SRichard Smith         if (Header.Size)
2256040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2257040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2258040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2259040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2260040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2261040e1266SRichard Smith           break;
2262040e1266SRichard Smith         }
2263040e1266SRichard Smith         Header.Size = Tok.getInteger();
2264040e1266SRichard Smith         consumeToken();
2265040e1266SRichard Smith         break;
2266040e1266SRichard Smith 
2267040e1266SRichard Smith       case ModTime:
2268040e1266SRichard Smith         if (Header.ModTime)
2269040e1266SRichard Smith           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2270040e1266SRichard Smith         if (!Tok.is(MMToken::IntegerLiteral)) {
2271040e1266SRichard Smith           Diags.Report(Tok.getLocation(),
2272040e1266SRichard Smith                        diag::err_mmap_invalid_header_attribute_value) << Str;
2273040e1266SRichard Smith           skipUntil(MMToken::RBrace);
2274040e1266SRichard Smith           break;
2275040e1266SRichard Smith         }
2276040e1266SRichard Smith         Header.ModTime = Tok.getInteger();
2277040e1266SRichard Smith         consumeToken();
2278040e1266SRichard Smith         break;
2279040e1266SRichard Smith 
2280040e1266SRichard Smith       case Unknown:
2281040e1266SRichard Smith         Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
2282040e1266SRichard Smith         skipUntil(MMToken::RBrace);
2283040e1266SRichard Smith         break;
2284040e1266SRichard Smith       }
22853ec6663bSDouglas Gregor     }
22865257fc63SDouglas Gregor 
2287040e1266SRichard Smith     if (Tok.is(MMToken::RBrace))
2288040e1266SRichard Smith       consumeToken();
2289040e1266SRichard Smith     else {
2290040e1266SRichard Smith       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2291040e1266SRichard Smith       Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2292322f633cSDouglas Gregor       HadError = true;
2293322f633cSDouglas Gregor     }
22940101b540SHans Wennborg   }
229525d50758SRichard Smith 
22969f6020bcSBruno Cardoso Lopes   bool NeedsFramework = false;
22979f6020bcSBruno Cardoso Lopes   Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
22989f6020bcSBruno Cardoso Lopes 
22999f6020bcSBruno Cardoso Lopes   if (NeedsFramework && ActiveModule)
23009f6020bcSBruno Cardoso Lopes     Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
23019f6020bcSBruno Cardoso Lopes       << ActiveModule->getFullModuleName()
23029f6020bcSBruno Cardoso Lopes       << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
2303718292f2SDouglas Gregor }
2304718292f2SDouglas Gregor 
230541f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A,
230641f81994SBen Langmuir                                 const Module::Header *B) {
230741f81994SBen Langmuir   return A->NameAsWritten.compare(B->NameAsWritten);
230841f81994SBen Langmuir }
230941f81994SBen Langmuir 
23109fc8faf9SAdrian Prantl /// Parse an umbrella directory declaration.
2311524e33e1SDouglas Gregor ///
2312524e33e1SDouglas Gregor ///   umbrella-dir-declaration:
2313524e33e1SDouglas Gregor ///     umbrella string-literal
2314524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
2315524e33e1SDouglas Gregor   // Parse the directory name.
2316524e33e1SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2317524e33e1SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2318524e33e1SDouglas Gregor       << "umbrella";
2319524e33e1SDouglas Gregor     HadError = true;
2320524e33e1SDouglas Gregor     return;
2321524e33e1SDouglas Gregor   }
2322524e33e1SDouglas Gregor 
2323524e33e1SDouglas Gregor   std::string DirName = Tok.getString();
2324524e33e1SDouglas Gregor   SourceLocation DirNameLoc = consumeToken();
2325524e33e1SDouglas Gregor 
2326524e33e1SDouglas Gregor   // Check whether we already have an umbrella.
2327524e33e1SDouglas Gregor   if (ActiveModule->Umbrella) {
2328524e33e1SDouglas Gregor     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
2329524e33e1SDouglas Gregor       << ActiveModule->getFullModuleName();
2330524e33e1SDouglas Gregor     HadError = true;
2331524e33e1SDouglas Gregor     return;
2332524e33e1SDouglas Gregor   }
2333524e33e1SDouglas Gregor 
2334524e33e1SDouglas Gregor   // Look for this file.
2335d2d442caSCraig Topper   const DirectoryEntry *Dir = nullptr;
2336524e33e1SDouglas Gregor   if (llvm::sys::path::is_absolute(DirName))
2337524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(DirName);
2338524e33e1SDouglas Gregor   else {
23392c1dd271SDylan Noblesmith     SmallString<128> PathName;
2340524e33e1SDouglas Gregor     PathName = Directory->getName();
2341524e33e1SDouglas Gregor     llvm::sys::path::append(PathName, DirName);
2342524e33e1SDouglas Gregor     Dir = SourceMgr.getFileManager().getDirectory(PathName);
2343524e33e1SDouglas Gregor   }
2344524e33e1SDouglas Gregor 
2345524e33e1SDouglas Gregor   if (!Dir) {
2346a0320b97SVassil Vassilev     Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
2347524e33e1SDouglas Gregor       << DirName;
2348524e33e1SDouglas Gregor     return;
2349524e33e1SDouglas Gregor   }
2350524e33e1SDouglas Gregor 
23517ff29148SBen Langmuir   if (UsesRequiresExcludedHack.count(ActiveModule)) {
23527ff29148SBen Langmuir     // Mark this header 'textual' (see doc comment for
23537ff29148SBen Langmuir     // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
23547ff29148SBen Langmuir     // directory is relatively expensive, in practice this only applies to the
23557ff29148SBen Langmuir     // uncommonly used Tcl module on Darwin platforms.
23567ff29148SBen Langmuir     std::error_code EC;
23577ff29148SBen Langmuir     SmallVector<Module::Header, 6> Headers;
2358b171a59bSBruno Cardoso Lopes     vfs::FileSystem &FS = *SourceMgr.getFileManager().getVirtualFileSystem();
2359b171a59bSBruno Cardoso Lopes     for (vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
23607ff29148SBen Langmuir          I != E && !EC; I.increment(EC)) {
2361b171a59bSBruno Cardoso Lopes       if (const FileEntry *FE =
2362b171a59bSBruno Cardoso Lopes               SourceMgr.getFileManager().getFile(I->getName())) {
23637ff29148SBen Langmuir 
2364b171a59bSBruno Cardoso Lopes         Module::Header Header = {I->getName(), FE};
23657ff29148SBen Langmuir         Headers.push_back(std::move(Header));
23667ff29148SBen Langmuir       }
23677ff29148SBen Langmuir     }
23687ff29148SBen Langmuir 
23697ff29148SBen Langmuir     // Sort header paths so that the pcm doesn't depend on iteration order.
237041f81994SBen Langmuir     llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
237141f81994SBen Langmuir 
23727ff29148SBen Langmuir     for (auto &Header : Headers)
23737ff29148SBen Langmuir       Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
23747ff29148SBen Langmuir     return;
23757ff29148SBen Langmuir   }
23767ff29148SBen Langmuir 
2377524e33e1SDouglas Gregor   if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
2378524e33e1SDouglas Gregor     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
2379524e33e1SDouglas Gregor       << OwningModule->getFullModuleName();
2380524e33e1SDouglas Gregor     HadError = true;
2381524e33e1SDouglas Gregor     return;
2382524e33e1SDouglas Gregor   }
2383524e33e1SDouglas Gregor 
2384524e33e1SDouglas Gregor   // Record this umbrella directory.
23852b63d15fSRichard Smith   Map.setUmbrellaDir(ActiveModule, Dir, DirName);
2386524e33e1SDouglas Gregor }
2387524e33e1SDouglas Gregor 
23889fc8faf9SAdrian Prantl /// Parse a module export declaration.
23892b82c2a5SDouglas Gregor ///
23902b82c2a5SDouglas Gregor ///   export-declaration:
23912b82c2a5SDouglas Gregor ///     'export' wildcard-module-id
23922b82c2a5SDouglas Gregor ///
23932b82c2a5SDouglas Gregor ///   wildcard-module-id:
23942b82c2a5SDouglas Gregor ///     identifier
23952b82c2a5SDouglas Gregor ///     '*'
23962b82c2a5SDouglas Gregor ///     identifier '.' wildcard-module-id
23972b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() {
23982b82c2a5SDouglas Gregor   assert(Tok.is(MMToken::ExportKeyword));
23992b82c2a5SDouglas Gregor   SourceLocation ExportLoc = consumeToken();
24002b82c2a5SDouglas Gregor 
24012b82c2a5SDouglas Gregor   // Parse the module-id with an optional wildcard at the end.
24022b82c2a5SDouglas Gregor   ModuleId ParsedModuleId;
24032b82c2a5SDouglas Gregor   bool Wildcard = false;
24042b82c2a5SDouglas Gregor   do {
2405306d8920SRichard Smith     // FIXME: Support string-literal module names here.
24062b82c2a5SDouglas Gregor     if (Tok.is(MMToken::Identifier)) {
24072b82c2a5SDouglas Gregor       ParsedModuleId.push_back(std::make_pair(Tok.getString(),
24082b82c2a5SDouglas Gregor                                               Tok.getLocation()));
24092b82c2a5SDouglas Gregor       consumeToken();
24102b82c2a5SDouglas Gregor 
24112b82c2a5SDouglas Gregor       if (Tok.is(MMToken::Period)) {
24122b82c2a5SDouglas Gregor         consumeToken();
24132b82c2a5SDouglas Gregor         continue;
24142b82c2a5SDouglas Gregor       }
24152b82c2a5SDouglas Gregor 
24162b82c2a5SDouglas Gregor       break;
24172b82c2a5SDouglas Gregor     }
24182b82c2a5SDouglas Gregor 
24192b82c2a5SDouglas Gregor     if(Tok.is(MMToken::Star)) {
24202b82c2a5SDouglas Gregor       Wildcard = true;
2421f5eedd05SDouglas Gregor       consumeToken();
24222b82c2a5SDouglas Gregor       break;
24232b82c2a5SDouglas Gregor     }
24242b82c2a5SDouglas Gregor 
2425ba7f2f71SDaniel Jasper     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
24262b82c2a5SDouglas Gregor     HadError = true;
24272b82c2a5SDouglas Gregor     return;
24282b82c2a5SDouglas Gregor   } while (true);
24292b82c2a5SDouglas Gregor 
24302b82c2a5SDouglas Gregor   Module::UnresolvedExportDecl Unresolved = {
24312b82c2a5SDouglas Gregor     ExportLoc, ParsedModuleId, Wildcard
24322b82c2a5SDouglas Gregor   };
24332b82c2a5SDouglas Gregor   ActiveModule->UnresolvedExports.push_back(Unresolved);
24342b82c2a5SDouglas Gregor }
24352b82c2a5SDouglas Gregor 
24369fc8faf9SAdrian Prantl /// Parse a module export_as declaration.
2437f0b11de2SDouglas Gregor ///
2438f0b11de2SDouglas Gregor ///   export-as-declaration:
2439f0b11de2SDouglas Gregor ///     'export_as' identifier
2440f0b11de2SDouglas Gregor void ModuleMapParser::parseExportAsDecl() {
2441f0b11de2SDouglas Gregor   assert(Tok.is(MMToken::ExportAsKeyword));
2442f0b11de2SDouglas Gregor   consumeToken();
2443f0b11de2SDouglas Gregor 
2444f0b11de2SDouglas Gregor   if (!Tok.is(MMToken::Identifier)) {
2445f0b11de2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
2446f0b11de2SDouglas Gregor     HadError = true;
2447f0b11de2SDouglas Gregor     return;
2448f0b11de2SDouglas Gregor   }
2449f0b11de2SDouglas Gregor 
2450f0b11de2SDouglas Gregor   if (ActiveModule->Parent) {
2451f0b11de2SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
2452f0b11de2SDouglas Gregor     consumeToken();
2453f0b11de2SDouglas Gregor     return;
2454f0b11de2SDouglas Gregor   }
2455f0b11de2SDouglas Gregor 
2456f0b11de2SDouglas Gregor   if (!ActiveModule->ExportAsModule.empty()) {
2457f0b11de2SDouglas Gregor     if (ActiveModule->ExportAsModule == Tok.getString()) {
2458f0b11de2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
2459f0b11de2SDouglas Gregor         << ActiveModule->Name << Tok.getString();
2460f0b11de2SDouglas Gregor     } else {
2461f0b11de2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
2462f0b11de2SDouglas Gregor         << ActiveModule->Name << ActiveModule->ExportAsModule
2463f0b11de2SDouglas Gregor         << Tok.getString();
2464f0b11de2SDouglas Gregor     }
2465f0b11de2SDouglas Gregor   }
2466f0b11de2SDouglas Gregor 
2467f0b11de2SDouglas Gregor   ActiveModule->ExportAsModule = Tok.getString();
2468a3b5f71eSBruno Cardoso Lopes   Map.addLinkAsDependency(ActiveModule);
2469a3b5f71eSBruno Cardoso Lopes 
2470f0b11de2SDouglas Gregor   consumeToken();
2471f0b11de2SDouglas Gregor }
2472f0b11de2SDouglas Gregor 
24739fc8faf9SAdrian Prantl /// Parse a module use declaration.
2474ba7f2f71SDaniel Jasper ///
24758f4d3ff1SRichard Smith ///   use-declaration:
24768f4d3ff1SRichard Smith ///     'use' wildcard-module-id
2477ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() {
2478ba7f2f71SDaniel Jasper   assert(Tok.is(MMToken::UseKeyword));
24798f4d3ff1SRichard Smith   auto KWLoc = consumeToken();
2480ba7f2f71SDaniel Jasper   // Parse the module-id.
2481ba7f2f71SDaniel Jasper   ModuleId ParsedModuleId;
24823cd34c76SDaniel Jasper   parseModuleId(ParsedModuleId);
2483ba7f2f71SDaniel Jasper 
24848f4d3ff1SRichard Smith   if (ActiveModule->Parent)
24858f4d3ff1SRichard Smith     Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
24868f4d3ff1SRichard Smith   else
2487ba7f2f71SDaniel Jasper     ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
2488ba7f2f71SDaniel Jasper }
2489ba7f2f71SDaniel Jasper 
24909fc8faf9SAdrian Prantl /// Parse a link declaration.
24916ddfca91SDouglas Gregor ///
24926ddfca91SDouglas Gregor ///   module-declaration:
24936ddfca91SDouglas Gregor ///     'link' 'framework'[opt] string-literal
24946ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() {
24956ddfca91SDouglas Gregor   assert(Tok.is(MMToken::LinkKeyword));
24966ddfca91SDouglas Gregor   SourceLocation LinkLoc = consumeToken();
24976ddfca91SDouglas Gregor 
24986ddfca91SDouglas Gregor   // Parse the optional 'framework' keyword.
24996ddfca91SDouglas Gregor   bool IsFramework = false;
25006ddfca91SDouglas Gregor   if (Tok.is(MMToken::FrameworkKeyword)) {
25016ddfca91SDouglas Gregor     consumeToken();
25026ddfca91SDouglas Gregor     IsFramework = true;
25036ddfca91SDouglas Gregor   }
25046ddfca91SDouglas Gregor 
25056ddfca91SDouglas Gregor   // Parse the library name
25066ddfca91SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
25076ddfca91SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
25086ddfca91SDouglas Gregor       << IsFramework << SourceRange(LinkLoc);
25096ddfca91SDouglas Gregor     HadError = true;
25106ddfca91SDouglas Gregor     return;
25116ddfca91SDouglas Gregor   }
25126ddfca91SDouglas Gregor 
25136ddfca91SDouglas Gregor   std::string LibraryName = Tok.getString();
25146ddfca91SDouglas Gregor   consumeToken();
25156ddfca91SDouglas Gregor   ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
25166ddfca91SDouglas Gregor                                                             IsFramework));
25176ddfca91SDouglas Gregor }
25186ddfca91SDouglas Gregor 
25199fc8faf9SAdrian Prantl /// Parse a configuration macro declaration.
252035b13eceSDouglas Gregor ///
252135b13eceSDouglas Gregor ///   module-declaration:
252235b13eceSDouglas Gregor ///     'config_macros' attributes[opt] config-macro-list?
252335b13eceSDouglas Gregor ///
252435b13eceSDouglas Gregor ///   config-macro-list:
252535b13eceSDouglas Gregor ///     identifier (',' identifier)?
252635b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() {
252735b13eceSDouglas Gregor   assert(Tok.is(MMToken::ConfigMacros));
252835b13eceSDouglas Gregor   SourceLocation ConfigMacrosLoc = consumeToken();
252935b13eceSDouglas Gregor 
253035b13eceSDouglas Gregor   // Only top-level modules can have configuration macros.
253135b13eceSDouglas Gregor   if (ActiveModule->Parent) {
253235b13eceSDouglas Gregor     Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
253335b13eceSDouglas Gregor   }
253435b13eceSDouglas Gregor 
253535b13eceSDouglas Gregor   // Parse the optional attributes.
253635b13eceSDouglas Gregor   Attributes Attrs;
25375d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
25385d29dee0SDavide Italiano     return;
25395d29dee0SDavide Italiano 
254035b13eceSDouglas Gregor   if (Attrs.IsExhaustive && !ActiveModule->Parent) {
254135b13eceSDouglas Gregor     ActiveModule->ConfigMacrosExhaustive = true;
254235b13eceSDouglas Gregor   }
254335b13eceSDouglas Gregor 
254435b13eceSDouglas Gregor   // If we don't have an identifier, we're done.
2545306d8920SRichard Smith   // FIXME: Support macros with the same name as a keyword here.
254635b13eceSDouglas Gregor   if (!Tok.is(MMToken::Identifier))
254735b13eceSDouglas Gregor     return;
254835b13eceSDouglas Gregor 
254935b13eceSDouglas Gregor   // Consume the first identifier.
255035b13eceSDouglas Gregor   if (!ActiveModule->Parent) {
255135b13eceSDouglas Gregor     ActiveModule->ConfigMacros.push_back(Tok.getString().str());
255235b13eceSDouglas Gregor   }
255335b13eceSDouglas Gregor   consumeToken();
255435b13eceSDouglas Gregor 
255535b13eceSDouglas Gregor   do {
255635b13eceSDouglas Gregor     // If there's a comma, consume it.
255735b13eceSDouglas Gregor     if (!Tok.is(MMToken::Comma))
255835b13eceSDouglas Gregor       break;
255935b13eceSDouglas Gregor     consumeToken();
256035b13eceSDouglas Gregor 
256135b13eceSDouglas Gregor     // We expect to see a macro name here.
2562306d8920SRichard Smith     // FIXME: Support macros with the same name as a keyword here.
256335b13eceSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
256435b13eceSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
256535b13eceSDouglas Gregor       break;
256635b13eceSDouglas Gregor     }
256735b13eceSDouglas Gregor 
256835b13eceSDouglas Gregor     // Consume the macro name.
256935b13eceSDouglas Gregor     if (!ActiveModule->Parent) {
257035b13eceSDouglas Gregor       ActiveModule->ConfigMacros.push_back(Tok.getString().str());
257135b13eceSDouglas Gregor     }
257235b13eceSDouglas Gregor     consumeToken();
257335b13eceSDouglas Gregor   } while (true);
257435b13eceSDouglas Gregor }
257535b13eceSDouglas Gregor 
25769fc8faf9SAdrian Prantl /// Format a module-id into a string.
2577fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) {
2578fb912657SDouglas Gregor   std::string result;
2579fb912657SDouglas Gregor   {
2580fb912657SDouglas Gregor     llvm::raw_string_ostream OS(result);
2581fb912657SDouglas Gregor 
2582fb912657SDouglas Gregor     for (unsigned I = 0, N = Id.size(); I != N; ++I) {
2583fb912657SDouglas Gregor       if (I)
2584fb912657SDouglas Gregor         OS << ".";
2585fb912657SDouglas Gregor       OS << Id[I].first;
2586fb912657SDouglas Gregor     }
2587fb912657SDouglas Gregor   }
2588fb912657SDouglas Gregor 
2589fb912657SDouglas Gregor   return result;
2590fb912657SDouglas Gregor }
2591fb912657SDouglas Gregor 
25929fc8faf9SAdrian Prantl /// Parse a conflict declaration.
2593fb912657SDouglas Gregor ///
2594fb912657SDouglas Gregor ///   module-declaration:
2595fb912657SDouglas Gregor ///     'conflict' module-id ',' string-literal
2596fb912657SDouglas Gregor void ModuleMapParser::parseConflict() {
2597fb912657SDouglas Gregor   assert(Tok.is(MMToken::Conflict));
2598fb912657SDouglas Gregor   SourceLocation ConflictLoc = consumeToken();
2599fb912657SDouglas Gregor   Module::UnresolvedConflict Conflict;
2600fb912657SDouglas Gregor 
2601fb912657SDouglas Gregor   // Parse the module-id.
2602fb912657SDouglas Gregor   if (parseModuleId(Conflict.Id))
2603fb912657SDouglas Gregor     return;
2604fb912657SDouglas Gregor 
2605fb912657SDouglas Gregor   // Parse the ','.
2606fb912657SDouglas Gregor   if (!Tok.is(MMToken::Comma)) {
2607fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
2608fb912657SDouglas Gregor       << SourceRange(ConflictLoc);
2609fb912657SDouglas Gregor     return;
2610fb912657SDouglas Gregor   }
2611fb912657SDouglas Gregor   consumeToken();
2612fb912657SDouglas Gregor 
2613fb912657SDouglas Gregor   // Parse the message.
2614fb912657SDouglas Gregor   if (!Tok.is(MMToken::StringLiteral)) {
2615fb912657SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
2616fb912657SDouglas Gregor       << formatModuleId(Conflict.Id);
2617fb912657SDouglas Gregor     return;
2618fb912657SDouglas Gregor   }
2619fb912657SDouglas Gregor   Conflict.Message = Tok.getString().str();
2620fb912657SDouglas Gregor   consumeToken();
2621fb912657SDouglas Gregor 
2622fb912657SDouglas Gregor   // Add this unresolved conflict.
2623fb912657SDouglas Gregor   ActiveModule->UnresolvedConflicts.push_back(Conflict);
2624fb912657SDouglas Gregor }
2625fb912657SDouglas Gregor 
26269fc8faf9SAdrian Prantl /// Parse an inferred module declaration (wildcard modules).
26279194a91dSDouglas Gregor ///
26289194a91dSDouglas Gregor ///   module-declaration:
26299194a91dSDouglas Gregor ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
26309194a91dSDouglas Gregor ///       { inferred-module-member* }
26319194a91dSDouglas Gregor ///
26329194a91dSDouglas Gregor ///   inferred-module-member:
26339194a91dSDouglas Gregor ///     'export' '*'
26349194a91dSDouglas Gregor ///     'exclude' identifier
26359194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
263673441091SDouglas Gregor   assert(Tok.is(MMToken::Star));
263773441091SDouglas Gregor   SourceLocation StarLoc = consumeToken();
263873441091SDouglas Gregor   bool Failed = false;
263973441091SDouglas Gregor 
264073441091SDouglas Gregor   // Inferred modules must be submodules.
26419194a91dSDouglas Gregor   if (!ActiveModule && !Framework) {
264273441091SDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
264373441091SDouglas Gregor     Failed = true;
264473441091SDouglas Gregor   }
264573441091SDouglas Gregor 
26469194a91dSDouglas Gregor   if (ActiveModule) {
2647524e33e1SDouglas Gregor     // Inferred modules must have umbrella directories.
26484898cde4SBen Langmuir     if (!Failed && ActiveModule->IsAvailable &&
26494898cde4SBen Langmuir         !ActiveModule->getUmbrellaDir()) {
265073441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
265173441091SDouglas Gregor       Failed = true;
265273441091SDouglas Gregor     }
265373441091SDouglas Gregor 
265473441091SDouglas Gregor     // Check for redefinition of an inferred module.
2655dd005f69SDouglas Gregor     if (!Failed && ActiveModule->InferSubmodules) {
265673441091SDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2657dd005f69SDouglas Gregor       if (ActiveModule->InferredSubmoduleLoc.isValid())
2658dd005f69SDouglas Gregor         Diags.Report(ActiveModule->InferredSubmoduleLoc,
265973441091SDouglas Gregor                      diag::note_mmap_prev_definition);
266073441091SDouglas Gregor       Failed = true;
266173441091SDouglas Gregor     }
266273441091SDouglas Gregor 
26639194a91dSDouglas Gregor     // Check for the 'framework' keyword, which is not permitted here.
26649194a91dSDouglas Gregor     if (Framework) {
26659194a91dSDouglas Gregor       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
26669194a91dSDouglas Gregor       Framework = false;
26679194a91dSDouglas Gregor     }
26689194a91dSDouglas Gregor   } else if (Explicit) {
26699194a91dSDouglas Gregor     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
26709194a91dSDouglas Gregor     Explicit = false;
26719194a91dSDouglas Gregor   }
26729194a91dSDouglas Gregor 
267373441091SDouglas Gregor   // If there were any problems with this inferred submodule, skip its body.
267473441091SDouglas Gregor   if (Failed) {
267573441091SDouglas Gregor     if (Tok.is(MMToken::LBrace)) {
267673441091SDouglas Gregor       consumeToken();
267773441091SDouglas Gregor       skipUntil(MMToken::RBrace);
267873441091SDouglas Gregor       if (Tok.is(MMToken::RBrace))
267973441091SDouglas Gregor         consumeToken();
268073441091SDouglas Gregor     }
268173441091SDouglas Gregor     HadError = true;
268273441091SDouglas Gregor     return;
268373441091SDouglas Gregor   }
268473441091SDouglas Gregor 
26859194a91dSDouglas Gregor   // Parse optional attributes.
26864442605fSBill Wendling   Attributes Attrs;
26875d29dee0SDavide Italiano   if (parseOptionalAttributes(Attrs))
26885d29dee0SDavide Italiano     return;
26899194a91dSDouglas Gregor 
26909194a91dSDouglas Gregor   if (ActiveModule) {
269173441091SDouglas Gregor     // Note that we have an inferred submodule.
2692dd005f69SDouglas Gregor     ActiveModule->InferSubmodules = true;
2693dd005f69SDouglas Gregor     ActiveModule->InferredSubmoduleLoc = StarLoc;
2694dd005f69SDouglas Gregor     ActiveModule->InferExplicitSubmodules = Explicit;
26959194a91dSDouglas Gregor   } else {
26969194a91dSDouglas Gregor     // We'll be inferring framework modules for this directory.
26979194a91dSDouglas Gregor     Map.InferredDirectories[Directory].InferModules = true;
2698c1d88ea5SBen Langmuir     Map.InferredDirectories[Directory].Attrs = Attrs;
2699beee15e7SBen Langmuir     Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
2700131daca0SRichard Smith     // FIXME: Handle the 'framework' keyword.
27019194a91dSDouglas Gregor   }
270273441091SDouglas Gregor 
270373441091SDouglas Gregor   // Parse the opening brace.
270473441091SDouglas Gregor   if (!Tok.is(MMToken::LBrace)) {
270573441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
270673441091SDouglas Gregor     HadError = true;
270773441091SDouglas Gregor     return;
270873441091SDouglas Gregor   }
270973441091SDouglas Gregor   SourceLocation LBraceLoc = consumeToken();
271073441091SDouglas Gregor 
271173441091SDouglas Gregor   // Parse the body of the inferred submodule.
271273441091SDouglas Gregor   bool Done = false;
271373441091SDouglas Gregor   do {
271473441091SDouglas Gregor     switch (Tok.Kind) {
271573441091SDouglas Gregor     case MMToken::EndOfFile:
271673441091SDouglas Gregor     case MMToken::RBrace:
271773441091SDouglas Gregor       Done = true;
271873441091SDouglas Gregor       break;
271973441091SDouglas Gregor 
2720afd1b1c9SEugene Zelenko     case MMToken::ExcludeKeyword:
27219194a91dSDouglas Gregor       if (ActiveModule) {
27229194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2723d2d442caSCraig Topper           << (ActiveModule != nullptr);
27249194a91dSDouglas Gregor         consumeToken();
27259194a91dSDouglas Gregor         break;
27269194a91dSDouglas Gregor       }
27279194a91dSDouglas Gregor 
27289194a91dSDouglas Gregor       consumeToken();
2729306d8920SRichard Smith       // FIXME: Support string-literal module names here.
27309194a91dSDouglas Gregor       if (!Tok.is(MMToken::Identifier)) {
27319194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
27329194a91dSDouglas Gregor         break;
27339194a91dSDouglas Gregor       }
27349194a91dSDouglas Gregor 
27359194a91dSDouglas Gregor       Map.InferredDirectories[Directory].ExcludedModules
27369194a91dSDouglas Gregor         .push_back(Tok.getString());
27379194a91dSDouglas Gregor       consumeToken();
27389194a91dSDouglas Gregor       break;
27399194a91dSDouglas Gregor 
27409194a91dSDouglas Gregor     case MMToken::ExportKeyword:
27419194a91dSDouglas Gregor       if (!ActiveModule) {
27429194a91dSDouglas Gregor         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2743d2d442caSCraig Topper           << (ActiveModule != nullptr);
27449194a91dSDouglas Gregor         consumeToken();
27459194a91dSDouglas Gregor         break;
27469194a91dSDouglas Gregor       }
27479194a91dSDouglas Gregor 
274873441091SDouglas Gregor       consumeToken();
274973441091SDouglas Gregor       if (Tok.is(MMToken::Star))
2750dd005f69SDouglas Gregor         ActiveModule->InferExportWildcard = true;
275173441091SDouglas Gregor       else
275273441091SDouglas Gregor         Diags.Report(Tok.getLocation(),
275373441091SDouglas Gregor                      diag::err_mmap_expected_export_wildcard);
275473441091SDouglas Gregor       consumeToken();
275573441091SDouglas Gregor       break;
275673441091SDouglas Gregor 
275773441091SDouglas Gregor     case MMToken::ExplicitKeyword:
275873441091SDouglas Gregor     case MMToken::ModuleKeyword:
275973441091SDouglas Gregor     case MMToken::HeaderKeyword:
2760b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
276173441091SDouglas Gregor     case MMToken::UmbrellaKeyword:
276273441091SDouglas Gregor     default:
27639194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2764d2d442caSCraig Topper           << (ActiveModule != nullptr);
276573441091SDouglas Gregor       consumeToken();
276673441091SDouglas Gregor       break;
276773441091SDouglas Gregor     }
276873441091SDouglas Gregor   } while (!Done);
276973441091SDouglas Gregor 
277073441091SDouglas Gregor   if (Tok.is(MMToken::RBrace))
277173441091SDouglas Gregor     consumeToken();
277273441091SDouglas Gregor   else {
277373441091SDouglas Gregor     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
277473441091SDouglas Gregor     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
277573441091SDouglas Gregor     HadError = true;
277673441091SDouglas Gregor   }
277773441091SDouglas Gregor }
277873441091SDouglas Gregor 
27799fc8faf9SAdrian Prantl /// Parse optional attributes.
27809194a91dSDouglas Gregor ///
27819194a91dSDouglas Gregor ///   attributes:
27829194a91dSDouglas Gregor ///     attribute attributes
27839194a91dSDouglas Gregor ///     attribute
27849194a91dSDouglas Gregor ///
27859194a91dSDouglas Gregor ///   attribute:
27869194a91dSDouglas Gregor ///     [ identifier ]
27879194a91dSDouglas Gregor ///
27889194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes.
27899194a91dSDouglas Gregor ///
27909194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise.
27914442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
27929194a91dSDouglas Gregor   bool HadError = false;
27939194a91dSDouglas Gregor 
27949194a91dSDouglas Gregor   while (Tok.is(MMToken::LSquare)) {
27959194a91dSDouglas Gregor     // Consume the '['.
27969194a91dSDouglas Gregor     SourceLocation LSquareLoc = consumeToken();
27979194a91dSDouglas Gregor 
27989194a91dSDouglas Gregor     // Check whether we have an attribute name here.
27999194a91dSDouglas Gregor     if (!Tok.is(MMToken::Identifier)) {
28009194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
28019194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
28029194a91dSDouglas Gregor       if (Tok.is(MMToken::RSquare))
28039194a91dSDouglas Gregor         consumeToken();
28049194a91dSDouglas Gregor       HadError = true;
28059194a91dSDouglas Gregor     }
28069194a91dSDouglas Gregor 
28079194a91dSDouglas Gregor     // Decode the attribute name.
28089194a91dSDouglas Gregor     AttributeKind Attribute
28099194a91dSDouglas Gregor       = llvm::StringSwitch<AttributeKind>(Tok.getString())
281035b13eceSDouglas Gregor           .Case("exhaustive", AT_exhaustive)
281177944868SRichard Smith           .Case("extern_c", AT_extern_c)
2812ed84df00SBruno Cardoso Lopes           .Case("no_undeclared_includes", AT_no_undeclared_includes)
28139194a91dSDouglas Gregor           .Case("system", AT_system)
28149194a91dSDouglas Gregor           .Default(AT_unknown);
28159194a91dSDouglas Gregor     switch (Attribute) {
28169194a91dSDouglas Gregor     case AT_unknown:
28179194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
28189194a91dSDouglas Gregor         << Tok.getString();
28199194a91dSDouglas Gregor       break;
28209194a91dSDouglas Gregor 
28219194a91dSDouglas Gregor     case AT_system:
28229194a91dSDouglas Gregor       Attrs.IsSystem = true;
28239194a91dSDouglas Gregor       break;
282435b13eceSDouglas Gregor 
282577944868SRichard Smith     case AT_extern_c:
282677944868SRichard Smith       Attrs.IsExternC = true;
282777944868SRichard Smith       break;
282877944868SRichard Smith 
282935b13eceSDouglas Gregor     case AT_exhaustive:
283035b13eceSDouglas Gregor       Attrs.IsExhaustive = true;
283135b13eceSDouglas Gregor       break;
2832ed84df00SBruno Cardoso Lopes 
2833ed84df00SBruno Cardoso Lopes     case AT_no_undeclared_includes:
2834ed84df00SBruno Cardoso Lopes       Attrs.NoUndeclaredIncludes = true;
2835ed84df00SBruno Cardoso Lopes       break;
28369194a91dSDouglas Gregor     }
28379194a91dSDouglas Gregor     consumeToken();
28389194a91dSDouglas Gregor 
28399194a91dSDouglas Gregor     // Consume the ']'.
28409194a91dSDouglas Gregor     if (!Tok.is(MMToken::RSquare)) {
28419194a91dSDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
28429194a91dSDouglas Gregor       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
28439194a91dSDouglas Gregor       skipUntil(MMToken::RSquare);
28449194a91dSDouglas Gregor       HadError = true;
28459194a91dSDouglas Gregor     }
28469194a91dSDouglas Gregor 
28479194a91dSDouglas Gregor     if (Tok.is(MMToken::RSquare))
28489194a91dSDouglas Gregor       consumeToken();
28499194a91dSDouglas Gregor   }
28509194a91dSDouglas Gregor 
28519194a91dSDouglas Gregor   return HadError;
28529194a91dSDouglas Gregor }
28539194a91dSDouglas Gregor 
28549fc8faf9SAdrian Prantl /// Parse a module map file.
2855718292f2SDouglas Gregor ///
2856718292f2SDouglas Gregor ///   module-map-file:
2857718292f2SDouglas Gregor ///     module-declaration*
2858718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
2859718292f2SDouglas Gregor   do {
2860718292f2SDouglas Gregor     switch (Tok.Kind) {
2861718292f2SDouglas Gregor     case MMToken::EndOfFile:
2862718292f2SDouglas Gregor       return HadError;
2863718292f2SDouglas Gregor 
2864e7ab3669SDouglas Gregor     case MMToken::ExplicitKeyword:
286597292843SDaniel Jasper     case MMToken::ExternKeyword:
2866718292f2SDouglas Gregor     case MMToken::ModuleKeyword:
2867755b2055SDouglas Gregor     case MMToken::FrameworkKeyword:
2868718292f2SDouglas Gregor       parseModuleDecl();
2869718292f2SDouglas Gregor       break;
2870718292f2SDouglas Gregor 
28711fb5c3a6SDouglas Gregor     case MMToken::Comma:
287235b13eceSDouglas Gregor     case MMToken::ConfigMacros:
2873fb912657SDouglas Gregor     case MMToken::Conflict:
2874a3feee2aSRichard Smith     case MMToken::Exclaim:
287559527666SDouglas Gregor     case MMToken::ExcludeKeyword:
28762b82c2a5SDouglas Gregor     case MMToken::ExportKeyword:
2877f0b11de2SDouglas Gregor     case MMToken::ExportAsKeyword:
2878718292f2SDouglas Gregor     case MMToken::HeaderKeyword:
2879718292f2SDouglas Gregor     case MMToken::Identifier:
2880718292f2SDouglas Gregor     case MMToken::LBrace:
28816ddfca91SDouglas Gregor     case MMToken::LinkKeyword:
2882a686e1b0SDouglas Gregor     case MMToken::LSquare:
28832b82c2a5SDouglas Gregor     case MMToken::Period:
2884b53e5483SLawrence Crowl     case MMToken::PrivateKeyword:
2885718292f2SDouglas Gregor     case MMToken::RBrace:
2886a686e1b0SDouglas Gregor     case MMToken::RSquare:
28871fb5c3a6SDouglas Gregor     case MMToken::RequiresKeyword:
28882b82c2a5SDouglas Gregor     case MMToken::Star:
2889718292f2SDouglas Gregor     case MMToken::StringLiteral:
2890040e1266SRichard Smith     case MMToken::IntegerLiteral:
2891b8afebe2SRichard Smith     case MMToken::TextualKeyword:
2892718292f2SDouglas Gregor     case MMToken::UmbrellaKeyword:
2893ba7f2f71SDaniel Jasper     case MMToken::UseKeyword:
2894718292f2SDouglas Gregor       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
2895718292f2SDouglas Gregor       HadError = true;
2896718292f2SDouglas Gregor       consumeToken();
2897718292f2SDouglas Gregor       break;
2898718292f2SDouglas Gregor     }
2899718292f2SDouglas Gregor   } while (true);
2900718292f2SDouglas Gregor }
2901718292f2SDouglas Gregor 
29029acb99e3SRichard Smith bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
2903c192d194SBruno Cardoso Lopes                                    const DirectoryEntry *Dir, FileID ID,
29048128f332SRichard Smith                                    unsigned *Offset,
2905ae6df27eSRichard Smith                                    SourceLocation ExternModuleLoc) {
29068128f332SRichard Smith   assert(Target && "Missing target information");
29074ddf2221SDouglas Gregor   llvm::DenseMap<const FileEntry *, bool>::iterator Known
29084ddf2221SDouglas Gregor     = ParsedModuleMap.find(File);
29094ddf2221SDouglas Gregor   if (Known != ParsedModuleMap.end())
29104ddf2221SDouglas Gregor     return Known->second;
29114ddf2221SDouglas Gregor 
29128128f332SRichard Smith   // If the module map file wasn't already entered, do so now.
29138128f332SRichard Smith   if (ID.isInvalid()) {
2914f3f84616SRichard Smith     auto FileCharacter =
2915f3f84616SRichard Smith         IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
29168128f332SRichard Smith     ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
29178128f332SRichard Smith   }
29188128f332SRichard Smith 
29198128f332SRichard Smith   assert(Target && "Missing target information");
29201f76c4e8SManuel Klimek   const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID);
2921718292f2SDouglas Gregor   if (!Buffer)
29224ddf2221SDouglas Gregor     return ParsedModuleMap[File] = true;
29238128f332SRichard Smith   assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
29248128f332SRichard Smith          "invalid buffer offset");
2925718292f2SDouglas Gregor 
2926718292f2SDouglas Gregor   // Parse this module map file.
29278128f332SRichard Smith   Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
29288128f332SRichard Smith           Buffer->getBufferStart(),
29298128f332SRichard Smith           Buffer->getBufferStart() + (Offset ? *Offset : 0),
29308128f332SRichard Smith           Buffer->getBufferEnd());
29312a6edb30SRichard Smith   SourceLocation Start = L.getSourceLocation();
2932beee15e7SBen Langmuir   ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
2933c192d194SBruno Cardoso Lopes                          IsSystem);
2934718292f2SDouglas Gregor   bool Result = Parser.parseModuleMapFile();
29354ddf2221SDouglas Gregor   ParsedModuleMap[File] = Result;
29362a6edb30SRichard Smith 
29378128f332SRichard Smith   if (Offset) {
29388128f332SRichard Smith     auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
29398128f332SRichard Smith     assert(Loc.first == ID && "stopped in a different file?");
29408128f332SRichard Smith     *Offset = Loc.second;
29418128f332SRichard Smith   }
29428128f332SRichard Smith 
29432a6edb30SRichard Smith   // Notify callbacks that we parsed it.
29442a6edb30SRichard Smith   for (const auto &Cb : Callbacks)
29452a6edb30SRichard Smith     Cb->moduleMapFileRead(Start, *File, IsSystem);
29468587dfd9SBruno Cardoso Lopes 
2947718292f2SDouglas Gregor   return Result;
2948718292f2SDouglas Gregor }
2949