xref: /src/contrib/llvm-project/clang/lib/Lex/ModuleMap.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1461a67faSDimitry Andric //===- ModuleMap.cpp - Describe the layout of modules ---------------------===//
2dbe13110SDimitry Andric //
322989816SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
422989816SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
522989816SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6dbe13110SDimitry Andric //
7dbe13110SDimitry Andric //===----------------------------------------------------------------------===//
8dbe13110SDimitry Andric //
9dbe13110SDimitry Andric // This file defines the ModuleMap implementation, which describes the layout
10dbe13110SDimitry Andric // of a module as it relates to headers.
11dbe13110SDimitry Andric //
12dbe13110SDimitry Andric //===----------------------------------------------------------------------===//
13461a67faSDimitry Andric 
14dbe13110SDimitry Andric #include "clang/Lex/ModuleMap.h"
15809500fcSDimitry Andric #include "clang/Basic/CharInfo.h"
16dbe13110SDimitry Andric #include "clang/Basic/Diagnostic.h"
17dbe13110SDimitry Andric #include "clang/Basic/FileManager.h"
18461a67faSDimitry Andric #include "clang/Basic/LLVM.h"
19461a67faSDimitry Andric #include "clang/Basic/LangOptions.h"
20461a67faSDimitry Andric #include "clang/Basic/Module.h"
21461a67faSDimitry Andric #include "clang/Basic/SourceLocation.h"
22461a67faSDimitry Andric #include "clang/Basic/SourceManager.h"
23dbe13110SDimitry Andric #include "clang/Basic/TargetInfo.h"
24809500fcSDimitry Andric #include "clang/Lex/HeaderSearch.h"
2506d4ba38SDimitry Andric #include "clang/Lex/HeaderSearchOptions.h"
26809500fcSDimitry Andric #include "clang/Lex/LexDiagnostic.h"
27809500fcSDimitry Andric #include "clang/Lex/Lexer.h"
28809500fcSDimitry Andric #include "clang/Lex/LiteralSupport.h"
29461a67faSDimitry Andric #include "clang/Lex/Token.h"
30461a67faSDimitry Andric #include "llvm/ADT/DenseMap.h"
31461a67faSDimitry Andric #include "llvm/ADT/STLExtras.h"
32461a67faSDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
33461a67faSDimitry Andric #include "llvm/ADT/SmallString.h"
34461a67faSDimitry Andric #include "llvm/ADT/SmallVector.h"
35461a67faSDimitry Andric #include "llvm/ADT/StringMap.h"
36809500fcSDimitry Andric #include "llvm/ADT/StringRef.h"
37809500fcSDimitry Andric #include "llvm/ADT/StringSwitch.h"
38dbe13110SDimitry Andric #include "llvm/Support/Allocator.h"
39461a67faSDimitry Andric #include "llvm/Support/Compiler.h"
40461a67faSDimitry Andric #include "llvm/Support/ErrorHandling.h"
41461a67faSDimitry Andric #include "llvm/Support/MemoryBuffer.h"
42bfef3995SDimitry Andric #include "llvm/Support/Path.h"
43676fbe81SDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
44dbe13110SDimitry Andric #include "llvm/Support/raw_ostream.h"
45461a67faSDimitry Andric #include <algorithm>
46461a67faSDimitry Andric #include <cassert>
47461a67faSDimitry Andric #include <cstdint>
48461a67faSDimitry Andric #include <cstring>
49e3b55780SDimitry Andric #include <optional>
50461a67faSDimitry Andric #include <string>
51461a67faSDimitry Andric #include <system_error>
52461a67faSDimitry Andric #include <utility>
53461a67faSDimitry Andric 
54dbe13110SDimitry Andric using namespace clang;
55dbe13110SDimitry Andric 
anchor()56676fbe81SDimitry Andric void ModuleMapCallbacks::anchor() {}
57676fbe81SDimitry Andric 
resolveLinkAsDependencies(Module * Mod)5848675466SDimitry Andric void ModuleMap::resolveLinkAsDependencies(Module *Mod) {
5948675466SDimitry Andric   auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name);
6048675466SDimitry Andric   if (PendingLinkAs != PendingLinkAsModule.end()) {
6148675466SDimitry Andric     for (auto &Name : PendingLinkAs->second) {
6248675466SDimitry Andric       auto *M = findModule(Name.getKey());
6348675466SDimitry Andric       if (M)
6448675466SDimitry Andric         M->UseExportAsModuleLinkName = true;
6548675466SDimitry Andric     }
6648675466SDimitry Andric   }
6748675466SDimitry Andric }
6848675466SDimitry Andric 
addLinkAsDependency(Module * Mod)6948675466SDimitry Andric void ModuleMap::addLinkAsDependency(Module *Mod) {
7048675466SDimitry Andric   if (findModule(Mod->ExportAsModule))
7148675466SDimitry Andric     Mod->UseExportAsModuleLinkName = true;
7248675466SDimitry Andric   else
7348675466SDimitry Andric     PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name);
7448675466SDimitry Andric }
7548675466SDimitry Andric 
headerRoleToKind(ModuleHeaderRole Role)76551c6985SDimitry Andric Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
77551c6985SDimitry Andric   switch ((int)Role) {
78551c6985SDimitry Andric   case NormalHeader:
79551c6985SDimitry Andric     return Module::HK_Normal;
80551c6985SDimitry Andric   case PrivateHeader:
81551c6985SDimitry Andric     return Module::HK_Private;
82551c6985SDimitry Andric   case TextualHeader:
83551c6985SDimitry Andric     return Module::HK_Textual;
84551c6985SDimitry Andric   case PrivateHeader | TextualHeader:
85551c6985SDimitry Andric     return Module::HK_PrivateTextual;
86e3b55780SDimitry Andric   case ExcludedHeader:
87e3b55780SDimitry Andric     return Module::HK_Excluded;
88551c6985SDimitry Andric   }
89e3b55780SDimitry Andric   llvm_unreachable("unknown header role");
90551c6985SDimitry Andric }
91551c6985SDimitry Andric 
92551c6985SDimitry Andric ModuleMap::ModuleHeaderRole
headerKindToRole(Module::HeaderKind Kind)93551c6985SDimitry Andric ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
94551c6985SDimitry Andric   switch ((int)Kind) {
95551c6985SDimitry Andric   case Module::HK_Normal:
96551c6985SDimitry Andric     return NormalHeader;
97551c6985SDimitry Andric   case Module::HK_Private:
98551c6985SDimitry Andric     return PrivateHeader;
99551c6985SDimitry Andric   case Module::HK_Textual:
100551c6985SDimitry Andric     return TextualHeader;
101551c6985SDimitry Andric   case Module::HK_PrivateTextual:
102551c6985SDimitry Andric     return ModuleHeaderRole(PrivateHeader | TextualHeader);
103551c6985SDimitry Andric   case Module::HK_Excluded:
104e3b55780SDimitry Andric     return ExcludedHeader;
105551c6985SDimitry Andric   }
106551c6985SDimitry Andric   llvm_unreachable("unknown header kind");
107551c6985SDimitry Andric }
108551c6985SDimitry Andric 
isModular(ModuleHeaderRole Role)109e3b55780SDimitry Andric bool ModuleMap::isModular(ModuleHeaderRole Role) {
110e3b55780SDimitry Andric   return !(Role & (ModuleMap::TextualHeader | ModuleMap::ExcludedHeader));
111e3b55780SDimitry Andric }
112e3b55780SDimitry Andric 
113dbe13110SDimitry Andric Module::ExportDecl
resolveExport(Module * Mod,const Module::UnresolvedExportDecl & Unresolved,bool Complain) const114dbe13110SDimitry Andric ModuleMap::resolveExport(Module *Mod,
115dbe13110SDimitry Andric                          const Module::UnresolvedExportDecl &Unresolved,
116809500fcSDimitry Andric                          bool Complain) const {
117dbe13110SDimitry Andric   // We may have just a wildcard.
118dbe13110SDimitry Andric   if (Unresolved.Id.empty()) {
119dbe13110SDimitry Andric     assert(Unresolved.Wildcard && "Invalid unresolved export");
1209f4dbff6SDimitry Andric     return Module::ExportDecl(nullptr, true);
121dbe13110SDimitry Andric   }
122dbe13110SDimitry Andric 
123809500fcSDimitry Andric   // Resolve the module-id.
124809500fcSDimitry Andric   Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
125809500fcSDimitry Andric   if (!Context)
126461a67faSDimitry Andric     return {};
127809500fcSDimitry Andric 
128809500fcSDimitry Andric   return Module::ExportDecl(Context, Unresolved.Wildcard);
129809500fcSDimitry Andric }
130809500fcSDimitry Andric 
resolveModuleId(const ModuleId & Id,Module * Mod,bool Complain) const131809500fcSDimitry Andric Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
132809500fcSDimitry Andric                                    bool Complain) const {
133dbe13110SDimitry Andric   // Find the starting module.
134809500fcSDimitry Andric   Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
135dbe13110SDimitry Andric   if (!Context) {
136dbe13110SDimitry Andric     if (Complain)
1379f4dbff6SDimitry Andric       Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
138809500fcSDimitry Andric       << Id[0].first << Mod->getFullModuleName();
139dbe13110SDimitry Andric 
1409f4dbff6SDimitry Andric     return nullptr;
141dbe13110SDimitry Andric   }
142dbe13110SDimitry Andric 
143dbe13110SDimitry Andric   // Dig into the module path.
144809500fcSDimitry Andric   for (unsigned I = 1, N = Id.size(); I != N; ++I) {
145809500fcSDimitry Andric     Module *Sub = lookupModuleQualified(Id[I].first, Context);
146dbe13110SDimitry Andric     if (!Sub) {
147dbe13110SDimitry Andric       if (Complain)
1489f4dbff6SDimitry Andric         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
149809500fcSDimitry Andric         << Id[I].first << Context->getFullModuleName()
150809500fcSDimitry Andric         << SourceRange(Id[0].second, Id[I-1].second);
151dbe13110SDimitry Andric 
1529f4dbff6SDimitry Andric       return nullptr;
153dbe13110SDimitry Andric     }
154dbe13110SDimitry Andric 
155dbe13110SDimitry Andric     Context = Sub;
156dbe13110SDimitry Andric   }
157dbe13110SDimitry Andric 
158809500fcSDimitry Andric   return Context;
159dbe13110SDimitry Andric }
160dbe13110SDimitry Andric 
16148675466SDimitry Andric /// Append to \p Paths the set of paths needed to get to the
162b5aee35cSDimitry Andric /// subframework in which the given module lives.
appendSubframeworkPaths(Module * Mod,SmallVectorImpl<char> & Path)163b5aee35cSDimitry Andric static void appendSubframeworkPaths(Module *Mod,
164b5aee35cSDimitry Andric                                     SmallVectorImpl<char> &Path) {
165b5aee35cSDimitry Andric   // Collect the framework names from the given module to the top-level module.
166b5aee35cSDimitry Andric   SmallVector<StringRef, 2> Paths;
167b5aee35cSDimitry Andric   for (; Mod; Mod = Mod->Parent) {
168b5aee35cSDimitry Andric     if (Mod->IsFramework)
169b5aee35cSDimitry Andric       Paths.push_back(Mod->Name);
170b5aee35cSDimitry Andric   }
171b5aee35cSDimitry Andric 
172b5aee35cSDimitry Andric   if (Paths.empty())
173b5aee35cSDimitry Andric     return;
174b5aee35cSDimitry Andric 
175b5aee35cSDimitry Andric   // Add Frameworks/Name.framework for each subframework.
176c0981da4SDimitry Andric   for (StringRef Framework : llvm::drop_begin(llvm::reverse(Paths)))
177c0981da4SDimitry Andric     llvm::sys::path::append(Path, "Frameworks", Framework + ".framework");
178b5aee35cSDimitry Andric }
179b5aee35cSDimitry Andric 
findHeader(Module * M,const Module::UnresolvedHeaderDirective & Header,SmallVectorImpl<char> & RelativePathName,bool & NeedsFramework)180e3b55780SDimitry Andric OptionalFileEntryRef ModuleMap::findHeader(
18148675466SDimitry Andric     Module *M, const Module::UnresolvedHeaderDirective &Header,
18248675466SDimitry Andric     SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) {
18348675466SDimitry Andric   // Search for the header file within the module's home directory.
1847fa27ce4SDimitry Andric   auto Directory = M->Directory;
18548675466SDimitry Andric   SmallString<128> FullPathName(Directory->getName());
18648675466SDimitry Andric 
187e3b55780SDimitry Andric   auto GetFile = [&](StringRef Filename) -> OptionalFileEntryRef {
188b60736ecSDimitry Andric     auto File =
189b60736ecSDimitry Andric         expectedToOptional(SourceMgr.getFileManager().getFileRef(Filename));
190b60736ecSDimitry Andric     if (!File || (Header.Size && File->getSize() != *Header.Size) ||
191b60736ecSDimitry Andric         (Header.ModTime && File->getModificationTime() != *Header.ModTime))
192e3b55780SDimitry Andric       return std::nullopt;
193519fc96cSDimitry Andric     return *File;
194551c6985SDimitry Andric   };
195551c6985SDimitry Andric 
196e3b55780SDimitry Andric   auto GetFrameworkFile = [&]() -> OptionalFileEntryRef {
197b5aee35cSDimitry Andric     unsigned FullPathLength = FullPathName.size();
198b5aee35cSDimitry Andric     appendSubframeworkPaths(M, RelativePathName);
199b5aee35cSDimitry Andric     unsigned RelativePathLength = RelativePathName.size();
200b5aee35cSDimitry Andric 
201b5aee35cSDimitry Andric     // Check whether this file is in the public headers.
202b5aee35cSDimitry Andric     llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
203b5aee35cSDimitry Andric     llvm::sys::path::append(FullPathName, RelativePathName);
204b60736ecSDimitry Andric     if (auto File = GetFile(FullPathName))
205b5aee35cSDimitry Andric       return File;
206b5aee35cSDimitry Andric 
207b5aee35cSDimitry Andric     // Check whether this file is in the private headers.
208b5aee35cSDimitry Andric     // Ideally, private modules in the form 'FrameworkName.Private' should
209b5aee35cSDimitry Andric     // be defined as 'module FrameworkName.Private', and not as
210b5aee35cSDimitry Andric     // 'framework module FrameworkName.Private', since a 'Private.Framework'
211b5aee35cSDimitry Andric     // does not usually exist. However, since both are currently widely used
212b5aee35cSDimitry Andric     // for private modules, make sure we find the right path in both cases.
213b5aee35cSDimitry Andric     if (M->IsFramework && M->Name == "Private")
214b5aee35cSDimitry Andric       RelativePathName.clear();
215b5aee35cSDimitry Andric     else
216b5aee35cSDimitry Andric       RelativePathName.resize(RelativePathLength);
217b5aee35cSDimitry Andric     FullPathName.resize(FullPathLength);
218b5aee35cSDimitry Andric     llvm::sys::path::append(RelativePathName, "PrivateHeaders",
219b5aee35cSDimitry Andric                             Header.FileName);
220b5aee35cSDimitry Andric     llvm::sys::path::append(FullPathName, RelativePathName);
221551c6985SDimitry Andric     return GetFile(FullPathName);
22248675466SDimitry Andric   };
22348675466SDimitry Andric 
22448675466SDimitry Andric   if (llvm::sys::path::is_absolute(Header.FileName)) {
22548675466SDimitry Andric     RelativePathName.clear();
22648675466SDimitry Andric     RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
22748675466SDimitry Andric     return GetFile(Header.FileName);
228b5aee35cSDimitry Andric   }
229b5aee35cSDimitry Andric 
23048675466SDimitry Andric   if (M->isPartOfFramework())
23148675466SDimitry Andric     return GetFrameworkFile();
23248675466SDimitry Andric 
233b5aee35cSDimitry Andric   // Lookup for normal headers.
234b5aee35cSDimitry Andric   llvm::sys::path::append(RelativePathName, Header.FileName);
235b5aee35cSDimitry Andric   llvm::sys::path::append(FullPathName, RelativePathName);
236b60736ecSDimitry Andric   auto NormalHdrFile = GetFile(FullPathName);
23748675466SDimitry Andric 
238312c0ed1SDimitry Andric   if (!NormalHdrFile && Directory->getName().ends_with(".framework")) {
23948675466SDimitry Andric     // The lack of 'framework' keyword in a module declaration it's a simple
24048675466SDimitry Andric     // mistake we can diagnose when the header exists within the proper
24148675466SDimitry Andric     // framework style path.
24248675466SDimitry Andric     FullPathName.assign(Directory->getName());
24348675466SDimitry Andric     RelativePathName.clear();
24448675466SDimitry Andric     if (GetFrameworkFile()) {
24548675466SDimitry Andric       Diags.Report(Header.FileNameLoc,
24648675466SDimitry Andric                    diag::warn_mmap_incomplete_framework_module_declaration)
24748675466SDimitry Andric           << Header.FileName << M->getFullModuleName();
24848675466SDimitry Andric       NeedsFramework = true;
24948675466SDimitry Andric     }
250e3b55780SDimitry Andric     return std::nullopt;
25148675466SDimitry Andric   }
25248675466SDimitry Andric 
25348675466SDimitry Andric   return NormalHdrFile;
254b5aee35cSDimitry Andric }
255b5aee35cSDimitry Andric 
256b1c73532SDimitry Andric /// Determine whether the given file name is the name of a builtin
257b1c73532SDimitry Andric /// header, supplied by Clang to replace, override, or augment existing system
258b1c73532SDimitry Andric /// headers.
isBuiltinHeaderName(StringRef FileName)259b1c73532SDimitry Andric static bool isBuiltinHeaderName(StringRef FileName) {
260b1c73532SDimitry Andric   return llvm::StringSwitch<bool>(FileName)
261b1c73532SDimitry Andric            .Case("float.h", true)
262b1c73532SDimitry Andric            .Case("iso646.h", true)
263b1c73532SDimitry Andric            .Case("limits.h", true)
264b1c73532SDimitry Andric            .Case("stdalign.h", true)
265b1c73532SDimitry Andric            .Case("stdarg.h", true)
266b1c73532SDimitry Andric            .Case("stdatomic.h", true)
267b1c73532SDimitry Andric            .Case("stdbool.h", true)
268b1c73532SDimitry Andric            .Case("stddef.h", true)
269b1c73532SDimitry Andric            .Case("stdint.h", true)
270b1c73532SDimitry Andric            .Case("tgmath.h", true)
271b1c73532SDimitry Andric            .Case("unwind.h", true)
272b1c73532SDimitry Andric            .Default(false);
273b1c73532SDimitry Andric }
274b1c73532SDimitry Andric 
275b1c73532SDimitry Andric /// Determine whether the given module name is the name of a builtin
276b1c73532SDimitry Andric /// module that is cyclic with a system module  on some platforms.
isBuiltInModuleName(StringRef ModuleName)277b1c73532SDimitry Andric static bool isBuiltInModuleName(StringRef ModuleName) {
278b1c73532SDimitry Andric   return llvm::StringSwitch<bool>(ModuleName)
279b1c73532SDimitry Andric            .Case("_Builtin_float", true)
280b1c73532SDimitry Andric            .Case("_Builtin_inttypes", true)
281b1c73532SDimitry Andric            .Case("_Builtin_iso646", true)
282b1c73532SDimitry Andric            .Case("_Builtin_limits", true)
283b1c73532SDimitry Andric            .Case("_Builtin_stdalign", true)
284b1c73532SDimitry Andric            .Case("_Builtin_stdarg", true)
285b1c73532SDimitry Andric            .Case("_Builtin_stdatomic", true)
286b1c73532SDimitry Andric            .Case("_Builtin_stdbool", true)
287b1c73532SDimitry Andric            .Case("_Builtin_stddef", true)
288b1c73532SDimitry Andric            .Case("_Builtin_stdint", true)
289b1c73532SDimitry Andric            .Case("_Builtin_stdnoreturn", true)
290b1c73532SDimitry Andric            .Case("_Builtin_tgmath", true)
291b1c73532SDimitry Andric            .Case("_Builtin_unwind", true)
292b1c73532SDimitry Andric            .Default(false);
293b1c73532SDimitry Andric }
294b1c73532SDimitry Andric 
resolveHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header,bool & NeedsFramework)295551c6985SDimitry Andric void ModuleMap::resolveHeader(Module *Mod,
29648675466SDimitry Andric                               const Module::UnresolvedHeaderDirective &Header,
29748675466SDimitry Andric                               bool &NeedsFramework) {
298551c6985SDimitry Andric   SmallString<128> RelativePathName;
299e3b55780SDimitry Andric   if (OptionalFileEntryRef File =
30048675466SDimitry Andric           findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
301551c6985SDimitry Andric     if (Header.IsUmbrella) {
302b60736ecSDimitry Andric       const DirectoryEntry *UmbrellaDir = &File->getDir().getDirEntry();
303551c6985SDimitry Andric       if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
304551c6985SDimitry Andric         Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
305551c6985SDimitry Andric           << UmbrellaMod->getFullModuleName();
306551c6985SDimitry Andric       else
307551c6985SDimitry Andric         // Record this umbrella header.
3087fa27ce4SDimitry Andric         setUmbrellaHeaderAsWritten(Mod, *File, Header.FileName,
3097fa27ce4SDimitry Andric                                    RelativePathName.str());
310551c6985SDimitry Andric     } else {
3114df029ccSDimitry Andric       Module::Header H = {Header.FileName, std::string(RelativePathName),
312344a3780SDimitry Andric                           *File};
313551c6985SDimitry Andric       addHeader(Mod, H, headerKindToRole(Header.Kind));
314551c6985SDimitry Andric     }
315551c6985SDimitry Andric   } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
316551c6985SDimitry Andric     // There's a builtin header but no corresponding on-disk header. Assume
317551c6985SDimitry Andric     // this was supposed to modularize the builtin header alone.
318551c6985SDimitry Andric   } else if (Header.Kind == Module::HK_Excluded) {
319551c6985SDimitry Andric     // Ignore missing excluded header files. They're optional anyway.
320551c6985SDimitry Andric   } else {
321551c6985SDimitry Andric     // If we find a module that has a missing header, we mark this module as
322551c6985SDimitry Andric     // unavailable and store the header directive for displaying diagnostics.
323551c6985SDimitry Andric     Mod->MissingHeaders.push_back(Header);
324551c6985SDimitry Andric     // A missing header with stat information doesn't make the module
325551c6985SDimitry Andric     // unavailable; this keeps our behavior consistent as headers are lazily
326551c6985SDimitry Andric     // resolved. (Such a module still can't be built though, except from
327551c6985SDimitry Andric     // preprocessed source.)
328551c6985SDimitry Andric     if (!Header.Size && !Header.ModTime)
329cfca06d7SDimitry Andric       Mod->markUnavailable(/*Unimportable=*/false);
330551c6985SDimitry Andric   }
331551c6985SDimitry Andric }
332551c6985SDimitry Andric 
resolveAsBuiltinHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header)333551c6985SDimitry Andric bool ModuleMap::resolveAsBuiltinHeader(
334551c6985SDimitry Andric     Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
335551c6985SDimitry Andric   if (Header.Kind == Module::HK_Excluded ||
336551c6985SDimitry Andric       llvm::sys::path::is_absolute(Header.FileName) ||
337551c6985SDimitry Andric       Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
338551c6985SDimitry Andric       !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
339b1c73532SDimitry Andric       !LangOpts.BuiltinHeadersInSystemModules || !isBuiltinHeaderName(Header.FileName))
340551c6985SDimitry Andric     return false;
341b5aee35cSDimitry Andric 
342b5aee35cSDimitry Andric   // This is a system module with a top-level header. This header
343b5aee35cSDimitry Andric   // may have a counterpart (or replacement) in the set of headers
344b5aee35cSDimitry Andric   // supplied by Clang. Find that builtin header.
345551c6985SDimitry Andric   SmallString<128> Path;
346551c6985SDimitry Andric   llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
347e3b55780SDimitry Andric   auto File = SourceMgr.getFileManager().getOptionalFileRef(Path);
348551c6985SDimitry Andric   if (!File)
349551c6985SDimitry Andric     return false;
350551c6985SDimitry Andric 
351b1c73532SDimitry Andric   Module::Header H = {Header.FileName, Header.FileName, *File};
352551c6985SDimitry Andric   auto Role = headerKindToRole(Header.Kind);
353551c6985SDimitry Andric   addHeader(Mod, H, Role);
354551c6985SDimitry Andric   return true;
355b5aee35cSDimitry Andric }
356b5aee35cSDimitry Andric 
ModuleMap(SourceManager & SourceMgr,DiagnosticsEngine & Diags,const LangOptions & LangOpts,const TargetInfo * Target,HeaderSearch & HeaderInfo)3579f4dbff6SDimitry Andric ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
358809500fcSDimitry Andric                      const LangOptions &LangOpts, const TargetInfo *Target,
359809500fcSDimitry Andric                      HeaderSearch &HeaderInfo)
3609f4dbff6SDimitry Andric     : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
361461a67faSDimitry Andric       HeaderInfo(HeaderInfo) {
3625e20cdd8SDimitry Andric   MMapLangOpts.LineComment = true;
3635e20cdd8SDimitry Andric }
364dbe13110SDimitry Andric 
~ModuleMap()365dbe13110SDimitry Andric ModuleMap::~ModuleMap() {
3662b6b257fSDimitry Andric   for (auto &M : Modules)
3672b6b257fSDimitry Andric     delete M.getValue();
36848675466SDimitry Andric   for (auto *M : ShadowModules)
36948675466SDimitry Andric     delete M;
370dbe13110SDimitry Andric }
371dbe13110SDimitry Andric 
setTarget(const TargetInfo & Target)372dbe13110SDimitry Andric void ModuleMap::setTarget(const TargetInfo &Target) {
373dbe13110SDimitry Andric   assert((!this->Target || this->Target == &Target) &&
374dbe13110SDimitry Andric          "Improper target override");
375dbe13110SDimitry Andric   this->Target = &Target;
376dbe13110SDimitry Andric }
377dbe13110SDimitry Andric 
37848675466SDimitry Andric /// "Sanitize" a filename so that it can be used as an identifier.
sanitizeFilenameAsIdentifier(StringRef Name,SmallVectorImpl<char> & Buffer)37913cc256eSDimitry Andric static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
38013cc256eSDimitry Andric                                               SmallVectorImpl<char> &Buffer) {
38113cc256eSDimitry Andric   if (Name.empty())
38213cc256eSDimitry Andric     return Name;
38313cc256eSDimitry Andric 
384c0981da4SDimitry Andric   if (!isValidAsciiIdentifier(Name)) {
38513cc256eSDimitry Andric     // If we don't already have something with the form of an identifier,
38613cc256eSDimitry Andric     // create a buffer with the sanitized name.
38713cc256eSDimitry Andric     Buffer.clear();
388809500fcSDimitry Andric     if (isDigit(Name[0]))
38913cc256eSDimitry Andric       Buffer.push_back('_');
39013cc256eSDimitry Andric     Buffer.reserve(Buffer.size() + Name.size());
39113cc256eSDimitry Andric     for (unsigned I = 0, N = Name.size(); I != N; ++I) {
392c0981da4SDimitry Andric       if (isAsciiIdentifierContinue(Name[I]))
39313cc256eSDimitry Andric         Buffer.push_back(Name[I]);
39413cc256eSDimitry Andric       else
39513cc256eSDimitry Andric         Buffer.push_back('_');
39613cc256eSDimitry Andric     }
39713cc256eSDimitry Andric 
39813cc256eSDimitry Andric     Name = StringRef(Buffer.data(), Buffer.size());
39913cc256eSDimitry Andric   }
40013cc256eSDimitry Andric 
40113cc256eSDimitry Andric   while (llvm::StringSwitch<bool>(Name)
40213cc256eSDimitry Andric #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
40313cc256eSDimitry Andric #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
40413cc256eSDimitry Andric #include "clang/Basic/TokenKinds.def"
40513cc256eSDimitry Andric            .Default(false)) {
40613cc256eSDimitry Andric     if (Name.data() != Buffer.data())
40713cc256eSDimitry Andric       Buffer.append(Name.begin(), Name.end());
40813cc256eSDimitry Andric     Buffer.push_back('_');
40913cc256eSDimitry Andric     Name = StringRef(Buffer.data(), Buffer.size());
41013cc256eSDimitry Andric   }
41113cc256eSDimitry Andric 
41213cc256eSDimitry Andric   return Name;
41313cc256eSDimitry Andric }
41413cc256eSDimitry Andric 
isBuiltinHeader(FileEntryRef File)415b1c73532SDimitry Andric bool ModuleMap::isBuiltinHeader(FileEntryRef File) {
416b1c73532SDimitry Andric   return File.getDir() == BuiltinIncludeDir && LangOpts.BuiltinHeadersInSystemModules &&
417b1c73532SDimitry Andric          isBuiltinHeaderName(llvm::sys::path::filename(File.getName()));
4186a037251SDimitry Andric }
4196a037251SDimitry Andric 
shouldImportRelativeToBuiltinIncludeDir(StringRef FileName,Module * Module) const420b1c73532SDimitry Andric bool ModuleMap::shouldImportRelativeToBuiltinIncludeDir(StringRef FileName,
421b1c73532SDimitry Andric                                                         Module *Module) const {
422b1c73532SDimitry Andric   return LangOpts.BuiltinHeadersInSystemModules && BuiltinIncludeDir &&
423b1c73532SDimitry Andric          Module->IsSystem && !Module->isPartOfFramework() &&
424b1c73532SDimitry Andric          isBuiltinHeaderName(FileName);
425cfca06d7SDimitry Andric }
426cfca06d7SDimitry Andric 
findKnownHeader(FileEntryRef File)427b1c73532SDimitry Andric ModuleMap::HeadersMap::iterator ModuleMap::findKnownHeader(FileEntryRef File) {
428551c6985SDimitry Andric   resolveHeaderDirectives(File);
42913cc256eSDimitry Andric   HeadersMap::iterator Known = Headers.find(File);
4302e645aa5SDimitry Andric   if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
431cfca06d7SDimitry Andric       Known == Headers.end() && ModuleMap::isBuiltinHeader(File)) {
432bfef3995SDimitry Andric     HeaderInfo.loadTopLevelSystemModules();
4339f4dbff6SDimitry Andric     return Headers.find(File);
4349f4dbff6SDimitry Andric   }
4359f4dbff6SDimitry Andric   return Known;
4366a037251SDimitry Andric }
4376a037251SDimitry Andric 
findHeaderInUmbrellaDirs(FileEntryRef File,SmallVectorImpl<DirectoryEntryRef> & IntermediateDirs)4387fa27ce4SDimitry Andric ModuleMap::KnownHeader ModuleMap::findHeaderInUmbrellaDirs(
4397fa27ce4SDimitry Andric     FileEntryRef File, SmallVectorImpl<DirectoryEntryRef> &IntermediateDirs) {
4402e645aa5SDimitry Andric   if (UmbrellaDirs.empty())
441461a67faSDimitry Andric     return {};
4422e645aa5SDimitry Andric 
4437fa27ce4SDimitry Andric   OptionalDirectoryEntryRef Dir = File.getDir();
444809500fcSDimitry Andric 
445809500fcSDimitry Andric   // Note: as an egregious but useful hack we use the real path here, because
446809500fcSDimitry Andric   // frameworks moving from top-level frameworks to embedded frameworks tend
447809500fcSDimitry Andric   // to be symlinked from the top-level location to the embedded location,
448809500fcSDimitry Andric   // and we need to resolve lookups as if we had found the embedded location.
4497fa27ce4SDimitry Andric   StringRef DirName = SourceMgr.getFileManager().getCanonicalName(*Dir);
450dbe13110SDimitry Andric 
451dbe13110SDimitry Andric   // Keep walking up the directory hierarchy, looking for a directory with
452dbe13110SDimitry Andric   // an umbrella header.
453dbe13110SDimitry Andric   do {
4547fa27ce4SDimitry Andric     auto KnownDir = UmbrellaDirs.find(*Dir);
4559f4dbff6SDimitry Andric     if (KnownDir != UmbrellaDirs.end())
4569f4dbff6SDimitry Andric       return KnownHeader(KnownDir->second, NormalHeader);
4579f4dbff6SDimitry Andric 
4587fa27ce4SDimitry Andric     IntermediateDirs.push_back(*Dir);
4599f4dbff6SDimitry Andric 
4609f4dbff6SDimitry Andric     // Retrieve our parent path.
4619f4dbff6SDimitry Andric     DirName = llvm::sys::path::parent_path(DirName);
4629f4dbff6SDimitry Andric     if (DirName.empty())
4639f4dbff6SDimitry Andric       break;
4649f4dbff6SDimitry Andric 
4659f4dbff6SDimitry Andric     // Resolve the parent path to a directory entry.
4667fa27ce4SDimitry Andric     Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
4679f4dbff6SDimitry Andric   } while (Dir);
468461a67faSDimitry Andric   return {};
4699f4dbff6SDimitry Andric }
4709f4dbff6SDimitry Andric 
violatesPrivateInclude(Module * RequestingModule,const FileEntry * IncFileEnt,ModuleMap::KnownHeader Header)4719f4dbff6SDimitry Andric static bool violatesPrivateInclude(Module *RequestingModule,
4729f4dbff6SDimitry Andric                                    const FileEntry *IncFileEnt,
4732b6b257fSDimitry Andric                                    ModuleMap::KnownHeader Header) {
4749f4dbff6SDimitry Andric #ifndef NDEBUG
4752b6b257fSDimitry Andric   if (Header.getRole() & ModuleMap::PrivateHeader) {
4769f4dbff6SDimitry Andric     // Check for consistency between the module header role
4779f4dbff6SDimitry Andric     // as obtained from the lookup and as obtained from the module.
4789f4dbff6SDimitry Andric     // This check is not cheap, so enable it only for debugging.
47906d4ba38SDimitry Andric     bool IsPrivate = false;
4805e20cdd8SDimitry Andric     SmallVectorImpl<Module::Header> *HeaderList[] = {
4812b6b257fSDimitry Andric         &Header.getModule()->Headers[Module::HK_Private],
4822b6b257fSDimitry Andric         &Header.getModule()->Headers[Module::HK_PrivateTextual]};
4835e20cdd8SDimitry Andric     for (auto *Hs : HeaderList)
4844b4fe385SDimitry Andric       IsPrivate |= llvm::any_of(
4854b4fe385SDimitry Andric           *Hs, [&](const Module::Header &H) { return H.Entry == IncFileEnt; });
4862b6b257fSDimitry Andric     assert(IsPrivate && "inconsistent headers and roles");
4875e20cdd8SDimitry Andric   }
4889f4dbff6SDimitry Andric #endif
4892b6b257fSDimitry Andric   return !Header.isAccessibleFrom(RequestingModule);
4909f4dbff6SDimitry Andric }
4919f4dbff6SDimitry Andric 
getTopLevelOrNull(Module * M)4929f4dbff6SDimitry Andric static Module *getTopLevelOrNull(Module *M) {
4939f4dbff6SDimitry Andric   return M ? M->getTopLevelModule() : nullptr;
4949f4dbff6SDimitry Andric }
4959f4dbff6SDimitry Andric 
diagnoseHeaderInclusion(Module * RequestingModule,bool RequestingModuleIsModuleInterface,SourceLocation FilenameLoc,StringRef Filename,FileEntryRef File)4969f4dbff6SDimitry Andric void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
4972b6b257fSDimitry Andric                                         bool RequestingModuleIsModuleInterface,
4989f4dbff6SDimitry Andric                                         SourceLocation FilenameLoc,
499145449b1SDimitry Andric                                         StringRef Filename, FileEntryRef File) {
5009f4dbff6SDimitry Andric   // No errors for indirect modules. This may be a bit of a problem for modules
5019f4dbff6SDimitry Andric   // with no source files.
5029f4dbff6SDimitry Andric   if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
5039f4dbff6SDimitry Andric     return;
5049f4dbff6SDimitry Andric 
505551c6985SDimitry Andric   if (RequestingModule) {
5069f4dbff6SDimitry Andric     resolveUses(RequestingModule, /*Complain=*/false);
507e3b55780SDimitry Andric     resolveHeaderDirectives(RequestingModule, /*File=*/std::nullopt);
508551c6985SDimitry Andric   }
5099f4dbff6SDimitry Andric 
5109f4dbff6SDimitry Andric   bool Excluded = false;
5119f4dbff6SDimitry Andric   Module *Private = nullptr;
5129f4dbff6SDimitry Andric   Module *NotUsed = nullptr;
5139f4dbff6SDimitry Andric 
5149f4dbff6SDimitry Andric   HeadersMap::iterator Known = findKnownHeader(File);
5159f4dbff6SDimitry Andric   if (Known != Headers.end()) {
5169f4dbff6SDimitry Andric     for (const KnownHeader &Header : Known->second) {
517e3b55780SDimitry Andric       // Excluded headers don't really belong to a module.
518e3b55780SDimitry Andric       if (Header.getRole() == ModuleMap::ExcludedHeader) {
519e3b55780SDimitry Andric         Excluded = true;
520e3b55780SDimitry Andric         continue;
521e3b55780SDimitry Andric       }
522e3b55780SDimitry Andric 
5239f4dbff6SDimitry Andric       // Remember private headers for later printing of a diagnostic.
5242b6b257fSDimitry Andric       if (violatesPrivateInclude(RequestingModule, File, Header)) {
5259f4dbff6SDimitry Andric         Private = Header.getModule();
5269f4dbff6SDimitry Andric         continue;
5279f4dbff6SDimitry Andric       }
5289f4dbff6SDimitry Andric 
5299f4dbff6SDimitry Andric       // If uses need to be specified explicitly, we are only allowed to return
5309f4dbff6SDimitry Andric       // modules that are explicitly used by the requesting module.
5319f4dbff6SDimitry Andric       if (RequestingModule && LangOpts.ModulesDeclUse &&
5325e20cdd8SDimitry Andric           !RequestingModule->directlyUses(Header.getModule())) {
5339f4dbff6SDimitry Andric         NotUsed = Header.getModule();
5349f4dbff6SDimitry Andric         continue;
5359f4dbff6SDimitry Andric       }
5369f4dbff6SDimitry Andric 
5379f4dbff6SDimitry Andric       // We have found a module that we can happily use.
5389f4dbff6SDimitry Andric       return;
5399f4dbff6SDimitry Andric     }
54006d4ba38SDimitry Andric 
54106d4ba38SDimitry Andric     Excluded = true;
5429f4dbff6SDimitry Andric   }
5439f4dbff6SDimitry Andric 
5449f4dbff6SDimitry Andric   // We have found a header, but it is private.
5459f4dbff6SDimitry Andric   if (Private) {
5465e20cdd8SDimitry Andric     Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
5479f4dbff6SDimitry Andric         << Filename;
5489f4dbff6SDimitry Andric     return;
5499f4dbff6SDimitry Andric   }
5509f4dbff6SDimitry Andric 
5519f4dbff6SDimitry Andric   // We have found a module, but we don't use it.
5529f4dbff6SDimitry Andric   if (NotUsed) {
5537fa27ce4SDimitry Andric     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module_indirect)
5547fa27ce4SDimitry Andric         << RequestingModule->getTopLevelModule()->Name << Filename
5557fa27ce4SDimitry Andric         << NotUsed->Name;
5569f4dbff6SDimitry Andric     return;
5579f4dbff6SDimitry Andric   }
5589f4dbff6SDimitry Andric 
5599f4dbff6SDimitry Andric   if (Excluded || isHeaderInUmbrellaDirs(File))
5609f4dbff6SDimitry Andric     return;
5619f4dbff6SDimitry Andric 
5629f4dbff6SDimitry Andric   // At this point, only non-modular includes remain.
5639f4dbff6SDimitry Andric 
564676fbe81SDimitry Andric   if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
5655e20cdd8SDimitry Andric     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
56648675466SDimitry Andric         << RequestingModule->getTopLevelModule()->Name << Filename;
567bab175ecSDimitry Andric   } else if (RequestingModule && RequestingModuleIsModuleInterface &&
568bab175ecSDimitry Andric              LangOpts.isCompilingModule()) {
569bab175ecSDimitry Andric     // Do not diagnose when we are not compiling a module.
5709f4dbff6SDimitry Andric     diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
5719f4dbff6SDimitry Andric         diag::warn_non_modular_include_in_framework_module :
5729f4dbff6SDimitry Andric         diag::warn_non_modular_include_in_module;
573bab175ecSDimitry Andric     Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
574145449b1SDimitry Andric         << File.getName();
5759f4dbff6SDimitry Andric   }
5769f4dbff6SDimitry Andric }
5779f4dbff6SDimitry Andric 
isBetterKnownHeader(const ModuleMap::KnownHeader & New,const ModuleMap::KnownHeader & Old)5785e20cdd8SDimitry Andric static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
5795e20cdd8SDimitry Andric                                 const ModuleMap::KnownHeader &Old) {
58045b53394SDimitry Andric   // Prefer available modules.
581cfca06d7SDimitry Andric   // FIXME: Considering whether the module is available rather than merely
582cfca06d7SDimitry Andric   // importable is non-hermetic and can result in surprising behavior for
583cfca06d7SDimitry Andric   // prebuilt modules. Consider only checking for importability here.
58445b53394SDimitry Andric   if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
58545b53394SDimitry Andric     return true;
58645b53394SDimitry Andric 
5875e20cdd8SDimitry Andric   // Prefer a public header over a private header.
5885e20cdd8SDimitry Andric   if ((New.getRole() & ModuleMap::PrivateHeader) !=
5895e20cdd8SDimitry Andric       (Old.getRole() & ModuleMap::PrivateHeader))
5905e20cdd8SDimitry Andric     return !(New.getRole() & ModuleMap::PrivateHeader);
5915e20cdd8SDimitry Andric 
5925e20cdd8SDimitry Andric   // Prefer a non-textual header over a textual header.
5935e20cdd8SDimitry Andric   if ((New.getRole() & ModuleMap::TextualHeader) !=
5945e20cdd8SDimitry Andric       (Old.getRole() & ModuleMap::TextualHeader))
5955e20cdd8SDimitry Andric     return !(New.getRole() & ModuleMap::TextualHeader);
5965e20cdd8SDimitry Andric 
597e3b55780SDimitry Andric   // Prefer a non-excluded header over an excluded header.
598e3b55780SDimitry Andric   if ((New.getRole() == ModuleMap::ExcludedHeader) !=
599e3b55780SDimitry Andric       (Old.getRole() == ModuleMap::ExcludedHeader))
600e3b55780SDimitry Andric     return New.getRole() != ModuleMap::ExcludedHeader;
601e3b55780SDimitry Andric 
6025e20cdd8SDimitry Andric   // Don't have a reason to choose between these. Just keep the first one.
6035e20cdd8SDimitry Andric   return false;
6045e20cdd8SDimitry Andric }
6055e20cdd8SDimitry Andric 
findModuleForHeader(FileEntryRef File,bool AllowTextual,bool AllowExcluded)6067fa27ce4SDimitry Andric ModuleMap::KnownHeader ModuleMap::findModuleForHeader(FileEntryRef File,
607e3b55780SDimitry Andric                                                       bool AllowTextual,
608e3b55780SDimitry Andric                                                       bool AllowExcluded) {
60906d4ba38SDimitry Andric   auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
610bab175ecSDimitry Andric     if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
611461a67faSDimitry Andric       return {};
61206d4ba38SDimitry Andric     return R;
61306d4ba38SDimitry Andric   };
61406d4ba38SDimitry Andric 
6152e645aa5SDimitry Andric   HeadersMap::iterator Known = findKnownHeader(File);
6169f4dbff6SDimitry Andric   if (Known != Headers.end()) {
61706d4ba38SDimitry Andric     ModuleMap::KnownHeader Result;
6189f4dbff6SDimitry Andric     // Iterate over all modules that 'File' is part of to find the best fit.
6192e645aa5SDimitry Andric     for (KnownHeader &H : Known->second) {
620e3b55780SDimitry Andric       // Cannot use a module if the header is excluded in it.
621e3b55780SDimitry Andric       if (!AllowExcluded && H.getRole() == ModuleMap::ExcludedHeader)
622e3b55780SDimitry Andric         continue;
6232b6b257fSDimitry Andric       // Prefer a header from the source module over all others.
6242b6b257fSDimitry Andric       if (H.getModule()->getTopLevelModule() == SourceModule)
625c192b3dcSDimitry Andric         return MakeResult(H);
6262e645aa5SDimitry Andric       if (!Result || isBetterKnownHeader(H, Result))
6272e645aa5SDimitry Andric         Result = H;
6289f4dbff6SDimitry Andric     }
62906d4ba38SDimitry Andric     return MakeResult(Result);
6309f4dbff6SDimitry Andric   }
6319f4dbff6SDimitry Andric 
63245b53394SDimitry Andric   return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
63345b53394SDimitry Andric }
63445b53394SDimitry Andric 
63545b53394SDimitry Andric ModuleMap::KnownHeader
findOrCreateModuleForHeaderInUmbrellaDir(FileEntryRef File)6367fa27ce4SDimitry Andric ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(FileEntryRef File) {
63745b53394SDimitry Andric   assert(!Headers.count(File) && "already have a module for this header");
63845b53394SDimitry Andric 
6397fa27ce4SDimitry Andric   SmallVector<DirectoryEntryRef, 2> SkippedDirs;
6409f4dbff6SDimitry Andric   KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
6419f4dbff6SDimitry Andric   if (H) {
6429f4dbff6SDimitry Andric     Module *Result = H.getModule();
643dbe13110SDimitry Andric 
644dbe13110SDimitry Andric     // Search up the module stack until we find a module with an umbrella
645dbe13110SDimitry Andric     // directory.
646dbe13110SDimitry Andric     Module *UmbrellaModule = Result;
6477fa27ce4SDimitry Andric     while (!UmbrellaModule->getEffectiveUmbrellaDir() && UmbrellaModule->Parent)
648dbe13110SDimitry Andric       UmbrellaModule = UmbrellaModule->Parent;
649dbe13110SDimitry Andric 
650dbe13110SDimitry Andric     if (UmbrellaModule->InferSubmodules) {
651ac9a064cSDimitry Andric       FileID UmbrellaModuleMap = getModuleMapFileIDForUniquing(UmbrellaModule);
65206d4ba38SDimitry Andric 
653dbe13110SDimitry Andric       // Infer submodules for each of the directories we found between
654dbe13110SDimitry Andric       // the directory of the umbrella header and the directory where
655dbe13110SDimitry Andric       // the actual header is located.
656dbe13110SDimitry Andric       bool Explicit = UmbrellaModule->InferExplicitSubmodules;
657dbe13110SDimitry Andric 
6587fa27ce4SDimitry Andric       for (DirectoryEntryRef SkippedDir : llvm::reverse(SkippedDirs)) {
659dbe13110SDimitry Andric         // Find or create the module that corresponds to this directory name.
66013cc256eSDimitry Andric         SmallString<32> NameBuf;
66113cc256eSDimitry Andric         StringRef Name = sanitizeFilenameAsIdentifier(
6627fa27ce4SDimitry Andric             llvm::sys::path::stem(SkippedDir.getName()), NameBuf);
66306d4ba38SDimitry Andric         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
66406d4ba38SDimitry Andric                                     Explicit).first;
66506d4ba38SDimitry Andric         InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
6669f4dbff6SDimitry Andric         Result->IsInferred = true;
667dbe13110SDimitry Andric 
668dbe13110SDimitry Andric         // Associate the module and the directory.
669c0981da4SDimitry Andric         UmbrellaDirs[SkippedDir] = Result;
670dbe13110SDimitry Andric 
671dbe13110SDimitry Andric         // If inferred submodules export everything they import, add a
672dbe13110SDimitry Andric         // wildcard to the set of exports.
673dbe13110SDimitry Andric         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
6749f4dbff6SDimitry Andric           Result->Exports.push_back(Module::ExportDecl(nullptr, true));
675dbe13110SDimitry Andric       }
676dbe13110SDimitry Andric 
677dbe13110SDimitry Andric       // Infer a submodule with the same name as this header file.
67813cc256eSDimitry Andric       SmallString<32> NameBuf;
67913cc256eSDimitry Andric       StringRef Name = sanitizeFilenameAsIdentifier(
6807fa27ce4SDimitry Andric                          llvm::sys::path::stem(File.getName()), NameBuf);
68106d4ba38SDimitry Andric       Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
68206d4ba38SDimitry Andric                                   Explicit).first;
68306d4ba38SDimitry Andric       InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
6849f4dbff6SDimitry Andric       Result->IsInferred = true;
685809500fcSDimitry Andric       Result->addTopHeader(File);
686dbe13110SDimitry Andric 
687dbe13110SDimitry Andric       // If inferred submodules export everything they import, add a
688dbe13110SDimitry Andric       // wildcard to the set of exports.
689dbe13110SDimitry Andric       if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
6909f4dbff6SDimitry Andric         Result->Exports.push_back(Module::ExportDecl(nullptr, true));
691dbe13110SDimitry Andric     } else {
692dbe13110SDimitry Andric       // Record each of the directories we stepped through as being part of
693dbe13110SDimitry Andric       // the module we found, since the umbrella header covers them all.
694dbe13110SDimitry Andric       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
695dbe13110SDimitry Andric         UmbrellaDirs[SkippedDirs[I]] = Result;
696dbe13110SDimitry Andric     }
697dbe13110SDimitry Andric 
69845b53394SDimitry Andric     KnownHeader Header(Result, NormalHeader);
69945b53394SDimitry Andric     Headers[File].push_back(Header);
70045b53394SDimitry Andric     return Header;
701dbe13110SDimitry Andric   }
702dbe13110SDimitry Andric 
703461a67faSDimitry Andric   return {};
704dbe13110SDimitry Andric }
705dbe13110SDimitry Andric 
70645b53394SDimitry Andric ArrayRef<ModuleMap::KnownHeader>
findAllModulesForHeader(FileEntryRef File)7077fa27ce4SDimitry Andric ModuleMap::findAllModulesForHeader(FileEntryRef File) {
708cfca06d7SDimitry Andric   HeadersMap::iterator Known = findKnownHeader(File);
709cfca06d7SDimitry Andric   if (Known != Headers.end())
710cfca06d7SDimitry Andric     return Known->second;
711cfca06d7SDimitry Andric 
712cfca06d7SDimitry Andric   if (findOrCreateModuleForHeaderInUmbrellaDir(File))
713cfca06d7SDimitry Andric     return Headers.find(File)->second;
714cfca06d7SDimitry Andric 
715e3b55780SDimitry Andric   return std::nullopt;
716cfca06d7SDimitry Andric }
717cfca06d7SDimitry Andric 
718cfca06d7SDimitry Andric ArrayRef<ModuleMap::KnownHeader>
findResolvedModulesForHeader(FileEntryRef File) const719b1c73532SDimitry Andric ModuleMap::findResolvedModulesForHeader(FileEntryRef File) const {
720cfca06d7SDimitry Andric   // FIXME: Is this necessary?
721551c6985SDimitry Andric   resolveHeaderDirectives(File);
72245b53394SDimitry Andric   auto It = Headers.find(File);
72345b53394SDimitry Andric   if (It == Headers.end())
724e3b55780SDimitry Andric     return std::nullopt;
72545b53394SDimitry Andric   return It->second;
72645b53394SDimitry Andric }
72745b53394SDimitry Andric 
isHeaderInUnavailableModule(FileEntryRef Header) const7287fa27ce4SDimitry Andric bool ModuleMap::isHeaderInUnavailableModule(FileEntryRef Header) const {
7299f4dbff6SDimitry Andric   return isHeaderUnavailableInModule(Header, nullptr);
7309f4dbff6SDimitry Andric }
7319f4dbff6SDimitry Andric 
isHeaderUnavailableInModule(FileEntryRef Header,const Module * RequestingModule) const7327fa27ce4SDimitry Andric bool ModuleMap::isHeaderUnavailableInModule(
7337fa27ce4SDimitry Andric     FileEntryRef Header, const Module *RequestingModule) const {
734551c6985SDimitry Andric   resolveHeaderDirectives(Header);
735809500fcSDimitry Andric   HeadersMap::const_iterator Known = Headers.find(Header);
736bfef3995SDimitry Andric   if (Known != Headers.end()) {
737bfef3995SDimitry Andric     for (SmallVectorImpl<KnownHeader>::const_iterator
738bfef3995SDimitry Andric              I = Known->second.begin(),
739bfef3995SDimitry Andric              E = Known->second.end();
740bfef3995SDimitry Andric          I != E; ++I) {
741d2e0a8ddSDimitry Andric 
742e3b55780SDimitry Andric       if (I->getRole() == ModuleMap::ExcludedHeader)
743e3b55780SDimitry Andric         continue;
744e3b55780SDimitry Andric 
745d2e0a8ddSDimitry Andric       if (I->isAvailable() &&
746d2e0a8ddSDimitry Andric           (!RequestingModule ||
747d2e0a8ddSDimitry Andric            I->getModule()->isSubModuleOf(RequestingModule))) {
748d2e0a8ddSDimitry Andric         // When no requesting module is available, the caller is looking if a
749d2e0a8ddSDimitry Andric         // header is part a module by only looking into the module map. This is
750d2e0a8ddSDimitry Andric         // done by warn_uncovered_module_header checks; don't consider textual
751d2e0a8ddSDimitry Andric         // headers part of it in this mode, otherwise we get misleading warnings
752d2e0a8ddSDimitry Andric         // that a umbrella header is not including a textual header.
753d2e0a8ddSDimitry Andric         if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
754d2e0a8ddSDimitry Andric           continue;
755bfef3995SDimitry Andric         return false;
756bfef3995SDimitry Andric       }
757d2e0a8ddSDimitry Andric     }
758bfef3995SDimitry Andric     return true;
759bfef3995SDimitry Andric   }
760dbe13110SDimitry Andric 
7617fa27ce4SDimitry Andric   OptionalDirectoryEntryRef Dir = Header.getDir();
7627fa27ce4SDimitry Andric   SmallVector<DirectoryEntryRef, 2> SkippedDirs;
763dbe13110SDimitry Andric   StringRef DirName = Dir->getName();
764dbe13110SDimitry Andric 
7659f4dbff6SDimitry Andric   auto IsUnavailable = [&](const Module *M) {
7669f4dbff6SDimitry Andric     return !M->isAvailable() && (!RequestingModule ||
7679f4dbff6SDimitry Andric                                  M->isSubModuleOf(RequestingModule));
7689f4dbff6SDimitry Andric   };
7699f4dbff6SDimitry Andric 
770dbe13110SDimitry Andric   // Keep walking up the directory hierarchy, looking for a directory with
771dbe13110SDimitry Andric   // an umbrella header.
772dbe13110SDimitry Andric   do {
7737fa27ce4SDimitry Andric     auto KnownDir = UmbrellaDirs.find(*Dir);
774dbe13110SDimitry Andric     if (KnownDir != UmbrellaDirs.end()) {
775dbe13110SDimitry Andric       Module *Found = KnownDir->second;
7769f4dbff6SDimitry Andric       if (IsUnavailable(Found))
777dbe13110SDimitry Andric         return true;
778dbe13110SDimitry Andric 
779dbe13110SDimitry Andric       // Search up the module stack until we find a module with an umbrella
780dbe13110SDimitry Andric       // directory.
781dbe13110SDimitry Andric       Module *UmbrellaModule = Found;
7827fa27ce4SDimitry Andric       while (!UmbrellaModule->getEffectiveUmbrellaDir() &&
7837fa27ce4SDimitry Andric              UmbrellaModule->Parent)
784dbe13110SDimitry Andric         UmbrellaModule = UmbrellaModule->Parent;
785dbe13110SDimitry Andric 
786dbe13110SDimitry Andric       if (UmbrellaModule->InferSubmodules) {
7877fa27ce4SDimitry Andric         for (DirectoryEntryRef SkippedDir : llvm::reverse(SkippedDirs)) {
788dbe13110SDimitry Andric           // Find or create the module that corresponds to this directory name.
78913cc256eSDimitry Andric           SmallString<32> NameBuf;
79013cc256eSDimitry Andric           StringRef Name = sanitizeFilenameAsIdentifier(
7917fa27ce4SDimitry Andric               llvm::sys::path::stem(SkippedDir.getName()), NameBuf);
792dbe13110SDimitry Andric           Found = lookupModuleQualified(Name, Found);
793dbe13110SDimitry Andric           if (!Found)
794dbe13110SDimitry Andric             return false;
7959f4dbff6SDimitry Andric           if (IsUnavailable(Found))
796dbe13110SDimitry Andric             return true;
797dbe13110SDimitry Andric         }
798dbe13110SDimitry Andric 
799dbe13110SDimitry Andric         // Infer a submodule with the same name as this header file.
80013cc256eSDimitry Andric         SmallString<32> NameBuf;
80113cc256eSDimitry Andric         StringRef Name = sanitizeFilenameAsIdentifier(
8027fa27ce4SDimitry Andric                            llvm::sys::path::stem(Header.getName()),
80313cc256eSDimitry Andric                            NameBuf);
804dbe13110SDimitry Andric         Found = lookupModuleQualified(Name, Found);
805dbe13110SDimitry Andric         if (!Found)
806dbe13110SDimitry Andric           return false;
807dbe13110SDimitry Andric       }
808dbe13110SDimitry Andric 
8099f4dbff6SDimitry Andric       return IsUnavailable(Found);
810dbe13110SDimitry Andric     }
811dbe13110SDimitry Andric 
8127fa27ce4SDimitry Andric     SkippedDirs.push_back(*Dir);
813dbe13110SDimitry Andric 
814dbe13110SDimitry Andric     // Retrieve our parent path.
815dbe13110SDimitry Andric     DirName = llvm::sys::path::parent_path(DirName);
816dbe13110SDimitry Andric     if (DirName.empty())
817dbe13110SDimitry Andric       break;
818dbe13110SDimitry Andric 
819dbe13110SDimitry Andric     // Resolve the parent path to a directory entry.
8207fa27ce4SDimitry Andric     Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
821dbe13110SDimitry Andric   } while (Dir);
822dbe13110SDimitry Andric 
823dbe13110SDimitry Andric   return false;
824dbe13110SDimitry Andric }
825dbe13110SDimitry Andric 
findModule(StringRef Name) const826809500fcSDimitry Andric Module *ModuleMap::findModule(StringRef Name) const {
827809500fcSDimitry Andric   llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
828dbe13110SDimitry Andric   if (Known != Modules.end())
829dbe13110SDimitry Andric     return Known->getValue();
830dbe13110SDimitry Andric 
8319f4dbff6SDimitry Andric   return nullptr;
832dbe13110SDimitry Andric }
833dbe13110SDimitry Andric 
lookupModuleUnqualified(StringRef Name,Module * Context) const834809500fcSDimitry Andric Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
835809500fcSDimitry Andric                                            Module *Context) const {
836dbe13110SDimitry Andric   for(; Context; Context = Context->Parent) {
837dbe13110SDimitry Andric     if (Module *Sub = lookupModuleQualified(Name, Context))
838dbe13110SDimitry Andric       return Sub;
839dbe13110SDimitry Andric   }
840dbe13110SDimitry Andric 
841dbe13110SDimitry Andric   return findModule(Name);
842dbe13110SDimitry Andric }
843dbe13110SDimitry Andric 
lookupModuleQualified(StringRef Name,Module * Context) const844809500fcSDimitry Andric Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
845dbe13110SDimitry Andric   if (!Context)
846dbe13110SDimitry Andric     return findModule(Name);
847dbe13110SDimitry Andric 
848dbe13110SDimitry Andric   return Context->findSubmodule(Name);
849dbe13110SDimitry Andric }
850dbe13110SDimitry Andric 
findOrCreateModule(StringRef Name,Module * Parent,bool IsFramework,bool IsExplicit)8517442d6faSDimitry Andric std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
8527442d6faSDimitry Andric                                                         Module *Parent,
8537442d6faSDimitry Andric                                                         bool IsFramework,
854dbe13110SDimitry Andric                                                         bool IsExplicit) {
855dbe13110SDimitry Andric   // Try to find an existing module with this name.
856dbe13110SDimitry Andric   if (Module *Sub = lookupModuleQualified(Name, Parent))
857dbe13110SDimitry Andric     return std::make_pair(Sub, false);
858dbe13110SDimitry Andric 
859dbe13110SDimitry Andric   // Create a new module with this name.
8607442d6faSDimitry Andric   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
8617442d6faSDimitry Andric                               IsExplicit, NumCreatedModules++);
862bfef3995SDimitry Andric   if (!Parent) {
8632b6b257fSDimitry Andric     if (LangOpts.CurrentModule == Name)
8642b6b257fSDimitry Andric       SourceModule = Result;
865dbe13110SDimitry Andric     Modules[Name] = Result;
86648675466SDimitry Andric     ModuleScopeIDs[Result] = CurrentModuleScopeID;
867bfef3995SDimitry Andric   }
868dbe13110SDimitry Andric   return std::make_pair(Result, true);
869dbe13110SDimitry Andric }
870dbe13110SDimitry Andric 
createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,Module * Parent)87177fc4c14SDimitry Andric Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
87277fc4c14SDimitry Andric                                                            Module *Parent) {
87377fc4c14SDimitry Andric   auto *Result = new Module("<global>", Loc, Parent, /*IsFramework*/ false,
87477fc4c14SDimitry Andric                             /*IsExplicit*/ true, NumCreatedModules++);
8757fa27ce4SDimitry Andric   Result->Kind = Module::ExplicitGlobalModuleFragment;
87677fc4c14SDimitry Andric   // If the created module isn't owned by a parent, send it to PendingSubmodules
87777fc4c14SDimitry Andric   // to wait for its parent.
87877fc4c14SDimitry Andric   if (!Result->Parent)
87977fc4c14SDimitry Andric     PendingSubmodules.emplace_back(Result);
88077fc4c14SDimitry Andric   return Result;
881461a67faSDimitry Andric }
882461a67faSDimitry Andric 
883b1c73532SDimitry Andric Module *
createImplicitGlobalModuleFragmentForModuleUnit(SourceLocation Loc,Module * Parent)884b1c73532SDimitry Andric ModuleMap::createImplicitGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
885b1c73532SDimitry Andric                                                            Module *Parent) {
8867fa27ce4SDimitry Andric   assert(Parent && "We should only create an implicit global module fragment "
8877fa27ce4SDimitry Andric                    "in a module purview");
8887fa27ce4SDimitry Andric   // Note: Here the `IsExplicit` parameter refers to the semantics in clang
8897fa27ce4SDimitry Andric   // modules. All the non-explicit submodules in clang modules will be exported
8907fa27ce4SDimitry Andric   // too. Here we simplify the implementation by using the concept.
891b1c73532SDimitry Andric   auto *Result =
892b1c73532SDimitry Andric       new Module("<implicit global>", Loc, Parent, /*IsFramework=*/false,
893b1c73532SDimitry Andric                  /*IsExplicit=*/false, NumCreatedModules++);
8947fa27ce4SDimitry Andric   Result->Kind = Module::ImplicitGlobalModuleFragment;
8957fa27ce4SDimitry Andric   return Result;
8967fa27ce4SDimitry Andric }
8977fa27ce4SDimitry Andric 
89822989816SDimitry Andric Module *
createPrivateModuleFragmentForInterfaceUnit(Module * Parent,SourceLocation Loc)89922989816SDimitry Andric ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
90022989816SDimitry Andric                                                        SourceLocation Loc) {
90122989816SDimitry Andric   auto *Result =
90222989816SDimitry Andric       new Module("<private>", Loc, Parent, /*IsFramework*/ false,
90322989816SDimitry Andric                  /*IsExplicit*/ true, NumCreatedModules++);
90422989816SDimitry Andric   Result->Kind = Module::PrivateModuleFragment;
90522989816SDimitry Andric   return Result;
90622989816SDimitry Andric }
90722989816SDimitry Andric 
createModuleUnitWithKind(SourceLocation Loc,StringRef Name,Module::ModuleKind Kind)9087fa27ce4SDimitry Andric Module *ModuleMap::createModuleUnitWithKind(SourceLocation Loc, StringRef Name,
9097fa27ce4SDimitry Andric                                             Module::ModuleKind Kind) {
9107fa27ce4SDimitry Andric   auto *Result =
9117fa27ce4SDimitry Andric       new Module(Name, Loc, nullptr, /*IsFramework*/ false,
9127fa27ce4SDimitry Andric                  /*IsExplicit*/ false, NumCreatedModules++);
9137fa27ce4SDimitry Andric   Result->Kind = Kind;
9147fa27ce4SDimitry Andric 
9157fa27ce4SDimitry Andric   // Reparent any current global module fragment as a submodule of this module.
9167fa27ce4SDimitry Andric   for (auto &Submodule : PendingSubmodules) {
9177fa27ce4SDimitry Andric     Submodule->setParent(Result);
9187fa27ce4SDimitry Andric     Submodule.release(); // now owned by parent
9197fa27ce4SDimitry Andric   }
9207fa27ce4SDimitry Andric   PendingSubmodules.clear();
9217fa27ce4SDimitry Andric   return Result;
9227fa27ce4SDimitry Andric }
9237fa27ce4SDimitry Andric 
createModuleForInterfaceUnit(SourceLocation Loc,StringRef Name)924bab175ecSDimitry Andric Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
925e3b55780SDimitry Andric                                                 StringRef Name) {
926bab175ecSDimitry Andric   assert(LangOpts.CurrentModule == Name && "module name mismatch");
927bab175ecSDimitry Andric   assert(!Modules[Name] && "redefining existing module");
928bab175ecSDimitry Andric 
929bab175ecSDimitry Andric   auto *Result =
9307fa27ce4SDimitry Andric       createModuleUnitWithKind(Loc, Name, Module::ModuleInterfaceUnit);
931bab175ecSDimitry Andric   Modules[Name] = SourceModule = Result;
932bab175ecSDimitry Andric 
933bab175ecSDimitry Andric   // Mark the main source file as being within the newly-created module so that
934bab175ecSDimitry Andric   // declarations and macros are properly visibility-restricted to it.
935b1c73532SDimitry Andric   auto MainFile = SourceMgr.getFileEntryRefForID(SourceMgr.getMainFileID());
936bab175ecSDimitry Andric   assert(MainFile && "no input file for module interface");
937b1c73532SDimitry Andric   Headers[*MainFile].push_back(KnownHeader(Result, PrivateHeader));
938bab175ecSDimitry Andric 
939bab175ecSDimitry Andric   return Result;
940bab175ecSDimitry Andric }
941bab175ecSDimitry Andric 
createModuleForImplementationUnit(SourceLocation Loc,StringRef Name)9427fa27ce4SDimitry Andric Module *ModuleMap::createModuleForImplementationUnit(SourceLocation Loc,
9437fa27ce4SDimitry Andric                                                      StringRef Name) {
9447fa27ce4SDimitry Andric   assert(LangOpts.CurrentModule == Name && "module name mismatch");
9457fa27ce4SDimitry Andric   // The interface for this implementation must exist and be loaded.
9467fa27ce4SDimitry Andric   assert(Modules[Name] && Modules[Name]->Kind == Module::ModuleInterfaceUnit &&
9477fa27ce4SDimitry Andric          "creating implementation module without an interface");
9487fa27ce4SDimitry Andric 
9497fa27ce4SDimitry Andric   // Create an entry in the modules map to own the implementation unit module.
9507fa27ce4SDimitry Andric   // User module names must not start with a period (so that this cannot clash
9517fa27ce4SDimitry Andric   // with any legal user-defined module name).
9527fa27ce4SDimitry Andric   StringRef IName = ".ImplementationUnit";
9537fa27ce4SDimitry Andric   assert(!Modules[IName] && "multiple implementation units?");
9547fa27ce4SDimitry Andric 
9557fa27ce4SDimitry Andric   auto *Result =
9567fa27ce4SDimitry Andric       createModuleUnitWithKind(Loc, Name, Module::ModuleImplementationUnit);
9577fa27ce4SDimitry Andric   Modules[IName] = SourceModule = Result;
9587fa27ce4SDimitry Andric 
9597fa27ce4SDimitry Andric   // Check that the main file is present.
9607fa27ce4SDimitry Andric   assert(SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()) &&
9617fa27ce4SDimitry Andric          "no input file for module implementation");
9627fa27ce4SDimitry Andric 
9637fa27ce4SDimitry Andric   return Result;
9647fa27ce4SDimitry Andric }
9657fa27ce4SDimitry Andric 
createHeaderUnit(SourceLocation Loc,StringRef Name,Module::Header H)966145449b1SDimitry Andric Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name,
967145449b1SDimitry Andric                                     Module::Header H) {
968145449b1SDimitry Andric   assert(LangOpts.CurrentModule == Name && "module name mismatch");
969145449b1SDimitry Andric   assert(!Modules[Name] && "redefining existing module");
970145449b1SDimitry Andric 
971145449b1SDimitry Andric   auto *Result = new Module(Name, Loc, nullptr, /*IsFramework*/ false,
972145449b1SDimitry Andric                             /*IsExplicit*/ false, NumCreatedModules++);
973145449b1SDimitry Andric   Result->Kind = Module::ModuleHeaderUnit;
974145449b1SDimitry Andric   Modules[Name] = SourceModule = Result;
975145449b1SDimitry Andric   addHeader(Result, H, NormalHeader);
976145449b1SDimitry Andric   return Result;
977145449b1SDimitry Andric }
978145449b1SDimitry Andric 
97948675466SDimitry Andric /// For a framework module, infer the framework against which we
980809500fcSDimitry Andric /// should link.
inferFrameworkLink(Module * Mod)9817fa27ce4SDimitry Andric static void inferFrameworkLink(Module *Mod) {
982809500fcSDimitry Andric   assert(Mod->IsFramework && "Can only infer linking for framework modules");
983809500fcSDimitry Andric   assert(!Mod->isSubFramework() &&
984809500fcSDimitry Andric          "Can only infer linking for top-level frameworks");
985809500fcSDimitry Andric 
986aca2e42cSDimitry Andric   StringRef FrameworkName(Mod->Name);
987aca2e42cSDimitry Andric   FrameworkName.consume_back("_Private");
988aca2e42cSDimitry Andric   Mod->LinkLibraries.push_back(Module::LinkLibrary(FrameworkName.str(),
989809500fcSDimitry Andric                                                    /*IsFramework=*/true));
990809500fcSDimitry Andric }
991809500fcSDimitry Andric 
inferFrameworkModule(DirectoryEntryRef FrameworkDir,bool IsSystem,Module * Parent)9927fa27ce4SDimitry Andric Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
993c192b3dcSDimitry Andric                                         bool IsSystem, Module *Parent) {
99406d4ba38SDimitry Andric   Attributes Attrs;
99506d4ba38SDimitry Andric   Attrs.IsSystem = IsSystem;
996c192b3dcSDimitry Andric   return inferFrameworkModule(FrameworkDir, Attrs, Parent);
99706d4ba38SDimitry Andric }
99806d4ba38SDimitry Andric 
inferFrameworkModule(DirectoryEntryRef FrameworkDir,Attributes Attrs,Module * Parent)9997fa27ce4SDimitry Andric Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
100006d4ba38SDimitry Andric                                         Attributes Attrs, Module *Parent) {
1001c192b3dcSDimitry Andric   // Note: as an egregious but useful hack we use the real path here, because
1002c192b3dcSDimitry Andric   // we might be looking at an embedded framework that symlinks out to a
1003c192b3dcSDimitry Andric   // top-level framework, and we need to infer as if we were naming the
1004c192b3dcSDimitry Andric   // top-level framework.
1005c192b3dcSDimitry Andric   StringRef FrameworkDirName =
1006c192b3dcSDimitry Andric       SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
1007c192b3dcSDimitry Andric 
1008c192b3dcSDimitry Andric   // In case this is a case-insensitive filesystem, use the canonical
1009c192b3dcSDimitry Andric   // directory name as the ModuleName, since modules are case-sensitive.
1010c192b3dcSDimitry Andric   // FIXME: we should be able to give a fix-it hint for the correct spelling.
1011c192b3dcSDimitry Andric   SmallString<32> ModuleNameStorage;
1012c192b3dcSDimitry Andric   StringRef ModuleName = sanitizeFilenameAsIdentifier(
1013c192b3dcSDimitry Andric       llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
101406d4ba38SDimitry Andric 
1015dbe13110SDimitry Andric   // Check whether we've already found this module.
1016dbe13110SDimitry Andric   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
1017dbe13110SDimitry Andric     return Mod;
1018dbe13110SDimitry Andric 
1019bfef3995SDimitry Andric   FileManager &FileMgr = SourceMgr.getFileManager();
1020dbe13110SDimitry Andric 
102113cc256eSDimitry Andric   // If the framework has a parent path from which we're allowed to infer
102213cc256eSDimitry Andric   // a framework module, do so.
1023ac9a064cSDimitry Andric   FileID ModuleMapFID;
102413cc256eSDimitry Andric   if (!Parent) {
1025809500fcSDimitry Andric     // Determine whether we're allowed to infer a module map.
102613cc256eSDimitry Andric     bool canInfer = false;
1027809500fcSDimitry Andric     if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
102813cc256eSDimitry Andric       // Figure out the parent path.
1029809500fcSDimitry Andric       StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
10307fa27ce4SDimitry Andric       if (auto ParentDir = FileMgr.getOptionalDirectoryRef(Parent)) {
103113cc256eSDimitry Andric         // Check whether we have already looked into the parent directory
103213cc256eSDimitry Andric         // for a module map.
1033809500fcSDimitry Andric         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
1034519fc96cSDimitry Andric           inferred = InferredDirectories.find(*ParentDir);
103513cc256eSDimitry Andric         if (inferred == InferredDirectories.end()) {
103613cc256eSDimitry Andric           // We haven't looked here before. Load a module map, if there is
103713cc256eSDimitry Andric           // one.
1038312c0ed1SDimitry Andric           bool IsFrameworkDir = Parent.ends_with(".framework");
10397fa27ce4SDimitry Andric           if (OptionalFileEntryRef ModMapFile =
1040519fc96cSDimitry Andric                   HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) {
10417fa27ce4SDimitry Andric             parseModuleMapFile(*ModMapFile, Attrs.IsSystem, *ParentDir);
1042519fc96cSDimitry Andric             inferred = InferredDirectories.find(*ParentDir);
104313cc256eSDimitry Andric           }
104413cc256eSDimitry Andric 
104513cc256eSDimitry Andric           if (inferred == InferredDirectories.end())
104613cc256eSDimitry Andric             inferred = InferredDirectories.insert(
1047519fc96cSDimitry Andric                          std::make_pair(*ParentDir, InferredDirectory())).first;
104813cc256eSDimitry Andric         }
104913cc256eSDimitry Andric 
105013cc256eSDimitry Andric         if (inferred->second.InferModules) {
105113cc256eSDimitry Andric           // We're allowed to infer for this directory, but make sure it's okay
105213cc256eSDimitry Andric           // to infer this particular module.
1053809500fcSDimitry Andric           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
1054c0981da4SDimitry Andric           canInfer =
1055c0981da4SDimitry Andric               !llvm::is_contained(inferred->second.ExcludedModules, Name);
105613cc256eSDimitry Andric 
105706d4ba38SDimitry Andric           Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
105806d4ba38SDimitry Andric           Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
105906d4ba38SDimitry Andric           Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
1060bab175ecSDimitry Andric           Attrs.NoUndeclaredIncludes |=
1061bab175ecSDimitry Andric               inferred->second.Attrs.NoUndeclaredIncludes;
1062ac9a064cSDimitry Andric           ModuleMapFID = inferred->second.ModuleMapFID;
106313cc256eSDimitry Andric         }
106413cc256eSDimitry Andric       }
106513cc256eSDimitry Andric     }
106613cc256eSDimitry Andric 
106713cc256eSDimitry Andric     // If we're not allowed to infer a framework module, don't.
106813cc256eSDimitry Andric     if (!canInfer)
10699f4dbff6SDimitry Andric       return nullptr;
1070e3b55780SDimitry Andric   } else {
1071ac9a064cSDimitry Andric     ModuleMapFID = getModuleMapFileIDForUniquing(Parent);
1072e3b55780SDimitry Andric   }
107313cc256eSDimitry Andric 
1074dbe13110SDimitry Andric   // Look for an umbrella header.
10757fa27ce4SDimitry Andric   SmallString<128> UmbrellaName = FrameworkDir.getName();
1076bfef3995SDimitry Andric   llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
1077e3b55780SDimitry Andric   auto UmbrellaHeader = FileMgr.getOptionalFileRef(UmbrellaName);
1078dbe13110SDimitry Andric 
1079dbe13110SDimitry Andric   // FIXME: If there's no umbrella header, we could probably scan the
1080dbe13110SDimitry Andric   // framework to load *everything*. But, it's not clear that this is a good
1081dbe13110SDimitry Andric   // idea.
1082dbe13110SDimitry Andric   if (!UmbrellaHeader)
10839f4dbff6SDimitry Andric     return nullptr;
1084dbe13110SDimitry Andric 
108506d4ba38SDimitry Andric   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
10865e20cdd8SDimitry Andric                               /*IsFramework=*/true, /*IsExplicit=*/false,
10875e20cdd8SDimitry Andric                               NumCreatedModules++);
1088ac9a064cSDimitry Andric   InferredModuleAllowedBy[Result] = ModuleMapFID;
108906d4ba38SDimitry Andric   Result->IsInferred = true;
10902b6b257fSDimitry Andric   if (!Parent) {
10912b6b257fSDimitry Andric     if (LangOpts.CurrentModule == ModuleName)
1092bfef3995SDimitry Andric       SourceModule = Result;
10932b6b257fSDimitry Andric     Modules[ModuleName] = Result;
109448675466SDimitry Andric     ModuleScopeIDs[Result] = CurrentModuleScopeID;
1095bfef3995SDimitry Andric   }
109606d4ba38SDimitry Andric 
109706d4ba38SDimitry Andric   Result->IsSystem |= Attrs.IsSystem;
109806d4ba38SDimitry Andric   Result->IsExternC |= Attrs.IsExternC;
109906d4ba38SDimitry Andric   Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
1100bab175ecSDimitry Andric   Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
11015e20cdd8SDimitry Andric   Result->Directory = FrameworkDir;
1102dbe13110SDimitry Andric 
1103344a3780SDimitry Andric   // Chop off the first framework bit, as that is implied.
1104344a3780SDimitry Andric   StringRef RelativePath = UmbrellaName.str().substr(
1105344a3780SDimitry Andric       Result->getTopLevelModule()->Directory->getName().size());
1106344a3780SDimitry Andric   RelativePath = llvm::sys::path::relative_path(RelativePath);
1107344a3780SDimitry Andric 
1108dbe13110SDimitry Andric   // umbrella header "umbrella-header-name"
11097fa27ce4SDimitry Andric   setUmbrellaHeaderAsWritten(Result, *UmbrellaHeader, ModuleName + ".h",
11107fa27ce4SDimitry Andric                              RelativePath);
1111dbe13110SDimitry Andric 
1112dbe13110SDimitry Andric   // export *
11139f4dbff6SDimitry Andric   Result->Exports.push_back(Module::ExportDecl(nullptr, true));
1114dbe13110SDimitry Andric 
1115dbe13110SDimitry Andric   // module * { export * }
1116dbe13110SDimitry Andric   Result->InferSubmodules = true;
1117dbe13110SDimitry Andric   Result->InferExportWildcard = true;
1118dbe13110SDimitry Andric 
1119dbe13110SDimitry Andric   // Look for subframeworks.
11209f4dbff6SDimitry Andric   std::error_code EC;
11217fa27ce4SDimitry Andric   SmallString<128> SubframeworksDirName = FrameworkDir.getName();
1122dbe13110SDimitry Andric   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
1123bfef3995SDimitry Andric   llvm::sys::path::native(SubframeworksDirName);
112422989816SDimitry Andric   llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
1125676fbe81SDimitry Andric   for (llvm::vfs::directory_iterator
1126676fbe81SDimitry Andric            Dir = FS.dir_begin(SubframeworksDirName, EC),
11272b6b257fSDimitry Andric            DirEnd;
1128dbe13110SDimitry Andric        Dir != DirEnd && !EC; Dir.increment(EC)) {
1129312c0ed1SDimitry Andric     if (!StringRef(Dir->path()).ends_with(".framework"))
1130dbe13110SDimitry Andric       continue;
1131dbe13110SDimitry Andric 
11327fa27ce4SDimitry Andric     if (auto SubframeworkDir = FileMgr.getOptionalDirectoryRef(Dir->path())) {
113313cc256eSDimitry Andric       // Note: as an egregious but useful hack, we use the real path here and
113413cc256eSDimitry Andric       // check whether it is actually a subdirectory of the parent directory.
113513cc256eSDimitry Andric       // This will not be the case if the 'subframework' is actually a symlink
113613cc256eSDimitry Andric       // out to a top-level framework.
1137519fc96cSDimitry Andric       StringRef SubframeworkDirName =
1138519fc96cSDimitry Andric           FileMgr.getCanonicalName(*SubframeworkDir);
113913cc256eSDimitry Andric       bool FoundParent = false;
114013cc256eSDimitry Andric       do {
114113cc256eSDimitry Andric         // Get the parent directory name.
114213cc256eSDimitry Andric         SubframeworkDirName
114313cc256eSDimitry Andric           = llvm::sys::path::parent_path(SubframeworkDirName);
114413cc256eSDimitry Andric         if (SubframeworkDirName.empty())
114513cc256eSDimitry Andric           break;
114613cc256eSDimitry Andric 
1147519fc96cSDimitry Andric         if (auto SubDir = FileMgr.getDirectory(SubframeworkDirName)) {
1148519fc96cSDimitry Andric           if (*SubDir == FrameworkDir) {
114913cc256eSDimitry Andric             FoundParent = true;
115013cc256eSDimitry Andric             break;
115113cc256eSDimitry Andric           }
1152519fc96cSDimitry Andric         }
115313cc256eSDimitry Andric       } while (true);
115413cc256eSDimitry Andric 
115513cc256eSDimitry Andric       if (!FoundParent)
115613cc256eSDimitry Andric         continue;
115713cc256eSDimitry Andric 
1158dbe13110SDimitry Andric       // FIXME: Do we want to warn about subframeworks without umbrella headers?
1159519fc96cSDimitry Andric       inferFrameworkModule(*SubframeworkDir, Attrs, Result);
1160dbe13110SDimitry Andric     }
1161dbe13110SDimitry Andric   }
1162dbe13110SDimitry Andric 
1163809500fcSDimitry Andric   // If the module is a top-level framework, automatically link against the
1164809500fcSDimitry Andric   // framework.
11657fa27ce4SDimitry Andric   if (!Result->isSubFramework())
11667fa27ce4SDimitry Andric     inferFrameworkLink(Result);
1167809500fcSDimitry Andric 
1168dbe13110SDimitry Andric   return Result;
1169dbe13110SDimitry Andric }
1170dbe13110SDimitry Andric 
createShadowedModule(StringRef Name,bool IsFramework,Module * ShadowingModule)117148675466SDimitry Andric Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
117248675466SDimitry Andric                                         Module *ShadowingModule) {
117348675466SDimitry Andric 
117448675466SDimitry Andric   // Create a new module with this name.
117548675466SDimitry Andric   Module *Result =
117648675466SDimitry Andric       new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
117748675466SDimitry Andric                  /*IsExplicit=*/false, NumCreatedModules++);
117848675466SDimitry Andric   Result->ShadowingModule = ShadowingModule;
1179cfca06d7SDimitry Andric   Result->markUnavailable(/*Unimportable*/true);
118048675466SDimitry Andric   ModuleScopeIDs[Result] = CurrentModuleScopeID;
118148675466SDimitry Andric   ShadowModules.push_back(Result);
118248675466SDimitry Andric 
118348675466SDimitry Andric   return Result;
118448675466SDimitry Andric }
118548675466SDimitry Andric 
setUmbrellaHeaderAsWritten(Module * Mod,FileEntryRef UmbrellaHeader,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)11867fa27ce4SDimitry Andric void ModuleMap::setUmbrellaHeaderAsWritten(
1187e3b55780SDimitry Andric     Module *Mod, FileEntryRef UmbrellaHeader, const Twine &NameAsWritten,
1188344a3780SDimitry Andric     const Twine &PathRelativeToRootModuleDirectory) {
1189bfef3995SDimitry Andric   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
11907fa27ce4SDimitry Andric   Mod->Umbrella = UmbrellaHeader;
11915e20cdd8SDimitry Andric   Mod->UmbrellaAsWritten = NameAsWritten.str();
1192344a3780SDimitry Andric   Mod->UmbrellaRelativeToRootModuleDirectory =
1193344a3780SDimitry Andric       PathRelativeToRootModuleDirectory.str();
1194e3b55780SDimitry Andric   UmbrellaDirs[UmbrellaHeader.getDir()] = Mod;
11952b6b257fSDimitry Andric 
11962b6b257fSDimitry Andric   // Notify callbacks that we just added a new header.
11972b6b257fSDimitry Andric   for (const auto &Cb : Callbacks)
11987fa27ce4SDimitry Andric     Cb->moduleMapAddUmbrellaHeader(UmbrellaHeader);
1199dbe13110SDimitry Andric }
1200dbe13110SDimitry Andric 
setUmbrellaDirAsWritten(Module * Mod,DirectoryEntryRef UmbrellaDir,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)12017fa27ce4SDimitry Andric void ModuleMap::setUmbrellaDirAsWritten(
12027fa27ce4SDimitry Andric     Module *Mod, DirectoryEntryRef UmbrellaDir, const Twine &NameAsWritten,
1203344a3780SDimitry Andric     const Twine &PathRelativeToRootModuleDirectory) {
1204344a3780SDimitry Andric   Mod->Umbrella = UmbrellaDir;
12055e20cdd8SDimitry Andric   Mod->UmbrellaAsWritten = NameAsWritten.str();
1206344a3780SDimitry Andric   Mod->UmbrellaRelativeToRootModuleDirectory =
1207344a3780SDimitry Andric       PathRelativeToRootModuleDirectory.str();
1208dbe13110SDimitry Andric   UmbrellaDirs[UmbrellaDir] = Mod;
1209dbe13110SDimitry Andric }
1210dbe13110SDimitry Andric 
addUnresolvedHeader(Module * Mod,Module::UnresolvedHeaderDirective Header,bool & NeedsFramework)1211551c6985SDimitry Andric void ModuleMap::addUnresolvedHeader(Module *Mod,
121248675466SDimitry Andric                                     Module::UnresolvedHeaderDirective Header,
121348675466SDimitry Andric                                     bool &NeedsFramework) {
1214551c6985SDimitry Andric   // If there is a builtin counterpart to this file, add it now so it can
1215551c6985SDimitry Andric   // wrap the system header.
1216551c6985SDimitry Andric   if (resolveAsBuiltinHeader(Mod, Header)) {
1217551c6985SDimitry Andric     // If we have both a builtin and system version of the file, the
1218551c6985SDimitry Andric     // builtin version may want to inject macros into the system header, so
1219551c6985SDimitry Andric     // force the system header to be treated as a textual header in this
1220551c6985SDimitry Andric     // case.
1221551c6985SDimitry Andric     Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
1222551c6985SDimitry Andric         headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
1223551c6985SDimitry Andric     Header.HasBuiltinHeader = true;
1224809500fcSDimitry Andric   }
1225551c6985SDimitry Andric 
1226551c6985SDimitry Andric   // If possible, don't stat the header until we need to. This requires the
1227551c6985SDimitry Andric   // user to have provided us with some stat information about the file.
1228551c6985SDimitry Andric   // FIXME: Add support for lazily stat'ing umbrella headers and excluded
1229551c6985SDimitry Andric   // headers.
1230551c6985SDimitry Andric   if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
1231551c6985SDimitry Andric       Header.Kind != Module::HK_Excluded) {
1232551c6985SDimitry Andric     // We expect more variation in mtime than size, so if we're given both,
1233551c6985SDimitry Andric     // use the mtime as the key.
1234551c6985SDimitry Andric     if (Header.ModTime)
1235551c6985SDimitry Andric       LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
1236551c6985SDimitry Andric     else
1237551c6985SDimitry Andric       LazyHeadersBySize[*Header.Size].push_back(Mod);
1238551c6985SDimitry Andric     Mod->UnresolvedHeaders.push_back(Header);
1239551c6985SDimitry Andric     return;
1240551c6985SDimitry Andric   }
1241551c6985SDimitry Andric 
1242551c6985SDimitry Andric   // We don't have stat information or can't defer looking this file up.
1243551c6985SDimitry Andric   // Perform the lookup now.
124448675466SDimitry Andric   resolveHeader(Mod, Header, NeedsFramework);
1245551c6985SDimitry Andric }
1246551c6985SDimitry Andric 
resolveHeaderDirectives(const FileEntry * File) const1247551c6985SDimitry Andric void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
1248551c6985SDimitry Andric   auto BySize = LazyHeadersBySize.find(File->getSize());
1249551c6985SDimitry Andric   if (BySize != LazyHeadersBySize.end()) {
1250551c6985SDimitry Andric     for (auto *M : BySize->second)
1251145449b1SDimitry Andric       resolveHeaderDirectives(M, File);
1252551c6985SDimitry Andric     LazyHeadersBySize.erase(BySize);
1253551c6985SDimitry Andric   }
1254551c6985SDimitry Andric 
1255551c6985SDimitry Andric   auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
1256551c6985SDimitry Andric   if (ByModTime != LazyHeadersByModTime.end()) {
1257551c6985SDimitry Andric     for (auto *M : ByModTime->second)
1258145449b1SDimitry Andric       resolveHeaderDirectives(M, File);
1259551c6985SDimitry Andric     LazyHeadersByModTime.erase(ByModTime);
1260551c6985SDimitry Andric   }
1261551c6985SDimitry Andric }
1262551c6985SDimitry Andric 
resolveHeaderDirectives(Module * Mod,std::optional<const FileEntry * > File) const1263145449b1SDimitry Andric void ModuleMap::resolveHeaderDirectives(
1264e3b55780SDimitry Andric     Module *Mod, std::optional<const FileEntry *> File) const {
126548675466SDimitry Andric   bool NeedsFramework = false;
1266145449b1SDimitry Andric   SmallVector<Module::UnresolvedHeaderDirective, 1> NewHeaders;
1267e3b55780SDimitry Andric   const auto Size = File ? (*File)->getSize() : 0;
1268e3b55780SDimitry Andric   const auto ModTime = File ? (*File)->getModificationTime() : 0;
1269145449b1SDimitry Andric 
1270145449b1SDimitry Andric   for (auto &Header : Mod->UnresolvedHeaders) {
1271145449b1SDimitry Andric     if (File && ((Header.ModTime && Header.ModTime != ModTime) ||
1272145449b1SDimitry Andric                  (Header.Size && Header.Size != Size)))
1273145449b1SDimitry Andric       NewHeaders.push_back(Header);
1274145449b1SDimitry Andric     else
1275551c6985SDimitry Andric       // This operation is logically const; we're just changing how we represent
1276551c6985SDimitry Andric       // the header information for this file.
127748675466SDimitry Andric       const_cast<ModuleMap *>(this)->resolveHeader(Mod, Header, NeedsFramework);
1278145449b1SDimitry Andric   }
1279145449b1SDimitry Andric   Mod->UnresolvedHeaders.swap(NewHeaders);
128006d4ba38SDimitry Andric }
128106d4ba38SDimitry Andric 
addHeader(Module * Mod,Module::Header Header,ModuleHeaderRole Role,bool Imported)128206d4ba38SDimitry Andric void ModuleMap::addHeader(Module *Mod, Module::Header Header,
128345b53394SDimitry Andric                           ModuleHeaderRole Role, bool Imported) {
128445b53394SDimitry Andric   KnownHeader KH(Mod, Role);
128545b53394SDimitry Andric 
128645b53394SDimitry Andric   // Only add each header to the headers list once.
128745b53394SDimitry Andric   // FIXME: Should we diagnose if a header is listed twice in the
128845b53394SDimitry Andric   // same module definition?
128945b53394SDimitry Andric   auto &HeaderList = Headers[Header.Entry];
1290c0981da4SDimitry Andric   if (llvm::is_contained(HeaderList, KH))
129145b53394SDimitry Andric     return;
129245b53394SDimitry Andric 
129345b53394SDimitry Andric   HeaderList.push_back(KH);
1294bab175ecSDimitry Andric   Mod->Headers[headerRoleToKind(Role)].push_back(Header);
129545b53394SDimitry Andric 
1296b1c73532SDimitry Andric   bool isCompilingModuleHeader = Mod->isForBuilding(LangOpts);
129745b53394SDimitry Andric   if (!Imported || isCompilingModuleHeader) {
129845b53394SDimitry Andric     // When we import HeaderFileInfo, the external source is expected to
129945b53394SDimitry Andric     // set the isModuleHeader flag itself.
130006d4ba38SDimitry Andric     HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
130106d4ba38SDimitry Andric                                     isCompilingModuleHeader);
130206d4ba38SDimitry Andric   }
13032b6b257fSDimitry Andric 
13042b6b257fSDimitry Andric   // Notify callbacks that we just added a new header.
13052b6b257fSDimitry Andric   for (const auto &Cb : Callbacks)
13067fa27ce4SDimitry Andric     Cb->moduleMapAddHeader(Header.Entry.getName());
130706d4ba38SDimitry Andric }
130806d4ba38SDimitry Andric 
getContainingModuleMapFileID(const Module * Module) const1309ac9a064cSDimitry Andric FileID ModuleMap::getContainingModuleMapFileID(const Module *Module) const {
1310bfef3995SDimitry Andric   if (Module->DefinitionLoc.isInvalid())
1311ac9a064cSDimitry Andric     return {};
1312dbe13110SDimitry Andric 
1313ac9a064cSDimitry Andric   return SourceMgr.getFileID(Module->DefinitionLoc);
1314dbe13110SDimitry Andric }
1315dbe13110SDimitry Andric 
1316e3b55780SDimitry Andric OptionalFileEntryRef
getContainingModuleMapFile(const Module * Module) const1317ac9a064cSDimitry Andric ModuleMap::getContainingModuleMapFile(const Module *Module) const {
1318ac9a064cSDimitry Andric   return SourceMgr.getFileEntryRefForID(getContainingModuleMapFileID(Module));
1319ac9a064cSDimitry Andric }
1320ac9a064cSDimitry Andric 
getModuleMapFileIDForUniquing(const Module * M) const1321ac9a064cSDimitry Andric FileID ModuleMap::getModuleMapFileIDForUniquing(const Module *M) const {
132206d4ba38SDimitry Andric   if (M->IsInferred) {
132306d4ba38SDimitry Andric     assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
1324b1c73532SDimitry Andric     return InferredModuleAllowedBy.find(M)->second;
132506d4ba38SDimitry Andric   }
1326ac9a064cSDimitry Andric   return getContainingModuleMapFileID(M);
132706d4ba38SDimitry Andric }
132806d4ba38SDimitry Andric 
1329ac9a064cSDimitry Andric OptionalFileEntryRef
getModuleMapFileForUniquing(const Module * M) const1330ac9a064cSDimitry Andric ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
1331ac9a064cSDimitry Andric   return SourceMgr.getFileEntryRefForID(getModuleMapFileIDForUniquing(M));
1332ac9a064cSDimitry Andric }
1333ac9a064cSDimitry Andric 
setInferredModuleAllowedBy(Module * M,FileID ModMapFID)1334ac9a064cSDimitry Andric void ModuleMap::setInferredModuleAllowedBy(Module *M, FileID ModMapFID) {
133506d4ba38SDimitry Andric   assert(M->IsInferred && "module not inferred");
1336ac9a064cSDimitry Andric   InferredModuleAllowedBy[M] = ModMapFID;
133706d4ba38SDimitry Andric }
133806d4ba38SDimitry Andric 
1339e3b55780SDimitry Andric std::error_code
canonicalizeModuleMapPath(SmallVectorImpl<char> & Path)1340e3b55780SDimitry Andric ModuleMap::canonicalizeModuleMapPath(SmallVectorImpl<char> &Path) {
1341e3b55780SDimitry Andric   StringRef Dir = llvm::sys::path::parent_path({Path.data(), Path.size()});
1342e3b55780SDimitry Andric 
1343e3b55780SDimitry Andric   // Do not canonicalize within the framework; the module map parser expects
1344e3b55780SDimitry Andric   // Modules/ not Versions/A/Modules.
1345e3b55780SDimitry Andric   if (llvm::sys::path::filename(Dir) == "Modules") {
1346e3b55780SDimitry Andric     StringRef Parent = llvm::sys::path::parent_path(Dir);
1347312c0ed1SDimitry Andric     if (Parent.ends_with(".framework"))
1348e3b55780SDimitry Andric       Dir = Parent;
1349e3b55780SDimitry Andric   }
1350e3b55780SDimitry Andric 
1351e3b55780SDimitry Andric   FileManager &FM = SourceMgr.getFileManager();
13527fa27ce4SDimitry Andric   auto DirEntry = FM.getDirectoryRef(Dir.empty() ? "." : Dir);
1353e3b55780SDimitry Andric   if (!DirEntry)
13547fa27ce4SDimitry Andric     return llvm::errorToErrorCode(DirEntry.takeError());
1355e3b55780SDimitry Andric 
1356e3b55780SDimitry Andric   // Canonicalize the directory.
1357e3b55780SDimitry Andric   StringRef CanonicalDir = FM.getCanonicalName(*DirEntry);
13587fa27ce4SDimitry Andric   if (CanonicalDir != Dir)
13597fa27ce4SDimitry Andric     llvm::sys::path::replace_path_prefix(Path, Dir, CanonicalDir);
1360e3b55780SDimitry Andric 
1361e3b55780SDimitry Andric   // In theory, the filename component should also be canonicalized if it
1362e3b55780SDimitry Andric   // on a case-insensitive filesystem. However, the extra canonicalization is
1363e3b55780SDimitry Andric   // expensive and if clang looked up the filename it will always be lowercase.
1364e3b55780SDimitry Andric 
1365e3b55780SDimitry Andric   // Remove ., remove redundant separators, and switch to native separators.
1366e3b55780SDimitry Andric   // This is needed for separators between CanonicalDir and the filename.
1367e3b55780SDimitry Andric   llvm::sys::path::remove_dots(Path);
1368e3b55780SDimitry Andric 
1369e3b55780SDimitry Andric   return std::error_code();
1370e3b55780SDimitry Andric }
1371e3b55780SDimitry Andric 
addAdditionalModuleMapFile(const Module * M,FileEntryRef ModuleMap)1372cfca06d7SDimitry Andric void ModuleMap::addAdditionalModuleMapFile(const Module *M,
1373b1c73532SDimitry Andric                                            FileEntryRef ModuleMap) {
1374cfca06d7SDimitry Andric   AdditionalModMaps[M].insert(ModuleMap);
1375cfca06d7SDimitry Andric }
1376cfca06d7SDimitry Andric 
dump()13772b6b257fSDimitry Andric LLVM_DUMP_METHOD void ModuleMap::dump() {
1378dbe13110SDimitry Andric   llvm::errs() << "Modules:";
1379dbe13110SDimitry Andric   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1380dbe13110SDimitry Andric                                         MEnd = Modules.end();
1381dbe13110SDimitry Andric        M != MEnd; ++M)
1382dbe13110SDimitry Andric     M->getValue()->print(llvm::errs(), 2);
1383dbe13110SDimitry Andric 
1384dbe13110SDimitry Andric   llvm::errs() << "Headers:";
138513cc256eSDimitry Andric   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1386dbe13110SDimitry Andric        H != HEnd; ++H) {
1387b1c73532SDimitry Andric     llvm::errs() << "  \"" << H->first.getName() << "\" -> ";
1388bfef3995SDimitry Andric     for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
1389bfef3995SDimitry Andric                                                       E = H->second.end();
1390bfef3995SDimitry Andric          I != E; ++I) {
1391bfef3995SDimitry Andric       if (I != H->second.begin())
1392bfef3995SDimitry Andric         llvm::errs() << ",";
1393bfef3995SDimitry Andric       llvm::errs() << I->getModule()->getFullModuleName();
1394bfef3995SDimitry Andric     }
1395bfef3995SDimitry Andric     llvm::errs() << "\n";
1396dbe13110SDimitry Andric   }
1397dbe13110SDimitry Andric }
1398dbe13110SDimitry Andric 
resolveExports(Module * Mod,bool Complain)1399dbe13110SDimitry Andric bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
14005e20cdd8SDimitry Andric   auto Unresolved = std::move(Mod->UnresolvedExports);
14015e20cdd8SDimitry Andric   Mod->UnresolvedExports.clear();
14025e20cdd8SDimitry Andric   for (auto &UE : Unresolved) {
14035e20cdd8SDimitry Andric     Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
1404dbe13110SDimitry Andric     if (Export.getPointer() || Export.getInt())
1405dbe13110SDimitry Andric       Mod->Exports.push_back(Export);
1406dbe13110SDimitry Andric     else
14075e20cdd8SDimitry Andric       Mod->UnresolvedExports.push_back(UE);
1408dbe13110SDimitry Andric   }
14095e20cdd8SDimitry Andric   return !Mod->UnresolvedExports.empty();
1410dbe13110SDimitry Andric }
1411dbe13110SDimitry Andric 
resolveUses(Module * Mod,bool Complain)1412bfef3995SDimitry Andric bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
1413b1c73532SDimitry Andric   auto *Top = Mod->getTopLevelModule();
1414b1c73532SDimitry Andric   auto Unresolved = std::move(Top->UnresolvedDirectUses);
1415b1c73532SDimitry Andric   Top->UnresolvedDirectUses.clear();
14165e20cdd8SDimitry Andric   for (auto &UDU : Unresolved) {
1417b1c73532SDimitry Andric     Module *DirectUse = resolveModuleId(UDU, Top, Complain);
1418bfef3995SDimitry Andric     if (DirectUse)
1419b1c73532SDimitry Andric       Top->DirectUses.push_back(DirectUse);
1420bfef3995SDimitry Andric     else
1421b1c73532SDimitry Andric       Top->UnresolvedDirectUses.push_back(UDU);
1422bfef3995SDimitry Andric   }
1423b1c73532SDimitry Andric   return !Top->UnresolvedDirectUses.empty();
1424bfef3995SDimitry Andric }
1425bfef3995SDimitry Andric 
resolveConflicts(Module * Mod,bool Complain)1426809500fcSDimitry Andric bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
14275e20cdd8SDimitry Andric   auto Unresolved = std::move(Mod->UnresolvedConflicts);
14285e20cdd8SDimitry Andric   Mod->UnresolvedConflicts.clear();
14295e20cdd8SDimitry Andric   for (auto &UC : Unresolved) {
14305e20cdd8SDimitry Andric     if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1431809500fcSDimitry Andric       Module::Conflict Conflict;
1432809500fcSDimitry Andric       Conflict.Other = OtherMod;
14335e20cdd8SDimitry Andric       Conflict.Message = UC.Message;
1434809500fcSDimitry Andric       Mod->Conflicts.push_back(Conflict);
14355e20cdd8SDimitry Andric     } else
14365e20cdd8SDimitry Andric       Mod->UnresolvedConflicts.push_back(UC);
1437809500fcSDimitry Andric   }
14385e20cdd8SDimitry Andric   return !Mod->UnresolvedConflicts.empty();
1439809500fcSDimitry Andric }
1440809500fcSDimitry Andric 
1441dbe13110SDimitry Andric //----------------------------------------------------------------------------//
1442dbe13110SDimitry Andric // Module map file parser
1443dbe13110SDimitry Andric //----------------------------------------------------------------------------//
1444dbe13110SDimitry Andric 
1445dbe13110SDimitry Andric namespace clang {
1446461a67faSDimitry Andric 
144748675466SDimitry Andric   /// A token in a module map file.
1448dbe13110SDimitry Andric   struct MMToken {
1449dbe13110SDimitry Andric     enum TokenKind {
1450dbe13110SDimitry Andric       Comma,
1451809500fcSDimitry Andric       ConfigMacros,
1452809500fcSDimitry Andric       Conflict,
1453dbe13110SDimitry Andric       EndOfFile,
1454dbe13110SDimitry Andric       HeaderKeyword,
1455dbe13110SDimitry Andric       Identifier,
1456bfef3995SDimitry Andric       Exclaim,
145713cc256eSDimitry Andric       ExcludeKeyword,
1458dbe13110SDimitry Andric       ExplicitKeyword,
1459dbe13110SDimitry Andric       ExportKeyword,
1460461a67faSDimitry Andric       ExportAsKeyword,
1461bfef3995SDimitry Andric       ExternKeyword,
1462dbe13110SDimitry Andric       FrameworkKeyword,
1463809500fcSDimitry Andric       LinkKeyword,
1464dbe13110SDimitry Andric       ModuleKeyword,
1465dbe13110SDimitry Andric       Period,
1466bfef3995SDimitry Andric       PrivateKeyword,
1467dbe13110SDimitry Andric       UmbrellaKeyword,
1468bfef3995SDimitry Andric       UseKeyword,
1469dbe13110SDimitry Andric       RequiresKeyword,
1470dbe13110SDimitry Andric       Star,
1471dbe13110SDimitry Andric       StringLiteral,
1472551c6985SDimitry Andric       IntegerLiteral,
147306d4ba38SDimitry Andric       TextualKeyword,
1474dbe13110SDimitry Andric       LBrace,
1475dbe13110SDimitry Andric       RBrace,
1476dbe13110SDimitry Andric       LSquare,
1477dbe13110SDimitry Andric       RSquare
1478dbe13110SDimitry Andric     } Kind;
1479dbe13110SDimitry Andric 
1480344a3780SDimitry Andric     SourceLocation::UIntTy Location;
1481dbe13110SDimitry Andric     unsigned StringLength;
1482551c6985SDimitry Andric     union {
1483551c6985SDimitry Andric       // If Kind != IntegerLiteral.
1484dbe13110SDimitry Andric       const char *StringData;
1485461a67faSDimitry Andric 
1486551c6985SDimitry Andric       // If Kind == IntegerLiteral.
1487551c6985SDimitry Andric       uint64_t IntegerValue;
1488551c6985SDimitry Andric     };
1489dbe13110SDimitry Andric 
clearclang::MMToken1490dbe13110SDimitry Andric     void clear() {
1491dbe13110SDimitry Andric       Kind = EndOfFile;
1492dbe13110SDimitry Andric       Location = 0;
1493dbe13110SDimitry Andric       StringLength = 0;
14949f4dbff6SDimitry Andric       StringData = nullptr;
1495dbe13110SDimitry Andric     }
1496dbe13110SDimitry Andric 
isclang::MMToken1497dbe13110SDimitry Andric     bool is(TokenKind K) const { return Kind == K; }
1498dbe13110SDimitry Andric 
getLocationclang::MMToken1499dbe13110SDimitry Andric     SourceLocation getLocation() const {
1500dbe13110SDimitry Andric       return SourceLocation::getFromRawEncoding(Location);
1501dbe13110SDimitry Andric     }
1502dbe13110SDimitry Andric 
getIntegerclang::MMToken1503551c6985SDimitry Andric     uint64_t getInteger() const {
1504551c6985SDimitry Andric       return Kind == IntegerLiteral ? IntegerValue : 0;
1505551c6985SDimitry Andric     }
1506551c6985SDimitry Andric 
getStringclang::MMToken1507dbe13110SDimitry Andric     StringRef getString() const {
1508551c6985SDimitry Andric       return Kind == IntegerLiteral ? StringRef()
1509551c6985SDimitry Andric                                     : StringRef(StringData, StringLength);
1510dbe13110SDimitry Andric     }
1511dbe13110SDimitry Andric   };
1512dbe13110SDimitry Andric 
1513dbe13110SDimitry Andric   class ModuleMapParser {
1514dbe13110SDimitry Andric     Lexer &L;
1515dbe13110SDimitry Andric     SourceManager &SourceMgr;
151613cc256eSDimitry Andric 
151748675466SDimitry Andric     /// Default target information, used only for string literal
151813cc256eSDimitry Andric     /// parsing.
151913cc256eSDimitry Andric     const TargetInfo *Target;
152013cc256eSDimitry Andric 
1521dbe13110SDimitry Andric     DiagnosticsEngine &Diags;
1522dbe13110SDimitry Andric     ModuleMap &Map;
1523dbe13110SDimitry Andric 
152448675466SDimitry Andric     /// The current module map file.
1525ac9a064cSDimitry Andric     FileID ModuleMapFID;
15269f4dbff6SDimitry Andric 
152748675466SDimitry Andric     /// Source location of most recent parsed module declaration
152848675466SDimitry Andric     SourceLocation CurrModuleDeclLoc;
152948675466SDimitry Andric 
153048675466SDimitry Andric     /// The directory that file names in this module map file should
153106d4ba38SDimitry Andric     /// be resolved relative to.
15327fa27ce4SDimitry Andric     DirectoryEntryRef Directory;
1533dbe13110SDimitry Andric 
153448675466SDimitry Andric     /// Whether this module map is in a system header directory.
1535bfef3995SDimitry Andric     bool IsSystem;
1536bfef3995SDimitry Andric 
153748675466SDimitry Andric     /// Whether an error occurred.
1538461a67faSDimitry Andric     bool HadError = false;
1539dbe13110SDimitry Andric 
154048675466SDimitry Andric     /// Stores string data for the various string literals referenced
1541dbe13110SDimitry Andric     /// during parsing.
1542dbe13110SDimitry Andric     llvm::BumpPtrAllocator StringData;
1543dbe13110SDimitry Andric 
154448675466SDimitry Andric     /// The current token.
1545dbe13110SDimitry Andric     MMToken Tok;
1546dbe13110SDimitry Andric 
154748675466SDimitry Andric     /// The active module.
1548461a67faSDimitry Andric     Module *ActiveModule = nullptr;
1549dbe13110SDimitry Andric 
155048675466SDimitry Andric     /// Whether a module uses the 'requires excluded' hack to mark its
155145b53394SDimitry Andric     /// contents as 'textual'.
155245b53394SDimitry Andric     ///
155345b53394SDimitry Andric     /// On older Darwin SDK versions, 'requires excluded' is used to mark the
155445b53394SDimitry Andric     /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
155545b53394SDimitry Andric     /// non-modular headers.  For backwards compatibility, we continue to
155645b53394SDimitry Andric     /// support this idiom for just these modules, and map the headers to
155745b53394SDimitry Andric     /// 'textual' to match the original intent.
155845b53394SDimitry Andric     llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
155945b53394SDimitry Andric 
156048675466SDimitry Andric     /// Consume the current token and return its location.
1561dbe13110SDimitry Andric     SourceLocation consumeToken();
1562dbe13110SDimitry Andric 
156348675466SDimitry Andric     /// Skip tokens until we reach the a token with the given kind
1564dbe13110SDimitry Andric     /// (or the end of the file).
1565dbe13110SDimitry Andric     void skipUntil(MMToken::TokenKind K);
1566dbe13110SDimitry Andric 
1567dbe13110SDimitry Andric     bool parseModuleId(ModuleId &Id);
1568dbe13110SDimitry Andric     void parseModuleDecl();
1569bfef3995SDimitry Andric     void parseExternModuleDecl();
1570dbe13110SDimitry Andric     void parseRequiresDecl();
1571461a67faSDimitry Andric     void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
1572dbe13110SDimitry Andric     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
1573dbe13110SDimitry Andric     void parseExportDecl();
1574461a67faSDimitry Andric     void parseExportAsDecl();
1575bfef3995SDimitry Andric     void parseUseDecl();
1576809500fcSDimitry Andric     void parseLinkDecl();
1577809500fcSDimitry Andric     void parseConfigMacros();
1578809500fcSDimitry Andric     void parseConflict();
157913cc256eSDimitry Andric     void parseInferredModuleDecl(bool Framework, bool Explicit);
158006d4ba38SDimitry Andric 
158148675466SDimitry Andric     /// Private modules are canonicalized as Foo_Private. Clang provides extra
158248675466SDimitry Andric     /// module map search logic to find the appropriate private module when PCH
158348675466SDimitry Andric     /// is used with implicit module maps. Warn when private modules are written
158448675466SDimitry Andric     /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
158548675466SDimitry Andric     void diagnosePrivateModules(SourceLocation ExplicitLoc,
158648675466SDimitry Andric                                 SourceLocation FrameworkLoc);
158748675466SDimitry Andric 
1588461a67faSDimitry Andric     using Attributes = ModuleMap::Attributes;
1589461a67faSDimitry Andric 
159013cc256eSDimitry Andric     bool parseOptionalAttributes(Attributes &Attrs);
1591dbe13110SDimitry Andric 
1592dbe13110SDimitry Andric   public:
ModuleMapParser(Lexer & L,SourceManager & SourceMgr,const TargetInfo * Target,DiagnosticsEngine & Diags,ModuleMap & Map,FileID ModuleMapFID,DirectoryEntryRef Directory,bool IsSystem)1593ac9a064cSDimitry Andric     ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
159448675466SDimitry Andric                     const TargetInfo *Target, DiagnosticsEngine &Diags,
1595ac9a064cSDimitry Andric                     ModuleMap &Map, FileID ModuleMapFID,
15967fa27ce4SDimitry Andric                     DirectoryEntryRef Directory, bool IsSystem)
159713cc256eSDimitry Andric         : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
1598ac9a064cSDimitry Andric           ModuleMapFID(ModuleMapFID), Directory(Directory), IsSystem(IsSystem) {
1599dbe13110SDimitry Andric       Tok.clear();
1600dbe13110SDimitry Andric       consumeToken();
1601dbe13110SDimitry Andric     }
1602dbe13110SDimitry Andric 
1603dbe13110SDimitry Andric     bool parseModuleMapFile();
16040a5fb09bSDimitry Andric 
terminatedByDirective()16050a5fb09bSDimitry Andric     bool terminatedByDirective() { return false; }
getLocation()16060a5fb09bSDimitry Andric     SourceLocation getLocation() { return Tok.getLocation(); }
1607dbe13110SDimitry Andric   };
1608461a67faSDimitry Andric 
1609461a67faSDimitry Andric } // namespace clang
1610dbe13110SDimitry Andric 
consumeToken()1611dbe13110SDimitry Andric SourceLocation ModuleMapParser::consumeToken() {
1612dbe13110SDimitry Andric   SourceLocation Result = Tok.getLocation();
1613dbe13110SDimitry Andric 
16140a5fb09bSDimitry Andric retry:
16150a5fb09bSDimitry Andric   Tok.clear();
1616dbe13110SDimitry Andric   Token LToken;
1617dbe13110SDimitry Andric   L.LexFromRawLexer(LToken);
1618dbe13110SDimitry Andric   Tok.Location = LToken.getLocation().getRawEncoding();
1619dbe13110SDimitry Andric   switch (LToken.getKind()) {
16209f4dbff6SDimitry Andric   case tok::raw_identifier: {
16219f4dbff6SDimitry Andric     StringRef RI = LToken.getRawIdentifier();
16229f4dbff6SDimitry Andric     Tok.StringData = RI.data();
16239f4dbff6SDimitry Andric     Tok.StringLength = RI.size();
16249f4dbff6SDimitry Andric     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
1625809500fcSDimitry Andric                  .Case("config_macros", MMToken::ConfigMacros)
1626809500fcSDimitry Andric                  .Case("conflict", MMToken::Conflict)
162713cc256eSDimitry Andric                  .Case("exclude", MMToken::ExcludeKeyword)
1628dbe13110SDimitry Andric                  .Case("explicit", MMToken::ExplicitKeyword)
1629dbe13110SDimitry Andric                  .Case("export", MMToken::ExportKeyword)
1630461a67faSDimitry Andric                  .Case("export_as", MMToken::ExportAsKeyword)
1631bfef3995SDimitry Andric                  .Case("extern", MMToken::ExternKeyword)
1632dbe13110SDimitry Andric                  .Case("framework", MMToken::FrameworkKeyword)
1633809500fcSDimitry Andric                  .Case("header", MMToken::HeaderKeyword)
1634809500fcSDimitry Andric                  .Case("link", MMToken::LinkKeyword)
1635dbe13110SDimitry Andric                  .Case("module", MMToken::ModuleKeyword)
1636bfef3995SDimitry Andric                  .Case("private", MMToken::PrivateKeyword)
1637dbe13110SDimitry Andric                  .Case("requires", MMToken::RequiresKeyword)
163806d4ba38SDimitry Andric                  .Case("textual", MMToken::TextualKeyword)
1639dbe13110SDimitry Andric                  .Case("umbrella", MMToken::UmbrellaKeyword)
1640bfef3995SDimitry Andric                  .Case("use", MMToken::UseKeyword)
1641dbe13110SDimitry Andric                  .Default(MMToken::Identifier);
1642dbe13110SDimitry Andric     break;
16439f4dbff6SDimitry Andric   }
1644dbe13110SDimitry Andric 
1645dbe13110SDimitry Andric   case tok::comma:
1646dbe13110SDimitry Andric     Tok.Kind = MMToken::Comma;
1647dbe13110SDimitry Andric     break;
1648dbe13110SDimitry Andric 
1649dbe13110SDimitry Andric   case tok::eof:
1650dbe13110SDimitry Andric     Tok.Kind = MMToken::EndOfFile;
1651dbe13110SDimitry Andric     break;
1652dbe13110SDimitry Andric 
1653dbe13110SDimitry Andric   case tok::l_brace:
1654dbe13110SDimitry Andric     Tok.Kind = MMToken::LBrace;
1655dbe13110SDimitry Andric     break;
1656dbe13110SDimitry Andric 
1657dbe13110SDimitry Andric   case tok::l_square:
1658dbe13110SDimitry Andric     Tok.Kind = MMToken::LSquare;
1659dbe13110SDimitry Andric     break;
1660dbe13110SDimitry Andric 
1661dbe13110SDimitry Andric   case tok::period:
1662dbe13110SDimitry Andric     Tok.Kind = MMToken::Period;
1663dbe13110SDimitry Andric     break;
1664dbe13110SDimitry Andric 
1665dbe13110SDimitry Andric   case tok::r_brace:
1666dbe13110SDimitry Andric     Tok.Kind = MMToken::RBrace;
1667dbe13110SDimitry Andric     break;
1668dbe13110SDimitry Andric 
1669dbe13110SDimitry Andric   case tok::r_square:
1670dbe13110SDimitry Andric     Tok.Kind = MMToken::RSquare;
1671dbe13110SDimitry Andric     break;
1672dbe13110SDimitry Andric 
1673dbe13110SDimitry Andric   case tok::star:
1674dbe13110SDimitry Andric     Tok.Kind = MMToken::Star;
1675dbe13110SDimitry Andric     break;
1676dbe13110SDimitry Andric 
1677bfef3995SDimitry Andric   case tok::exclaim:
1678bfef3995SDimitry Andric     Tok.Kind = MMToken::Exclaim;
1679bfef3995SDimitry Andric     break;
1680bfef3995SDimitry Andric 
1681dbe13110SDimitry Andric   case tok::string_literal: {
1682dbe13110SDimitry Andric     if (LToken.hasUDSuffix()) {
1683dbe13110SDimitry Andric       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
1684dbe13110SDimitry Andric       HadError = true;
1685dbe13110SDimitry Andric       goto retry;
1686dbe13110SDimitry Andric     }
1687dbe13110SDimitry Andric 
1688dbe13110SDimitry Andric     // Parse the string literal.
1689dbe13110SDimitry Andric     LangOptions LangOpts;
16909f4dbff6SDimitry Andric     StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
1691dbe13110SDimitry Andric     if (StringLiteral.hadError)
1692dbe13110SDimitry Andric       goto retry;
1693dbe13110SDimitry Andric 
1694dbe13110SDimitry Andric     // Copy the string literal into our string data allocator.
1695dbe13110SDimitry Andric     unsigned Length = StringLiteral.GetStringLength();
1696dbe13110SDimitry Andric     char *Saved = StringData.Allocate<char>(Length + 1);
1697dbe13110SDimitry Andric     memcpy(Saved, StringLiteral.GetString().data(), Length);
1698dbe13110SDimitry Andric     Saved[Length] = 0;
1699dbe13110SDimitry Andric 
1700dbe13110SDimitry Andric     // Form the token.
1701dbe13110SDimitry Andric     Tok.Kind = MMToken::StringLiteral;
1702dbe13110SDimitry Andric     Tok.StringData = Saved;
1703dbe13110SDimitry Andric     Tok.StringLength = Length;
1704dbe13110SDimitry Andric     break;
1705dbe13110SDimitry Andric   }
1706dbe13110SDimitry Andric 
1707551c6985SDimitry Andric   case tok::numeric_constant: {
1708551c6985SDimitry Andric     // We don't support any suffixes or other complications.
1709551c6985SDimitry Andric     SmallString<32> SpellingBuffer;
1710551c6985SDimitry Andric     SpellingBuffer.resize(LToken.getLength() + 1);
1711551c6985SDimitry Andric     const char *Start = SpellingBuffer.data();
1712551c6985SDimitry Andric     unsigned Length =
1713145449b1SDimitry Andric         Lexer::getSpelling(LToken, Start, SourceMgr, Map.LangOpts);
1714551c6985SDimitry Andric     uint64_t Value;
1715551c6985SDimitry Andric     if (StringRef(Start, Length).getAsInteger(0, Value)) {
1716551c6985SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1717551c6985SDimitry Andric       HadError = true;
1718551c6985SDimitry Andric       goto retry;
1719551c6985SDimitry Andric     }
1720551c6985SDimitry Andric 
1721551c6985SDimitry Andric     Tok.Kind = MMToken::IntegerLiteral;
1722551c6985SDimitry Andric     Tok.IntegerValue = Value;
1723551c6985SDimitry Andric     break;
1724551c6985SDimitry Andric   }
1725551c6985SDimitry Andric 
1726dbe13110SDimitry Andric   case tok::comment:
1727dbe13110SDimitry Andric     goto retry;
1728dbe13110SDimitry Andric 
17290a5fb09bSDimitry Andric   case tok::hash:
17300a5fb09bSDimitry Andric     // A module map can be terminated prematurely by
17310a5fb09bSDimitry Andric     //   #pragma clang module contents
17320a5fb09bSDimitry Andric     // When building the module, we'll treat the rest of the file as the
17330a5fb09bSDimitry Andric     // contents of the module.
17340a5fb09bSDimitry Andric     {
17350a5fb09bSDimitry Andric       auto NextIsIdent = [&](StringRef Str) -> bool {
17360a5fb09bSDimitry Andric         L.LexFromRawLexer(LToken);
17370a5fb09bSDimitry Andric         return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
17380a5fb09bSDimitry Andric                LToken.getRawIdentifier() == Str;
17390a5fb09bSDimitry Andric       };
17400a5fb09bSDimitry Andric       if (NextIsIdent("pragma") && NextIsIdent("clang") &&
17410a5fb09bSDimitry Andric           NextIsIdent("module") && NextIsIdent("contents")) {
17420a5fb09bSDimitry Andric         Tok.Kind = MMToken::EndOfFile;
17430a5fb09bSDimitry Andric         break;
17440a5fb09bSDimitry Andric       }
17450a5fb09bSDimitry Andric     }
1746e3b55780SDimitry Andric     [[fallthrough]];
17470a5fb09bSDimitry Andric 
1748dbe13110SDimitry Andric   default:
17490a5fb09bSDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1750dbe13110SDimitry Andric     HadError = true;
1751dbe13110SDimitry Andric     goto retry;
1752dbe13110SDimitry Andric   }
1753dbe13110SDimitry Andric 
1754dbe13110SDimitry Andric   return Result;
1755dbe13110SDimitry Andric }
1756dbe13110SDimitry Andric 
skipUntil(MMToken::TokenKind K)1757dbe13110SDimitry Andric void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
1758dbe13110SDimitry Andric   unsigned braceDepth = 0;
1759dbe13110SDimitry Andric   unsigned squareDepth = 0;
1760dbe13110SDimitry Andric   do {
1761dbe13110SDimitry Andric     switch (Tok.Kind) {
1762dbe13110SDimitry Andric     case MMToken::EndOfFile:
1763dbe13110SDimitry Andric       return;
1764dbe13110SDimitry Andric 
1765dbe13110SDimitry Andric     case MMToken::LBrace:
1766dbe13110SDimitry Andric       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1767dbe13110SDimitry Andric         return;
1768dbe13110SDimitry Andric 
1769dbe13110SDimitry Andric       ++braceDepth;
1770dbe13110SDimitry Andric       break;
1771dbe13110SDimitry Andric 
1772dbe13110SDimitry Andric     case MMToken::LSquare:
1773dbe13110SDimitry Andric       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1774dbe13110SDimitry Andric         return;
1775dbe13110SDimitry Andric 
1776dbe13110SDimitry Andric       ++squareDepth;
1777dbe13110SDimitry Andric       break;
1778dbe13110SDimitry Andric 
1779dbe13110SDimitry Andric     case MMToken::RBrace:
1780dbe13110SDimitry Andric       if (braceDepth > 0)
1781dbe13110SDimitry Andric         --braceDepth;
1782dbe13110SDimitry Andric       else if (Tok.is(K))
1783dbe13110SDimitry Andric         return;
1784dbe13110SDimitry Andric       break;
1785dbe13110SDimitry Andric 
1786dbe13110SDimitry Andric     case MMToken::RSquare:
1787dbe13110SDimitry Andric       if (squareDepth > 0)
1788dbe13110SDimitry Andric         --squareDepth;
1789dbe13110SDimitry Andric       else if (Tok.is(K))
1790dbe13110SDimitry Andric         return;
1791dbe13110SDimitry Andric       break;
1792dbe13110SDimitry Andric 
1793dbe13110SDimitry Andric     default:
1794dbe13110SDimitry Andric       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
1795dbe13110SDimitry Andric         return;
1796dbe13110SDimitry Andric       break;
1797dbe13110SDimitry Andric     }
1798dbe13110SDimitry Andric 
1799dbe13110SDimitry Andric    consumeToken();
1800dbe13110SDimitry Andric   } while (true);
1801dbe13110SDimitry Andric }
1802dbe13110SDimitry Andric 
180348675466SDimitry Andric /// Parse a module-id.
1804dbe13110SDimitry Andric ///
1805dbe13110SDimitry Andric ///   module-id:
1806dbe13110SDimitry Andric ///     identifier
1807dbe13110SDimitry Andric ///     identifier '.' module-id
1808dbe13110SDimitry Andric ///
1809dbe13110SDimitry Andric /// \returns true if an error occurred, false otherwise.
parseModuleId(ModuleId & Id)1810dbe13110SDimitry Andric bool ModuleMapParser::parseModuleId(ModuleId &Id) {
1811dbe13110SDimitry Andric   Id.clear();
1812dbe13110SDimitry Andric   do {
18139f4dbff6SDimitry Andric     if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1814cfca06d7SDimitry Andric       Id.push_back(
1815cfca06d7SDimitry Andric           std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
1816dbe13110SDimitry Andric       consumeToken();
1817dbe13110SDimitry Andric     } else {
1818dbe13110SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1819dbe13110SDimitry Andric       return true;
1820dbe13110SDimitry Andric     }
1821dbe13110SDimitry Andric 
1822dbe13110SDimitry Andric     if (!Tok.is(MMToken::Period))
1823dbe13110SDimitry Andric       break;
1824dbe13110SDimitry Andric 
1825dbe13110SDimitry Andric     consumeToken();
1826dbe13110SDimitry Andric   } while (true);
1827dbe13110SDimitry Andric 
1828dbe13110SDimitry Andric   return false;
1829dbe13110SDimitry Andric }
1830dbe13110SDimitry Andric 
1831dbe13110SDimitry Andric namespace {
1832461a67faSDimitry Andric 
183348675466SDimitry Andric   /// Enumerates the known attributes.
1834dbe13110SDimitry Andric   enum AttributeKind {
183548675466SDimitry Andric     /// An unknown attribute.
1836dbe13110SDimitry Andric     AT_unknown,
1837461a67faSDimitry Andric 
183848675466SDimitry Andric     /// The 'system' attribute.
1839809500fcSDimitry Andric     AT_system,
1840461a67faSDimitry Andric 
184148675466SDimitry Andric     /// The 'extern_c' attribute.
18429f4dbff6SDimitry Andric     AT_extern_c,
1843461a67faSDimitry Andric 
184448675466SDimitry Andric     /// The 'exhaustive' attribute.
1845bab175ecSDimitry Andric     AT_exhaustive,
1846461a67faSDimitry Andric 
184748675466SDimitry Andric     /// The 'no_undeclared_includes' attribute.
1848bab175ecSDimitry Andric     AT_no_undeclared_includes
1849dbe13110SDimitry Andric   };
1850461a67faSDimitry Andric 
1851461a67faSDimitry Andric } // namespace
1852dbe13110SDimitry Andric 
18536252156dSDimitry Andric /// Private modules are canonicalized as Foo_Private. Clang provides extra
18546252156dSDimitry Andric /// module map search logic to find the appropriate private module when PCH
18556252156dSDimitry Andric /// is used with implicit module maps. Warn when private modules are written
18566252156dSDimitry Andric /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
diagnosePrivateModules(SourceLocation ExplicitLoc,SourceLocation FrameworkLoc)185748675466SDimitry Andric void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
185848675466SDimitry Andric                                              SourceLocation FrameworkLoc) {
18596252156dSDimitry Andric   auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
186048675466SDimitry Andric                              const Module *M, SourceRange ReplLoc) {
18616252156dSDimitry Andric     auto D = Diags.Report(ActiveModule->DefinitionLoc,
18626252156dSDimitry Andric                           diag::note_mmap_rename_top_level_private_module);
18636252156dSDimitry Andric     D << BadName << M->Name;
186448675466SDimitry Andric     D << FixItHint::CreateReplacement(ReplLoc, Canonical);
18656252156dSDimitry Andric   };
18666252156dSDimitry Andric 
18676252156dSDimitry Andric   for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
18686252156dSDimitry Andric     auto const *M = E->getValue();
18696252156dSDimitry Andric     if (M->Directory != ActiveModule->Directory)
18706252156dSDimitry Andric       continue;
18716252156dSDimitry Andric 
18726252156dSDimitry Andric     SmallString<128> FullName(ActiveModule->getFullModuleName());
1873312c0ed1SDimitry Andric     if (!FullName.starts_with(M->Name) && !FullName.ends_with("Private"))
18746252156dSDimitry Andric       continue;
187548675466SDimitry Andric     SmallString<128> FixedPrivModDecl;
18766252156dSDimitry Andric     SmallString<128> Canonical(M->Name);
18776252156dSDimitry Andric     Canonical.append("_Private");
18786252156dSDimitry Andric 
18796252156dSDimitry Andric     // Foo.Private -> Foo_Private
18806252156dSDimitry Andric     if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
18816252156dSDimitry Andric         M->Name == ActiveModule->Parent->Name) {
18826252156dSDimitry Andric       Diags.Report(ActiveModule->DefinitionLoc,
18836252156dSDimitry Andric                    diag::warn_mmap_mismatched_private_submodule)
18846252156dSDimitry Andric           << FullName;
188548675466SDimitry Andric 
188648675466SDimitry Andric       SourceLocation FixItInitBegin = CurrModuleDeclLoc;
188748675466SDimitry Andric       if (FrameworkLoc.isValid())
188848675466SDimitry Andric         FixItInitBegin = FrameworkLoc;
188948675466SDimitry Andric       if (ExplicitLoc.isValid())
189048675466SDimitry Andric         FixItInitBegin = ExplicitLoc;
189148675466SDimitry Andric 
189248675466SDimitry Andric       if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
189348675466SDimitry Andric         FixedPrivModDecl.append("framework ");
189448675466SDimitry Andric       FixedPrivModDecl.append("module ");
189548675466SDimitry Andric       FixedPrivModDecl.append(Canonical);
189648675466SDimitry Andric 
189748675466SDimitry Andric       GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
189848675466SDimitry Andric                       SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
18996252156dSDimitry Andric       continue;
19006252156dSDimitry Andric     }
19016252156dSDimitry Andric 
19026252156dSDimitry Andric     // FooPrivate and whatnots -> Foo_Private
19036252156dSDimitry Andric     if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
19046252156dSDimitry Andric         ActiveModule->Name != Canonical) {
19056252156dSDimitry Andric       Diags.Report(ActiveModule->DefinitionLoc,
19066252156dSDimitry Andric                    diag::warn_mmap_mismatched_private_module_name)
19076252156dSDimitry Andric           << ActiveModule->Name;
190848675466SDimitry Andric       GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
190948675466SDimitry Andric                       SourceRange(ActiveModule->DefinitionLoc));
19106252156dSDimitry Andric     }
19116252156dSDimitry Andric   }
19126252156dSDimitry Andric }
19136252156dSDimitry Andric 
191448675466SDimitry Andric /// Parse a module declaration.
1915dbe13110SDimitry Andric ///
1916dbe13110SDimitry Andric ///   module-declaration:
1917bfef3995SDimitry Andric ///     'extern' 'module' module-id string-literal
1918dbe13110SDimitry Andric ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1919dbe13110SDimitry Andric ///       { module-member* }
1920dbe13110SDimitry Andric ///
1921dbe13110SDimitry Andric ///   module-member:
1922dbe13110SDimitry Andric ///     requires-declaration
1923dbe13110SDimitry Andric ///     header-declaration
1924dbe13110SDimitry Andric ///     submodule-declaration
1925dbe13110SDimitry Andric ///     export-declaration
1926461a67faSDimitry Andric ///     export-as-declaration
1927809500fcSDimitry Andric ///     link-declaration
1928dbe13110SDimitry Andric ///
1929dbe13110SDimitry Andric ///   submodule-declaration:
1930dbe13110SDimitry Andric ///     module-declaration
1931dbe13110SDimitry Andric ///     inferred-submodule-declaration
parseModuleDecl()1932dbe13110SDimitry Andric void ModuleMapParser::parseModuleDecl() {
1933dbe13110SDimitry Andric   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
1934bfef3995SDimitry Andric          Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
1935bfef3995SDimitry Andric   if (Tok.is(MMToken::ExternKeyword)) {
1936bfef3995SDimitry Andric     parseExternModuleDecl();
1937bfef3995SDimitry Andric     return;
1938bfef3995SDimitry Andric   }
1939bfef3995SDimitry Andric 
1940dbe13110SDimitry Andric   // Parse 'explicit' or 'framework' keyword, if present.
1941dbe13110SDimitry Andric   SourceLocation ExplicitLoc;
194248675466SDimitry Andric   SourceLocation FrameworkLoc;
1943dbe13110SDimitry Andric   bool Explicit = false;
1944dbe13110SDimitry Andric   bool Framework = false;
1945dbe13110SDimitry Andric 
1946dbe13110SDimitry Andric   // Parse 'explicit' keyword, if present.
1947dbe13110SDimitry Andric   if (Tok.is(MMToken::ExplicitKeyword)) {
1948dbe13110SDimitry Andric     ExplicitLoc = consumeToken();
1949dbe13110SDimitry Andric     Explicit = true;
1950dbe13110SDimitry Andric   }
1951dbe13110SDimitry Andric 
1952dbe13110SDimitry Andric   // Parse 'framework' keyword, if present.
1953dbe13110SDimitry Andric   if (Tok.is(MMToken::FrameworkKeyword)) {
195448675466SDimitry Andric     FrameworkLoc = consumeToken();
1955dbe13110SDimitry Andric     Framework = true;
1956dbe13110SDimitry Andric   }
1957dbe13110SDimitry Andric 
1958dbe13110SDimitry Andric   // Parse 'module' keyword.
1959dbe13110SDimitry Andric   if (!Tok.is(MMToken::ModuleKeyword)) {
1960dbe13110SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1961dbe13110SDimitry Andric     consumeToken();
1962dbe13110SDimitry Andric     HadError = true;
1963dbe13110SDimitry Andric     return;
1964dbe13110SDimitry Andric   }
196548675466SDimitry Andric   CurrModuleDeclLoc = consumeToken(); // 'module' keyword
1966dbe13110SDimitry Andric 
1967dbe13110SDimitry Andric   // If we have a wildcard for the module name, this is an inferred submodule.
1968dbe13110SDimitry Andric   // Parse it.
1969dbe13110SDimitry Andric   if (Tok.is(MMToken::Star))
197013cc256eSDimitry Andric     return parseInferredModuleDecl(Framework, Explicit);
1971dbe13110SDimitry Andric 
1972dbe13110SDimitry Andric   // Parse the module name.
1973dbe13110SDimitry Andric   ModuleId Id;
1974dbe13110SDimitry Andric   if (parseModuleId(Id)) {
1975dbe13110SDimitry Andric     HadError = true;
1976dbe13110SDimitry Andric     return;
1977dbe13110SDimitry Andric   }
1978dbe13110SDimitry Andric 
1979dbe13110SDimitry Andric   if (ActiveModule) {
1980dbe13110SDimitry Andric     if (Id.size() > 1) {
1981dbe13110SDimitry Andric       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1982dbe13110SDimitry Andric         << SourceRange(Id.front().second, Id.back().second);
1983dbe13110SDimitry Andric 
1984dbe13110SDimitry Andric       HadError = true;
1985dbe13110SDimitry Andric       return;
1986dbe13110SDimitry Andric     }
1987dbe13110SDimitry Andric   } else if (Id.size() == 1 && Explicit) {
1988dbe13110SDimitry Andric     // Top-level modules can't be explicit.
1989dbe13110SDimitry Andric     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1990dbe13110SDimitry Andric     Explicit = false;
1991dbe13110SDimitry Andric     ExplicitLoc = SourceLocation();
1992dbe13110SDimitry Andric     HadError = true;
1993dbe13110SDimitry Andric   }
1994dbe13110SDimitry Andric 
1995dbe13110SDimitry Andric   Module *PreviousActiveModule = ActiveModule;
1996dbe13110SDimitry Andric   if (Id.size() > 1) {
1997dbe13110SDimitry Andric     // This module map defines a submodule. Go find the module of which it
1998dbe13110SDimitry Andric     // is a submodule.
19999f4dbff6SDimitry Andric     ActiveModule = nullptr;
200006d4ba38SDimitry Andric     const Module *TopLevelModule = nullptr;
2001dbe13110SDimitry Andric     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
2002dbe13110SDimitry Andric       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
200306d4ba38SDimitry Andric         if (I == 0)
200406d4ba38SDimitry Andric           TopLevelModule = Next;
2005dbe13110SDimitry Andric         ActiveModule = Next;
2006dbe13110SDimitry Andric         continue;
2007dbe13110SDimitry Andric       }
2008dbe13110SDimitry Andric 
2009b60736ecSDimitry Andric       Diags.Report(Id[I].second, diag::err_mmap_missing_parent_module)
2010b60736ecSDimitry Andric           << Id[I].first << (ActiveModule != nullptr)
2011b60736ecSDimitry Andric           << (ActiveModule
2012b60736ecSDimitry Andric                   ? ActiveModule->getTopLevelModule()->getFullModuleName()
2013b60736ecSDimitry Andric                   : "");
2014dbe13110SDimitry Andric       HadError = true;
2015dbe13110SDimitry Andric     }
201606d4ba38SDimitry Andric 
2017b60736ecSDimitry Andric     if (TopLevelModule &&
2018ac9a064cSDimitry Andric         ModuleMapFID != Map.getContainingModuleMapFileID(TopLevelModule)) {
2019ac9a064cSDimitry Andric       assert(ModuleMapFID !=
2020ac9a064cSDimitry Andric                  Map.getModuleMapFileIDForUniquing(TopLevelModule) &&
202106d4ba38SDimitry Andric              "submodule defined in same file as 'module *' that allowed its "
202206d4ba38SDimitry Andric              "top-level module");
2023ac9a064cSDimitry Andric       Map.addAdditionalModuleMapFile(
2024ac9a064cSDimitry Andric           TopLevelModule, *SourceMgr.getFileEntryRefForID(ModuleMapFID));
202506d4ba38SDimitry Andric     }
2026dbe13110SDimitry Andric   }
2027dbe13110SDimitry Andric 
2028dbe13110SDimitry Andric   StringRef ModuleName = Id.back().first;
2029dbe13110SDimitry Andric   SourceLocation ModuleNameLoc = Id.back().second;
2030dbe13110SDimitry Andric 
2031dbe13110SDimitry Andric   // Parse the optional attribute list.
203213cc256eSDimitry Andric   Attributes Attrs;
20332b6b257fSDimitry Andric   if (parseOptionalAttributes(Attrs))
20342b6b257fSDimitry Andric     return;
20352b6b257fSDimitry Andric 
2036dbe13110SDimitry Andric   // Parse the opening brace.
2037dbe13110SDimitry Andric   if (!Tok.is(MMToken::LBrace)) {
2038dbe13110SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
2039dbe13110SDimitry Andric       << ModuleName;
2040dbe13110SDimitry Andric     HadError = true;
2041dbe13110SDimitry Andric     return;
2042dbe13110SDimitry Andric   }
2043dbe13110SDimitry Andric   SourceLocation LBraceLoc = consumeToken();
2044dbe13110SDimitry Andric 
2045dbe13110SDimitry Andric   // Determine whether this (sub)module has already been defined.
204648675466SDimitry Andric   Module *ShadowingModule = nullptr;
2047dbe13110SDimitry Andric   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
20482410013dSDimitry Andric     // We might see a (re)definition of a module that we already have a
20497fa27ce4SDimitry Andric     // definition for in four cases:
20502410013dSDimitry Andric     //  - If we loaded one definition from an AST file and we've just found a
20512410013dSDimitry Andric     //    corresponding definition in a module map file, or
20527fa27ce4SDimitry Andric     bool LoadedFromASTFile = Existing->IsFromModuleFile;
20537fa27ce4SDimitry Andric     //  - If we previously inferred this module from different module map file.
20547fa27ce4SDimitry Andric     bool Inferred = Existing->IsInferred;
20557fa27ce4SDimitry Andric     //  - If we're building a framework that vends a module map, we might've
20567fa27ce4SDimitry Andric     //    previously seen the one in intermediate products and now the system
20577fa27ce4SDimitry Andric     //    one.
20587fa27ce4SDimitry Andric     // FIXME: If we're parsing module map file that looks like this:
20597fa27ce4SDimitry Andric     //          framework module FW { ... }
20607fa27ce4SDimitry Andric     //          module FW.Sub { ... }
20617fa27ce4SDimitry Andric     //        We can't check the framework qualifier, since it's not attached to
20627fa27ce4SDimitry Andric     //        the definition of Sub. Checking that qualifier on \c Existing is
20637fa27ce4SDimitry Andric     //        not correct either, since we might've previously seen:
20647fa27ce4SDimitry Andric     //          module FW { ... }
20657fa27ce4SDimitry Andric     //          module FW.Sub { ... }
20667fa27ce4SDimitry Andric     //        We should enforce consistency of redefinitions so that we can rely
20677fa27ce4SDimitry Andric     //        that \c Existing is part of a framework iff the redefinition of FW
20687fa27ce4SDimitry Andric     //        we have just skipped had it too. Once we do that, stop checking
20697fa27ce4SDimitry Andric     //        the local framework qualifier and only rely on \c Existing.
20707fa27ce4SDimitry Andric     bool PartOfFramework = Framework || Existing->isPartOfFramework();
20712410013dSDimitry Andric     //  - If we're building a (preprocessed) module and we've just loaded the
20722410013dSDimitry Andric     //    module map file from which it was created.
20732410013dSDimitry Andric     bool ParsedAsMainInput =
20742410013dSDimitry Andric         Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
20752410013dSDimitry Andric         Map.LangOpts.CurrentModule == ModuleName &&
20762410013dSDimitry Andric         SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
20772410013dSDimitry Andric             SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
20787fa27ce4SDimitry Andric     if (LoadedFromASTFile || Inferred || PartOfFramework || ParsedAsMainInput) {
20797fa27ce4SDimitry Andric       ActiveModule = PreviousActiveModule;
2080dbe13110SDimitry Andric       // Skip the module definition.
2081dbe13110SDimitry Andric       skipUntil(MMToken::RBrace);
2082dbe13110SDimitry Andric       if (Tok.is(MMToken::RBrace))
2083dbe13110SDimitry Andric         consumeToken();
2084dbe13110SDimitry Andric       else {
2085dbe13110SDimitry Andric         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2086dbe13110SDimitry Andric         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2087dbe13110SDimitry Andric         HadError = true;
2088dbe13110SDimitry Andric       }
2089dbe13110SDimitry Andric       return;
2090dbe13110SDimitry Andric     }
2091dbe13110SDimitry Andric 
209248675466SDimitry Andric     if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
209348675466SDimitry Andric       ShadowingModule = Existing;
209448675466SDimitry Andric     } else {
209548675466SDimitry Andric       // This is not a shawdowed module decl, it is an illegal redefinition.
2096dbe13110SDimitry Andric       Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
2097dbe13110SDimitry Andric           << ModuleName;
2098dbe13110SDimitry Andric       Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
2099dbe13110SDimitry Andric 
2100dbe13110SDimitry Andric       // Skip the module definition.
2101dbe13110SDimitry Andric       skipUntil(MMToken::RBrace);
2102dbe13110SDimitry Andric       if (Tok.is(MMToken::RBrace))
2103dbe13110SDimitry Andric         consumeToken();
2104dbe13110SDimitry Andric 
2105dbe13110SDimitry Andric       HadError = true;
2106dbe13110SDimitry Andric       return;
2107dbe13110SDimitry Andric     }
210848675466SDimitry Andric   }
2109dbe13110SDimitry Andric 
2110dbe13110SDimitry Andric   // Start defining this module.
211148675466SDimitry Andric   if (ShadowingModule) {
211248675466SDimitry Andric     ActiveModule =
211348675466SDimitry Andric         Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
211448675466SDimitry Andric   } else {
211548675466SDimitry Andric     ActiveModule =
211648675466SDimitry Andric         Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
211748675466SDimitry Andric             .first;
211848675466SDimitry Andric   }
211948675466SDimitry Andric 
2120dbe13110SDimitry Andric   ActiveModule->DefinitionLoc = ModuleNameLoc;
2121bfef3995SDimitry Andric   if (Attrs.IsSystem || IsSystem)
2122dbe13110SDimitry Andric     ActiveModule->IsSystem = true;
21239f4dbff6SDimitry Andric   if (Attrs.IsExternC)
21249f4dbff6SDimitry Andric     ActiveModule->IsExternC = true;
2125e3b55780SDimitry Andric   if (Attrs.NoUndeclaredIncludes)
2126bab175ecSDimitry Andric     ActiveModule->NoUndeclaredIncludes = true;
212706d4ba38SDimitry Andric   ActiveModule->Directory = Directory;
2128dbe13110SDimitry Andric 
2129ac9a064cSDimitry Andric   StringRef MapFileName(
2130ac9a064cSDimitry Andric       SourceMgr.getFileEntryRefForID(ModuleMapFID)->getName());
2131312c0ed1SDimitry Andric   if (MapFileName.ends_with("module.private.modulemap") ||
2132312c0ed1SDimitry Andric       MapFileName.ends_with("module_private.map")) {
213348675466SDimitry Andric     ActiveModule->ModuleMapIsPrivate = true;
213448675466SDimitry Andric   }
21356252156dSDimitry Andric 
21366252156dSDimitry Andric   // Private modules named as FooPrivate, Foo.Private or similar are likely a
21376252156dSDimitry Andric   // user error; provide warnings, notes and fixits to direct users to use
21386252156dSDimitry Andric   // Foo_Private instead.
21396252156dSDimitry Andric   SourceLocation StartLoc =
21406252156dSDimitry Andric       SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
21416252156dSDimitry Andric   if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
21426252156dSDimitry Andric       !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
21436252156dSDimitry Andric                        StartLoc) &&
21446252156dSDimitry Andric       !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
21456252156dSDimitry Andric                        StartLoc) &&
214648675466SDimitry Andric       ActiveModule->ModuleMapIsPrivate)
214748675466SDimitry Andric     diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
2148bab175ecSDimitry Andric 
2149dbe13110SDimitry Andric   bool Done = false;
2150dbe13110SDimitry Andric   do {
2151dbe13110SDimitry Andric     switch (Tok.Kind) {
2152dbe13110SDimitry Andric     case MMToken::EndOfFile:
2153dbe13110SDimitry Andric     case MMToken::RBrace:
2154dbe13110SDimitry Andric       Done = true;
2155dbe13110SDimitry Andric       break;
2156dbe13110SDimitry Andric 
2157809500fcSDimitry Andric     case MMToken::ConfigMacros:
2158809500fcSDimitry Andric       parseConfigMacros();
2159809500fcSDimitry Andric       break;
2160809500fcSDimitry Andric 
2161809500fcSDimitry Andric     case MMToken::Conflict:
2162809500fcSDimitry Andric       parseConflict();
2163809500fcSDimitry Andric       break;
2164809500fcSDimitry Andric 
2165dbe13110SDimitry Andric     case MMToken::ExplicitKeyword:
2166bfef3995SDimitry Andric     case MMToken::ExternKeyword:
2167dbe13110SDimitry Andric     case MMToken::FrameworkKeyword:
2168dbe13110SDimitry Andric     case MMToken::ModuleKeyword:
2169dbe13110SDimitry Andric       parseModuleDecl();
2170dbe13110SDimitry Andric       break;
2171dbe13110SDimitry Andric 
2172dbe13110SDimitry Andric     case MMToken::ExportKeyword:
2173dbe13110SDimitry Andric       parseExportDecl();
2174dbe13110SDimitry Andric       break;
2175dbe13110SDimitry Andric 
2176461a67faSDimitry Andric     case MMToken::ExportAsKeyword:
2177461a67faSDimitry Andric       parseExportAsDecl();
2178461a67faSDimitry Andric       break;
2179461a67faSDimitry Andric 
2180bfef3995SDimitry Andric     case MMToken::UseKeyword:
2181bfef3995SDimitry Andric       parseUseDecl();
2182bfef3995SDimitry Andric       break;
2183bfef3995SDimitry Andric 
2184dbe13110SDimitry Andric     case MMToken::RequiresKeyword:
2185dbe13110SDimitry Andric       parseRequiresDecl();
2186dbe13110SDimitry Andric       break;
2187dbe13110SDimitry Andric 
218806d4ba38SDimitry Andric     case MMToken::TextualKeyword:
218906d4ba38SDimitry Andric       parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
219006d4ba38SDimitry Andric       break;
219106d4ba38SDimitry Andric 
2192dbe13110SDimitry Andric     case MMToken::UmbrellaKeyword: {
2193dbe13110SDimitry Andric       SourceLocation UmbrellaLoc = consumeToken();
2194dbe13110SDimitry Andric       if (Tok.is(MMToken::HeaderKeyword))
2195bfef3995SDimitry Andric         parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
2196dbe13110SDimitry Andric       else
2197dbe13110SDimitry Andric         parseUmbrellaDirDecl(UmbrellaLoc);
2198dbe13110SDimitry Andric       break;
2199dbe13110SDimitry Andric     }
2200dbe13110SDimitry Andric 
220106d4ba38SDimitry Andric     case MMToken::ExcludeKeyword:
220206d4ba38SDimitry Andric       parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
220313cc256eSDimitry Andric       break;
220413cc256eSDimitry Andric 
220506d4ba38SDimitry Andric     case MMToken::PrivateKeyword:
220606d4ba38SDimitry Andric       parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
2207bfef3995SDimitry Andric       break;
2208bfef3995SDimitry Andric 
2209dbe13110SDimitry Andric     case MMToken::HeaderKeyword:
221006d4ba38SDimitry Andric       parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
2211dbe13110SDimitry Andric       break;
2212dbe13110SDimitry Andric 
2213809500fcSDimitry Andric     case MMToken::LinkKeyword:
2214809500fcSDimitry Andric       parseLinkDecl();
2215809500fcSDimitry Andric       break;
2216809500fcSDimitry Andric 
2217dbe13110SDimitry Andric     default:
2218dbe13110SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
2219dbe13110SDimitry Andric       consumeToken();
2220dbe13110SDimitry Andric       break;
2221dbe13110SDimitry Andric     }
2222dbe13110SDimitry Andric   } while (!Done);
2223dbe13110SDimitry Andric 
2224dbe13110SDimitry Andric   if (Tok.is(MMToken::RBrace))
2225dbe13110SDimitry Andric     consumeToken();
2226dbe13110SDimitry Andric   else {
2227dbe13110SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2228dbe13110SDimitry Andric     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2229dbe13110SDimitry Andric     HadError = true;
2230dbe13110SDimitry Andric   }
2231dbe13110SDimitry Andric 
2232809500fcSDimitry Andric   // If the active module is a top-level framework, and there are no link
2233809500fcSDimitry Andric   // libraries, automatically link against the framework.
2234809500fcSDimitry Andric   if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
22357fa27ce4SDimitry Andric       ActiveModule->LinkLibraries.empty())
22367fa27ce4SDimitry Andric     inferFrameworkLink(ActiveModule);
2237809500fcSDimitry Andric 
22389f4dbff6SDimitry Andric   // If the module meets all requirements but is still unavailable, mark the
22399f4dbff6SDimitry Andric   // whole tree as unavailable to prevent it from building.
2240cfca06d7SDimitry Andric   if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
22419f4dbff6SDimitry Andric       ActiveModule->Parent) {
2242cfca06d7SDimitry Andric     ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false);
22439f4dbff6SDimitry Andric     ActiveModule->getTopLevelModule()->MissingHeaders.append(
22449f4dbff6SDimitry Andric       ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
22459f4dbff6SDimitry Andric   }
22469f4dbff6SDimitry Andric 
2247dbe13110SDimitry Andric   // We're done parsing this module. Pop back to the previous module.
2248dbe13110SDimitry Andric   ActiveModule = PreviousActiveModule;
2249dbe13110SDimitry Andric }
2250dbe13110SDimitry Andric 
225148675466SDimitry Andric /// Parse an extern module declaration.
2252bfef3995SDimitry Andric ///
2253bfef3995SDimitry Andric ///   extern module-declaration:
2254bfef3995SDimitry Andric ///     'extern' 'module' module-id string-literal
parseExternModuleDecl()2255bfef3995SDimitry Andric void ModuleMapParser::parseExternModuleDecl() {
2256bfef3995SDimitry Andric   assert(Tok.is(MMToken::ExternKeyword));
225751ece4aaSDimitry Andric   SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
2258bfef3995SDimitry Andric 
2259bfef3995SDimitry Andric   // Parse 'module' keyword.
2260bfef3995SDimitry Andric   if (!Tok.is(MMToken::ModuleKeyword)) {
2261bfef3995SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
2262bfef3995SDimitry Andric     consumeToken();
2263bfef3995SDimitry Andric     HadError = true;
2264bfef3995SDimitry Andric     return;
2265bfef3995SDimitry Andric   }
2266bfef3995SDimitry Andric   consumeToken(); // 'module' keyword
2267bfef3995SDimitry Andric 
2268bfef3995SDimitry Andric   // Parse the module name.
2269bfef3995SDimitry Andric   ModuleId Id;
2270bfef3995SDimitry Andric   if (parseModuleId(Id)) {
2271bfef3995SDimitry Andric     HadError = true;
2272bfef3995SDimitry Andric     return;
2273bfef3995SDimitry Andric   }
2274bfef3995SDimitry Andric 
2275bfef3995SDimitry Andric   // Parse the referenced module map file name.
2276bfef3995SDimitry Andric   if (!Tok.is(MMToken::StringLiteral)) {
2277bfef3995SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
2278bfef3995SDimitry Andric     HadError = true;
2279bfef3995SDimitry Andric     return;
2280bfef3995SDimitry Andric   }
2281cfca06d7SDimitry Andric   std::string FileName = std::string(Tok.getString());
2282bfef3995SDimitry Andric   consumeToken(); // filename
2283bfef3995SDimitry Andric 
2284bfef3995SDimitry Andric   StringRef FileNameRef = FileName;
2285bfef3995SDimitry Andric   SmallString<128> ModuleMapFileName;
2286bfef3995SDimitry Andric   if (llvm::sys::path::is_relative(FileNameRef)) {
22877fa27ce4SDimitry Andric     ModuleMapFileName += Directory.getName();
2288bfef3995SDimitry Andric     llvm::sys::path::append(ModuleMapFileName, FileName);
22895e20cdd8SDimitry Andric     FileNameRef = ModuleMapFileName;
2290bfef3995SDimitry Andric   }
22917fa27ce4SDimitry Andric   if (auto File = SourceMgr.getFileManager().getOptionalFileRef(FileNameRef))
229206d4ba38SDimitry Andric     Map.parseModuleMapFile(
2293c0981da4SDimitry Andric         *File, IsSystem,
229406d4ba38SDimitry Andric         Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
229506d4ba38SDimitry Andric             ? Directory
22967fa27ce4SDimitry Andric             : File->getDir(),
22970a5fb09bSDimitry Andric         FileID(), nullptr, ExternLoc);
2298bfef3995SDimitry Andric }
2299bfef3995SDimitry Andric 
230045b53394SDimitry Andric /// Whether to add the requirement \p Feature to the module \p M.
230145b53394SDimitry Andric ///
230245b53394SDimitry Andric /// This preserves backwards compatibility for two hacks in the Darwin system
230345b53394SDimitry Andric /// module map files:
230445b53394SDimitry Andric ///
230545b53394SDimitry Andric /// 1. The use of 'requires excluded' to make headers non-modular, which
230645b53394SDimitry Andric ///    should really be mapped to 'textual' now that we have this feature.  We
230745b53394SDimitry Andric ///    drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
230845b53394SDimitry Andric ///    true.  Later, this bit will be used to map all the headers inside this
230945b53394SDimitry Andric ///    module to 'textual'.
231045b53394SDimitry Andric ///
231145b53394SDimitry Andric ///    This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
231245b53394SDimitry Andric ///
231345b53394SDimitry Andric /// 2. Removes a bogus cplusplus requirement from IOKit.avc.  This requirement
231445b53394SDimitry Andric ///    was never correct and causes issues now that we check it, so drop it.
shouldAddRequirement(Module * M,StringRef Feature,bool & IsRequiresExcludedHack)231545b53394SDimitry Andric static bool shouldAddRequirement(Module *M, StringRef Feature,
231645b53394SDimitry Andric                                  bool &IsRequiresExcludedHack) {
2317bab175ecSDimitry Andric   if (Feature == "excluded" &&
2318bab175ecSDimitry Andric       (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
2319bab175ecSDimitry Andric        M->fullModuleNameIs({"Tcl", "Private"}))) {
232045b53394SDimitry Andric     IsRequiresExcludedHack = true;
232145b53394SDimitry Andric     return false;
2322bab175ecSDimitry Andric   } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
232345b53394SDimitry Andric     return false;
232445b53394SDimitry Andric   }
232545b53394SDimitry Andric 
232645b53394SDimitry Andric   return true;
232745b53394SDimitry Andric }
232845b53394SDimitry Andric 
232948675466SDimitry Andric /// Parse a requires declaration.
2330dbe13110SDimitry Andric ///
2331dbe13110SDimitry Andric ///   requires-declaration:
2332dbe13110SDimitry Andric ///     'requires' feature-list
2333dbe13110SDimitry Andric ///
2334dbe13110SDimitry Andric ///   feature-list:
2335bfef3995SDimitry Andric ///     feature ',' feature-list
2336bfef3995SDimitry Andric ///     feature
2337bfef3995SDimitry Andric ///
2338bfef3995SDimitry Andric ///   feature:
2339bfef3995SDimitry Andric ///     '!'[opt] identifier
parseRequiresDecl()2340dbe13110SDimitry Andric void ModuleMapParser::parseRequiresDecl() {
2341dbe13110SDimitry Andric   assert(Tok.is(MMToken::RequiresKeyword));
2342dbe13110SDimitry Andric 
2343dbe13110SDimitry Andric   // Parse 'requires' keyword.
2344dbe13110SDimitry Andric   consumeToken();
2345dbe13110SDimitry Andric 
2346dbe13110SDimitry Andric   // Parse the feature-list.
2347dbe13110SDimitry Andric   do {
2348bfef3995SDimitry Andric     bool RequiredState = true;
2349bfef3995SDimitry Andric     if (Tok.is(MMToken::Exclaim)) {
2350bfef3995SDimitry Andric       RequiredState = false;
2351bfef3995SDimitry Andric       consumeToken();
2352bfef3995SDimitry Andric     }
2353bfef3995SDimitry Andric 
2354dbe13110SDimitry Andric     if (!Tok.is(MMToken::Identifier)) {
2355dbe13110SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
2356dbe13110SDimitry Andric       HadError = true;
2357dbe13110SDimitry Andric       return;
2358dbe13110SDimitry Andric     }
2359dbe13110SDimitry Andric 
2360dbe13110SDimitry Andric     // Consume the feature name.
2361cfca06d7SDimitry Andric     std::string Feature = std::string(Tok.getString());
2362dbe13110SDimitry Andric     consumeToken();
2363dbe13110SDimitry Andric 
236445b53394SDimitry Andric     bool IsRequiresExcludedHack = false;
236545b53394SDimitry Andric     bool ShouldAddRequirement =
236645b53394SDimitry Andric         shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
236745b53394SDimitry Andric 
236845b53394SDimitry Andric     if (IsRequiresExcludedHack)
236945b53394SDimitry Andric       UsesRequiresExcludedHack.insert(ActiveModule);
237045b53394SDimitry Andric 
237145b53394SDimitry Andric     if (ShouldAddRequirement) {
2372dbe13110SDimitry Andric       // Add this feature.
237345b53394SDimitry Andric       ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
237445b53394SDimitry Andric                                    *Map.Target);
237545b53394SDimitry Andric     }
2376dbe13110SDimitry Andric 
2377dbe13110SDimitry Andric     if (!Tok.is(MMToken::Comma))
2378dbe13110SDimitry Andric       break;
2379dbe13110SDimitry Andric 
2380dbe13110SDimitry Andric     // Consume the comma.
2381dbe13110SDimitry Andric     consumeToken();
2382dbe13110SDimitry Andric   } while (true);
2383dbe13110SDimitry Andric }
2384dbe13110SDimitry Andric 
238548675466SDimitry Andric /// Parse a header declaration.
2386dbe13110SDimitry Andric ///
2387dbe13110SDimitry Andric ///   header-declaration:
238806d4ba38SDimitry Andric ///     'textual'[opt] 'header' string-literal
238906d4ba38SDimitry Andric ///     'private' 'textual'[opt] 'header' string-literal
239006d4ba38SDimitry Andric ///     'exclude' 'header' string-literal
239106d4ba38SDimitry Andric ///     'umbrella' 'header' string-literal
239206d4ba38SDimitry Andric ///
239306d4ba38SDimitry Andric /// FIXME: Support 'private textual header'.
parseHeaderDecl(MMToken::TokenKind LeadingToken,SourceLocation LeadingLoc)2394bfef3995SDimitry Andric void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
2395bfef3995SDimitry Andric                                       SourceLocation LeadingLoc) {
239606d4ba38SDimitry Andric   // We've already consumed the first token.
239706d4ba38SDimitry Andric   ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
2398e3b55780SDimitry Andric 
239906d4ba38SDimitry Andric   if (LeadingToken == MMToken::PrivateKeyword) {
240006d4ba38SDimitry Andric     Role = ModuleMap::PrivateHeader;
240106d4ba38SDimitry Andric     // 'private' may optionally be followed by 'textual'.
240206d4ba38SDimitry Andric     if (Tok.is(MMToken::TextualKeyword)) {
240306d4ba38SDimitry Andric       LeadingToken = Tok.Kind;
2404dbe13110SDimitry Andric       consumeToken();
240506d4ba38SDimitry Andric     }
2406e3b55780SDimitry Andric   } else if (LeadingToken == MMToken::ExcludeKeyword) {
2407e3b55780SDimitry Andric     Role = ModuleMap::ExcludedHeader;
240806d4ba38SDimitry Andric   }
240945b53394SDimitry Andric 
241006d4ba38SDimitry Andric   if (LeadingToken == MMToken::TextualKeyword)
241106d4ba38SDimitry Andric     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
241206d4ba38SDimitry Andric 
241345b53394SDimitry Andric   if (UsesRequiresExcludedHack.count(ActiveModule)) {
241445b53394SDimitry Andric     // Mark this header 'textual' (see doc comment for
241545b53394SDimitry Andric     // Module::UsesRequiresExcludedHack).
241645b53394SDimitry Andric     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
241745b53394SDimitry Andric   }
241845b53394SDimitry Andric 
241906d4ba38SDimitry Andric   if (LeadingToken != MMToken::HeaderKeyword) {
242006d4ba38SDimitry Andric     if (!Tok.is(MMToken::HeaderKeyword)) {
242106d4ba38SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
242206d4ba38SDimitry Andric           << (LeadingToken == MMToken::PrivateKeyword ? "private" :
242306d4ba38SDimitry Andric               LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
242406d4ba38SDimitry Andric               LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
242506d4ba38SDimitry Andric       return;
242606d4ba38SDimitry Andric     }
242706d4ba38SDimitry Andric     consumeToken();
242806d4ba38SDimitry Andric   }
2429dbe13110SDimitry Andric 
2430dbe13110SDimitry Andric   // Parse the header name.
2431dbe13110SDimitry Andric   if (!Tok.is(MMToken::StringLiteral)) {
2432dbe13110SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2433dbe13110SDimitry Andric       << "header";
2434dbe13110SDimitry Andric     HadError = true;
2435dbe13110SDimitry Andric     return;
2436dbe13110SDimitry Andric   }
243706d4ba38SDimitry Andric   Module::UnresolvedHeaderDirective Header;
2438cfca06d7SDimitry Andric   Header.FileName = std::string(Tok.getString());
24399f4dbff6SDimitry Andric   Header.FileNameLoc = consumeToken();
2440b5aee35cSDimitry Andric   Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
2441e3b55780SDimitry Andric   Header.Kind = Map.headerRoleToKind(Role);
2442dbe13110SDimitry Andric 
2443dbe13110SDimitry Andric   // Check whether we already have an umbrella.
2444b1c73532SDimitry Andric   if (Header.IsUmbrella &&
2445b1c73532SDimitry Andric       !std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
24469f4dbff6SDimitry Andric     Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2447dbe13110SDimitry Andric       << ActiveModule->getFullModuleName();
2448dbe13110SDimitry Andric     HadError = true;
2449dbe13110SDimitry Andric     return;
2450dbe13110SDimitry Andric   }
2451dbe13110SDimitry Andric 
2452551c6985SDimitry Andric   // If we were given stat information, parse it so we can skip looking for
2453551c6985SDimitry Andric   // the file.
2454551c6985SDimitry Andric   if (Tok.is(MMToken::LBrace)) {
2455551c6985SDimitry Andric     SourceLocation LBraceLoc = consumeToken();
2456dbe13110SDimitry Andric 
2457551c6985SDimitry Andric     while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
2458551c6985SDimitry Andric       enum Attribute { Size, ModTime, Unknown };
2459551c6985SDimitry Andric       StringRef Str = Tok.getString();
2460551c6985SDimitry Andric       SourceLocation Loc = consumeToken();
2461551c6985SDimitry Andric       switch (llvm::StringSwitch<Attribute>(Str)
2462551c6985SDimitry Andric                   .Case("size", Size)
2463551c6985SDimitry Andric                   .Case("mtime", ModTime)
2464551c6985SDimitry Andric                   .Default(Unknown)) {
2465551c6985SDimitry Andric       case Size:
2466551c6985SDimitry Andric         if (Header.Size)
2467551c6985SDimitry Andric           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2468551c6985SDimitry Andric         if (!Tok.is(MMToken::IntegerLiteral)) {
2469551c6985SDimitry Andric           Diags.Report(Tok.getLocation(),
2470551c6985SDimitry Andric                        diag::err_mmap_invalid_header_attribute_value) << Str;
2471551c6985SDimitry Andric           skipUntil(MMToken::RBrace);
2472551c6985SDimitry Andric           break;
2473551c6985SDimitry Andric         }
2474551c6985SDimitry Andric         Header.Size = Tok.getInteger();
2475551c6985SDimitry Andric         consumeToken();
2476551c6985SDimitry Andric         break;
2477551c6985SDimitry Andric 
2478551c6985SDimitry Andric       case ModTime:
2479551c6985SDimitry Andric         if (Header.ModTime)
2480551c6985SDimitry Andric           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2481551c6985SDimitry Andric         if (!Tok.is(MMToken::IntegerLiteral)) {
2482551c6985SDimitry Andric           Diags.Report(Tok.getLocation(),
2483551c6985SDimitry Andric                        diag::err_mmap_invalid_header_attribute_value) << Str;
2484551c6985SDimitry Andric           skipUntil(MMToken::RBrace);
2485551c6985SDimitry Andric           break;
2486551c6985SDimitry Andric         }
2487551c6985SDimitry Andric         Header.ModTime = Tok.getInteger();
2488551c6985SDimitry Andric         consumeToken();
2489551c6985SDimitry Andric         break;
2490551c6985SDimitry Andric 
2491551c6985SDimitry Andric       case Unknown:
2492551c6985SDimitry Andric         Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
2493551c6985SDimitry Andric         skipUntil(MMToken::RBrace);
2494551c6985SDimitry Andric         break;
2495551c6985SDimitry Andric       }
2496dbe13110SDimitry Andric     }
2497dbe13110SDimitry Andric 
2498551c6985SDimitry Andric     if (Tok.is(MMToken::RBrace))
2499551c6985SDimitry Andric       consumeToken();
2500551c6985SDimitry Andric     else {
2501551c6985SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2502551c6985SDimitry Andric       Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2503dbe13110SDimitry Andric       HadError = true;
2504dbe13110SDimitry Andric     }
250506d4ba38SDimitry Andric   }
250606d4ba38SDimitry Andric 
250748675466SDimitry Andric   bool NeedsFramework = false;
2508ac9a064cSDimitry Andric   // Don't add headers to the builtin modules if the builtin headers belong to
2509ac9a064cSDimitry Andric   // the system modules, with the exception of __stddef_max_align_t.h which
2510ac9a064cSDimitry Andric   // always had its own module.
2511ac9a064cSDimitry Andric   if (!Map.LangOpts.BuiltinHeadersInSystemModules ||
2512ac9a064cSDimitry Andric       !isBuiltInModuleName(ActiveModule->getTopLevelModuleName()) ||
2513ac9a064cSDimitry Andric       ActiveModule->fullModuleNameIs({"_Builtin_stddef", "max_align_t"}))
251448675466SDimitry Andric     Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
251548675466SDimitry Andric 
25167fa27ce4SDimitry Andric   if (NeedsFramework)
251748675466SDimitry Andric     Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
251848675466SDimitry Andric       << ActiveModule->getFullModuleName()
251948675466SDimitry Andric       << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
2520dbe13110SDimitry Andric }
2521dbe13110SDimitry Andric 
compareModuleHeaders(const Module::Header & A,const Module::Header & B)2522b1c73532SDimitry Andric static bool compareModuleHeaders(const Module::Header &A,
2523b1c73532SDimitry Andric                                  const Module::Header &B) {
2524b1c73532SDimitry Andric   return A.NameAsWritten < B.NameAsWritten;
252545b53394SDimitry Andric }
252645b53394SDimitry Andric 
252748675466SDimitry Andric /// Parse an umbrella directory declaration.
2528dbe13110SDimitry Andric ///
2529dbe13110SDimitry Andric ///   umbrella-dir-declaration:
2530dbe13110SDimitry Andric ///     umbrella string-literal
parseUmbrellaDirDecl(SourceLocation UmbrellaLoc)2531dbe13110SDimitry Andric void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
2532dbe13110SDimitry Andric   // Parse the directory name.
2533dbe13110SDimitry Andric   if (!Tok.is(MMToken::StringLiteral)) {
2534dbe13110SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2535dbe13110SDimitry Andric       << "umbrella";
2536dbe13110SDimitry Andric     HadError = true;
2537dbe13110SDimitry Andric     return;
2538dbe13110SDimitry Andric   }
2539dbe13110SDimitry Andric 
2540cfca06d7SDimitry Andric   std::string DirName = std::string(Tok.getString());
2541344a3780SDimitry Andric   std::string DirNameAsWritten = DirName;
2542dbe13110SDimitry Andric   SourceLocation DirNameLoc = consumeToken();
2543dbe13110SDimitry Andric 
2544dbe13110SDimitry Andric   // Check whether we already have an umbrella.
2545b1c73532SDimitry Andric   if (!std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
2546dbe13110SDimitry Andric     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
2547dbe13110SDimitry Andric       << ActiveModule->getFullModuleName();
2548dbe13110SDimitry Andric     HadError = true;
2549dbe13110SDimitry Andric     return;
2550dbe13110SDimitry Andric   }
2551dbe13110SDimitry Andric 
2552dbe13110SDimitry Andric   // Look for this file.
25537fa27ce4SDimitry Andric   OptionalDirectoryEntryRef Dir;
2554519fc96cSDimitry Andric   if (llvm::sys::path::is_absolute(DirName)) {
25557fa27ce4SDimitry Andric     Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
2556519fc96cSDimitry Andric   } else {
2557dbe13110SDimitry Andric     SmallString<128> PathName;
25587fa27ce4SDimitry Andric     PathName = Directory.getName();
2559dbe13110SDimitry Andric     llvm::sys::path::append(PathName, DirName);
25607fa27ce4SDimitry Andric     Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(PathName);
2561dbe13110SDimitry Andric   }
2562dbe13110SDimitry Andric 
2563dbe13110SDimitry Andric   if (!Dir) {
2564583e75ccSDimitry Andric     Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
2565dbe13110SDimitry Andric       << DirName;
2566dbe13110SDimitry Andric     return;
2567dbe13110SDimitry Andric   }
2568dbe13110SDimitry Andric 
256945b53394SDimitry Andric   if (UsesRequiresExcludedHack.count(ActiveModule)) {
257045b53394SDimitry Andric     // Mark this header 'textual' (see doc comment for
257145b53394SDimitry Andric     // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
257245b53394SDimitry Andric     // directory is relatively expensive, in practice this only applies to the
257345b53394SDimitry Andric     // uncommonly used Tcl module on Darwin platforms.
257445b53394SDimitry Andric     std::error_code EC;
257545b53394SDimitry Andric     SmallVector<Module::Header, 6> Headers;
2576676fbe81SDimitry Andric     llvm::vfs::FileSystem &FS =
257722989816SDimitry Andric         SourceMgr.getFileManager().getVirtualFileSystem();
2578676fbe81SDimitry Andric     for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
257945b53394SDimitry Andric          I != E && !EC; I.increment(EC)) {
2580e3b55780SDimitry Andric       if (auto FE = SourceMgr.getFileManager().getOptionalFileRef(I->path())) {
25817fa27ce4SDimitry Andric         Module::Header Header = {"", std::string(I->path()), *FE};
258245b53394SDimitry Andric         Headers.push_back(std::move(Header));
258345b53394SDimitry Andric       }
258445b53394SDimitry Andric     }
258545b53394SDimitry Andric 
258645b53394SDimitry Andric     // Sort header paths so that the pcm doesn't depend on iteration order.
2587b1c73532SDimitry Andric     std::stable_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
258845b53394SDimitry Andric 
258945b53394SDimitry Andric     for (auto &Header : Headers)
259045b53394SDimitry Andric       Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
259145b53394SDimitry Andric     return;
259245b53394SDimitry Andric   }
259345b53394SDimitry Andric 
25947fa27ce4SDimitry Andric   if (Module *OwningModule = Map.UmbrellaDirs[*Dir]) {
2595dbe13110SDimitry Andric     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
2596dbe13110SDimitry Andric       << OwningModule->getFullModuleName();
2597dbe13110SDimitry Andric     HadError = true;
2598dbe13110SDimitry Andric     return;
2599dbe13110SDimitry Andric   }
2600dbe13110SDimitry Andric 
2601dbe13110SDimitry Andric   // Record this umbrella directory.
26027fa27ce4SDimitry Andric   Map.setUmbrellaDirAsWritten(ActiveModule, *Dir, DirNameAsWritten, DirName);
2603dbe13110SDimitry Andric }
2604dbe13110SDimitry Andric 
260548675466SDimitry Andric /// Parse a module export declaration.
2606dbe13110SDimitry Andric ///
2607dbe13110SDimitry Andric ///   export-declaration:
2608dbe13110SDimitry Andric ///     'export' wildcard-module-id
2609dbe13110SDimitry Andric ///
2610dbe13110SDimitry Andric ///   wildcard-module-id:
2611dbe13110SDimitry Andric ///     identifier
2612dbe13110SDimitry Andric ///     '*'
2613dbe13110SDimitry Andric ///     identifier '.' wildcard-module-id
parseExportDecl()2614dbe13110SDimitry Andric void ModuleMapParser::parseExportDecl() {
2615dbe13110SDimitry Andric   assert(Tok.is(MMToken::ExportKeyword));
2616dbe13110SDimitry Andric   SourceLocation ExportLoc = consumeToken();
2617dbe13110SDimitry Andric 
2618dbe13110SDimitry Andric   // Parse the module-id with an optional wildcard at the end.
2619dbe13110SDimitry Andric   ModuleId ParsedModuleId;
2620dbe13110SDimitry Andric   bool Wildcard = false;
2621dbe13110SDimitry Andric   do {
262206d4ba38SDimitry Andric     // FIXME: Support string-literal module names here.
2623dbe13110SDimitry Andric     if (Tok.is(MMToken::Identifier)) {
2624cfca06d7SDimitry Andric       ParsedModuleId.push_back(
2625cfca06d7SDimitry Andric           std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
2626dbe13110SDimitry Andric       consumeToken();
2627dbe13110SDimitry Andric 
2628dbe13110SDimitry Andric       if (Tok.is(MMToken::Period)) {
2629dbe13110SDimitry Andric         consumeToken();
2630dbe13110SDimitry Andric         continue;
2631dbe13110SDimitry Andric       }
2632dbe13110SDimitry Andric 
2633dbe13110SDimitry Andric       break;
2634dbe13110SDimitry Andric     }
2635dbe13110SDimitry Andric 
2636dbe13110SDimitry Andric     if(Tok.is(MMToken::Star)) {
2637dbe13110SDimitry Andric       Wildcard = true;
2638dbe13110SDimitry Andric       consumeToken();
2639dbe13110SDimitry Andric       break;
2640dbe13110SDimitry Andric     }
2641dbe13110SDimitry Andric 
2642bfef3995SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
2643dbe13110SDimitry Andric     HadError = true;
2644dbe13110SDimitry Andric     return;
2645dbe13110SDimitry Andric   } while (true);
2646dbe13110SDimitry Andric 
2647dbe13110SDimitry Andric   Module::UnresolvedExportDecl Unresolved = {
2648dbe13110SDimitry Andric     ExportLoc, ParsedModuleId, Wildcard
2649dbe13110SDimitry Andric   };
2650dbe13110SDimitry Andric   ActiveModule->UnresolvedExports.push_back(Unresolved);
2651dbe13110SDimitry Andric }
2652dbe13110SDimitry Andric 
265348675466SDimitry Andric /// Parse a module export_as declaration.
2654461a67faSDimitry Andric ///
2655461a67faSDimitry Andric ///   export-as-declaration:
2656461a67faSDimitry Andric ///     'export_as' identifier
parseExportAsDecl()2657461a67faSDimitry Andric void ModuleMapParser::parseExportAsDecl() {
2658461a67faSDimitry Andric   assert(Tok.is(MMToken::ExportAsKeyword));
2659461a67faSDimitry Andric   consumeToken();
2660461a67faSDimitry Andric 
2661461a67faSDimitry Andric   if (!Tok.is(MMToken::Identifier)) {
2662461a67faSDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
2663461a67faSDimitry Andric     HadError = true;
2664461a67faSDimitry Andric     return;
2665461a67faSDimitry Andric   }
2666461a67faSDimitry Andric 
2667461a67faSDimitry Andric   if (ActiveModule->Parent) {
2668461a67faSDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
2669461a67faSDimitry Andric     consumeToken();
2670461a67faSDimitry Andric     return;
2671461a67faSDimitry Andric   }
2672461a67faSDimitry Andric 
2673461a67faSDimitry Andric   if (!ActiveModule->ExportAsModule.empty()) {
2674461a67faSDimitry Andric     if (ActiveModule->ExportAsModule == Tok.getString()) {
2675461a67faSDimitry Andric       Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
2676461a67faSDimitry Andric         << ActiveModule->Name << Tok.getString();
2677461a67faSDimitry Andric     } else {
2678461a67faSDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
2679461a67faSDimitry Andric         << ActiveModule->Name << ActiveModule->ExportAsModule
2680461a67faSDimitry Andric         << Tok.getString();
2681461a67faSDimitry Andric     }
2682461a67faSDimitry Andric   }
2683461a67faSDimitry Andric 
2684cfca06d7SDimitry Andric   ActiveModule->ExportAsModule = std::string(Tok.getString());
268548675466SDimitry Andric   Map.addLinkAsDependency(ActiveModule);
268648675466SDimitry Andric 
2687461a67faSDimitry Andric   consumeToken();
2688461a67faSDimitry Andric }
2689461a67faSDimitry Andric 
269048675466SDimitry Andric /// Parse a module use declaration.
2691bfef3995SDimitry Andric ///
26925e20cdd8SDimitry Andric ///   use-declaration:
26935e20cdd8SDimitry Andric ///     'use' wildcard-module-id
parseUseDecl()2694bfef3995SDimitry Andric void ModuleMapParser::parseUseDecl() {
2695bfef3995SDimitry Andric   assert(Tok.is(MMToken::UseKeyword));
26965e20cdd8SDimitry Andric   auto KWLoc = consumeToken();
2697bfef3995SDimitry Andric   // Parse the module-id.
2698bfef3995SDimitry Andric   ModuleId ParsedModuleId;
26999f4dbff6SDimitry Andric   parseModuleId(ParsedModuleId);
2700bfef3995SDimitry Andric 
27015e20cdd8SDimitry Andric   if (ActiveModule->Parent)
27025e20cdd8SDimitry Andric     Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
27035e20cdd8SDimitry Andric   else
2704bfef3995SDimitry Andric     ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
2705bfef3995SDimitry Andric }
2706bfef3995SDimitry Andric 
270748675466SDimitry Andric /// Parse a link declaration.
2708809500fcSDimitry Andric ///
2709809500fcSDimitry Andric ///   module-declaration:
2710809500fcSDimitry Andric ///     'link' 'framework'[opt] string-literal
parseLinkDecl()2711809500fcSDimitry Andric void ModuleMapParser::parseLinkDecl() {
2712809500fcSDimitry Andric   assert(Tok.is(MMToken::LinkKeyword));
2713809500fcSDimitry Andric   SourceLocation LinkLoc = consumeToken();
2714809500fcSDimitry Andric 
2715809500fcSDimitry Andric   // Parse the optional 'framework' keyword.
2716809500fcSDimitry Andric   bool IsFramework = false;
2717809500fcSDimitry Andric   if (Tok.is(MMToken::FrameworkKeyword)) {
2718809500fcSDimitry Andric     consumeToken();
2719809500fcSDimitry Andric     IsFramework = true;
2720809500fcSDimitry Andric   }
2721809500fcSDimitry Andric 
2722809500fcSDimitry Andric   // Parse the library name
2723809500fcSDimitry Andric   if (!Tok.is(MMToken::StringLiteral)) {
2724809500fcSDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
2725809500fcSDimitry Andric       << IsFramework << SourceRange(LinkLoc);
2726809500fcSDimitry Andric     HadError = true;
2727809500fcSDimitry Andric     return;
2728809500fcSDimitry Andric   }
2729809500fcSDimitry Andric 
2730cfca06d7SDimitry Andric   std::string LibraryName = std::string(Tok.getString());
2731809500fcSDimitry Andric   consumeToken();
2732809500fcSDimitry Andric   ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
2733809500fcSDimitry Andric                                                             IsFramework));
2734809500fcSDimitry Andric }
2735809500fcSDimitry Andric 
273648675466SDimitry Andric /// Parse a configuration macro declaration.
2737809500fcSDimitry Andric ///
2738809500fcSDimitry Andric ///   module-declaration:
2739809500fcSDimitry Andric ///     'config_macros' attributes[opt] config-macro-list?
2740809500fcSDimitry Andric ///
2741809500fcSDimitry Andric ///   config-macro-list:
2742809500fcSDimitry Andric ///     identifier (',' identifier)?
parseConfigMacros()2743809500fcSDimitry Andric void ModuleMapParser::parseConfigMacros() {
2744809500fcSDimitry Andric   assert(Tok.is(MMToken::ConfigMacros));
2745809500fcSDimitry Andric   SourceLocation ConfigMacrosLoc = consumeToken();
2746809500fcSDimitry Andric 
2747809500fcSDimitry Andric   // Only top-level modules can have configuration macros.
2748809500fcSDimitry Andric   if (ActiveModule->Parent) {
2749809500fcSDimitry Andric     Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
2750809500fcSDimitry Andric   }
2751809500fcSDimitry Andric 
2752809500fcSDimitry Andric   // Parse the optional attributes.
2753809500fcSDimitry Andric   Attributes Attrs;
27542b6b257fSDimitry Andric   if (parseOptionalAttributes(Attrs))
27552b6b257fSDimitry Andric     return;
27562b6b257fSDimitry Andric 
2757809500fcSDimitry Andric   if (Attrs.IsExhaustive && !ActiveModule->Parent) {
2758809500fcSDimitry Andric     ActiveModule->ConfigMacrosExhaustive = true;
2759809500fcSDimitry Andric   }
2760809500fcSDimitry Andric 
2761809500fcSDimitry Andric   // If we don't have an identifier, we're done.
276206d4ba38SDimitry Andric   // FIXME: Support macros with the same name as a keyword here.
2763809500fcSDimitry Andric   if (!Tok.is(MMToken::Identifier))
2764809500fcSDimitry Andric     return;
2765809500fcSDimitry Andric 
2766809500fcSDimitry Andric   // Consume the first identifier.
2767809500fcSDimitry Andric   if (!ActiveModule->Parent) {
2768809500fcSDimitry Andric     ActiveModule->ConfigMacros.push_back(Tok.getString().str());
2769809500fcSDimitry Andric   }
2770809500fcSDimitry Andric   consumeToken();
2771809500fcSDimitry Andric 
2772809500fcSDimitry Andric   do {
2773809500fcSDimitry Andric     // If there's a comma, consume it.
2774809500fcSDimitry Andric     if (!Tok.is(MMToken::Comma))
2775809500fcSDimitry Andric       break;
2776809500fcSDimitry Andric     consumeToken();
2777809500fcSDimitry Andric 
2778809500fcSDimitry Andric     // We expect to see a macro name here.
277906d4ba38SDimitry Andric     // FIXME: Support macros with the same name as a keyword here.
2780809500fcSDimitry Andric     if (!Tok.is(MMToken::Identifier)) {
2781809500fcSDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
2782809500fcSDimitry Andric       break;
2783809500fcSDimitry Andric     }
2784809500fcSDimitry Andric 
2785809500fcSDimitry Andric     // Consume the macro name.
2786809500fcSDimitry Andric     if (!ActiveModule->Parent) {
2787809500fcSDimitry Andric       ActiveModule->ConfigMacros.push_back(Tok.getString().str());
2788809500fcSDimitry Andric     }
2789809500fcSDimitry Andric     consumeToken();
2790809500fcSDimitry Andric   } while (true);
2791809500fcSDimitry Andric }
2792809500fcSDimitry Andric 
279348675466SDimitry Andric /// Format a module-id into a string.
formatModuleId(const ModuleId & Id)2794809500fcSDimitry Andric static std::string formatModuleId(const ModuleId &Id) {
2795809500fcSDimitry Andric   std::string result;
2796809500fcSDimitry Andric   {
2797809500fcSDimitry Andric     llvm::raw_string_ostream OS(result);
2798809500fcSDimitry Andric 
2799809500fcSDimitry Andric     for (unsigned I = 0, N = Id.size(); I != N; ++I) {
2800809500fcSDimitry Andric       if (I)
2801809500fcSDimitry Andric         OS << ".";
2802809500fcSDimitry Andric       OS << Id[I].first;
2803809500fcSDimitry Andric     }
2804809500fcSDimitry Andric   }
2805809500fcSDimitry Andric 
2806809500fcSDimitry Andric   return result;
2807809500fcSDimitry Andric }
2808809500fcSDimitry Andric 
280948675466SDimitry Andric /// Parse a conflict declaration.
2810809500fcSDimitry Andric ///
2811809500fcSDimitry Andric ///   module-declaration:
2812809500fcSDimitry Andric ///     'conflict' module-id ',' string-literal
parseConflict()2813809500fcSDimitry Andric void ModuleMapParser::parseConflict() {
2814809500fcSDimitry Andric   assert(Tok.is(MMToken::Conflict));
2815809500fcSDimitry Andric   SourceLocation ConflictLoc = consumeToken();
2816809500fcSDimitry Andric   Module::UnresolvedConflict Conflict;
2817809500fcSDimitry Andric 
2818809500fcSDimitry Andric   // Parse the module-id.
2819809500fcSDimitry Andric   if (parseModuleId(Conflict.Id))
2820809500fcSDimitry Andric     return;
2821809500fcSDimitry Andric 
2822809500fcSDimitry Andric   // Parse the ','.
2823809500fcSDimitry Andric   if (!Tok.is(MMToken::Comma)) {
2824809500fcSDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
2825809500fcSDimitry Andric       << SourceRange(ConflictLoc);
2826809500fcSDimitry Andric     return;
2827809500fcSDimitry Andric   }
2828809500fcSDimitry Andric   consumeToken();
2829809500fcSDimitry Andric 
2830809500fcSDimitry Andric   // Parse the message.
2831809500fcSDimitry Andric   if (!Tok.is(MMToken::StringLiteral)) {
2832809500fcSDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
2833809500fcSDimitry Andric       << formatModuleId(Conflict.Id);
2834809500fcSDimitry Andric     return;
2835809500fcSDimitry Andric   }
2836809500fcSDimitry Andric   Conflict.Message = Tok.getString().str();
2837809500fcSDimitry Andric   consumeToken();
2838809500fcSDimitry Andric 
2839809500fcSDimitry Andric   // Add this unresolved conflict.
2840809500fcSDimitry Andric   ActiveModule->UnresolvedConflicts.push_back(Conflict);
2841809500fcSDimitry Andric }
2842809500fcSDimitry Andric 
284348675466SDimitry Andric /// Parse an inferred module declaration (wildcard modules).
284413cc256eSDimitry Andric ///
284513cc256eSDimitry Andric ///   module-declaration:
284613cc256eSDimitry Andric ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
284713cc256eSDimitry Andric ///       { inferred-module-member* }
284813cc256eSDimitry Andric ///
284913cc256eSDimitry Andric ///   inferred-module-member:
285013cc256eSDimitry Andric ///     'export' '*'
285113cc256eSDimitry Andric ///     'exclude' identifier
parseInferredModuleDecl(bool Framework,bool Explicit)285213cc256eSDimitry Andric void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
2853dbe13110SDimitry Andric   assert(Tok.is(MMToken::Star));
2854dbe13110SDimitry Andric   SourceLocation StarLoc = consumeToken();
2855dbe13110SDimitry Andric   bool Failed = false;
2856dbe13110SDimitry Andric 
2857dbe13110SDimitry Andric   // Inferred modules must be submodules.
285813cc256eSDimitry Andric   if (!ActiveModule && !Framework) {
2859dbe13110SDimitry Andric     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
2860dbe13110SDimitry Andric     Failed = true;
2861dbe13110SDimitry Andric   }
2862dbe13110SDimitry Andric 
286313cc256eSDimitry Andric   if (ActiveModule) {
2864dbe13110SDimitry Andric     // Inferred modules must have umbrella directories.
28659f4dbff6SDimitry Andric     if (!Failed && ActiveModule->IsAvailable &&
28667fa27ce4SDimitry Andric         !ActiveModule->getEffectiveUmbrellaDir()) {
2867dbe13110SDimitry Andric       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
2868dbe13110SDimitry Andric       Failed = true;
2869dbe13110SDimitry Andric     }
2870dbe13110SDimitry Andric 
2871dbe13110SDimitry Andric     // Check for redefinition of an inferred module.
2872dbe13110SDimitry Andric     if (!Failed && ActiveModule->InferSubmodules) {
2873dbe13110SDimitry Andric       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2874dbe13110SDimitry Andric       if (ActiveModule->InferredSubmoduleLoc.isValid())
2875dbe13110SDimitry Andric         Diags.Report(ActiveModule->InferredSubmoduleLoc,
2876dbe13110SDimitry Andric                      diag::note_mmap_prev_definition);
2877dbe13110SDimitry Andric       Failed = true;
2878dbe13110SDimitry Andric     }
2879dbe13110SDimitry Andric 
288013cc256eSDimitry Andric     // Check for the 'framework' keyword, which is not permitted here.
288113cc256eSDimitry Andric     if (Framework) {
288213cc256eSDimitry Andric       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
288313cc256eSDimitry Andric       Framework = false;
288413cc256eSDimitry Andric     }
288513cc256eSDimitry Andric   } else if (Explicit) {
288613cc256eSDimitry Andric     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
288713cc256eSDimitry Andric     Explicit = false;
288813cc256eSDimitry Andric   }
288913cc256eSDimitry Andric 
2890dbe13110SDimitry Andric   // If there were any problems with this inferred submodule, skip its body.
2891dbe13110SDimitry Andric   if (Failed) {
2892dbe13110SDimitry Andric     if (Tok.is(MMToken::LBrace)) {
2893dbe13110SDimitry Andric       consumeToken();
2894dbe13110SDimitry Andric       skipUntil(MMToken::RBrace);
2895dbe13110SDimitry Andric       if (Tok.is(MMToken::RBrace))
2896dbe13110SDimitry Andric         consumeToken();
2897dbe13110SDimitry Andric     }
2898dbe13110SDimitry Andric     HadError = true;
2899dbe13110SDimitry Andric     return;
2900dbe13110SDimitry Andric   }
2901dbe13110SDimitry Andric 
290213cc256eSDimitry Andric   // Parse optional attributes.
290313cc256eSDimitry Andric   Attributes Attrs;
29042b6b257fSDimitry Andric   if (parseOptionalAttributes(Attrs))
29052b6b257fSDimitry Andric     return;
290613cc256eSDimitry Andric 
290713cc256eSDimitry Andric   if (ActiveModule) {
2908dbe13110SDimitry Andric     // Note that we have an inferred submodule.
2909dbe13110SDimitry Andric     ActiveModule->InferSubmodules = true;
2910dbe13110SDimitry Andric     ActiveModule->InferredSubmoduleLoc = StarLoc;
2911dbe13110SDimitry Andric     ActiveModule->InferExplicitSubmodules = Explicit;
291213cc256eSDimitry Andric   } else {
291313cc256eSDimitry Andric     // We'll be inferring framework modules for this directory.
291413cc256eSDimitry Andric     Map.InferredDirectories[Directory].InferModules = true;
291506d4ba38SDimitry Andric     Map.InferredDirectories[Directory].Attrs = Attrs;
2916ac9a064cSDimitry Andric     Map.InferredDirectories[Directory].ModuleMapFID = ModuleMapFID;
29179f4dbff6SDimitry Andric     // FIXME: Handle the 'framework' keyword.
291813cc256eSDimitry Andric   }
2919dbe13110SDimitry Andric 
2920dbe13110SDimitry Andric   // Parse the opening brace.
2921dbe13110SDimitry Andric   if (!Tok.is(MMToken::LBrace)) {
2922dbe13110SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
2923dbe13110SDimitry Andric     HadError = true;
2924dbe13110SDimitry Andric     return;
2925dbe13110SDimitry Andric   }
2926dbe13110SDimitry Andric   SourceLocation LBraceLoc = consumeToken();
2927dbe13110SDimitry Andric 
2928dbe13110SDimitry Andric   // Parse the body of the inferred submodule.
2929dbe13110SDimitry Andric   bool Done = false;
2930dbe13110SDimitry Andric   do {
2931dbe13110SDimitry Andric     switch (Tok.Kind) {
2932dbe13110SDimitry Andric     case MMToken::EndOfFile:
2933dbe13110SDimitry Andric     case MMToken::RBrace:
2934dbe13110SDimitry Andric       Done = true;
2935dbe13110SDimitry Andric       break;
2936dbe13110SDimitry Andric 
2937461a67faSDimitry Andric     case MMToken::ExcludeKeyword:
293813cc256eSDimitry Andric       if (ActiveModule) {
293913cc256eSDimitry Andric         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
29409f4dbff6SDimitry Andric           << (ActiveModule != nullptr);
294113cc256eSDimitry Andric         consumeToken();
294213cc256eSDimitry Andric         break;
294313cc256eSDimitry Andric       }
294413cc256eSDimitry Andric 
294513cc256eSDimitry Andric       consumeToken();
294606d4ba38SDimitry Andric       // FIXME: Support string-literal module names here.
294713cc256eSDimitry Andric       if (!Tok.is(MMToken::Identifier)) {
294813cc256eSDimitry Andric         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
294913cc256eSDimitry Andric         break;
295013cc256eSDimitry Andric       }
295113cc256eSDimitry Andric 
2952cfca06d7SDimitry Andric       Map.InferredDirectories[Directory].ExcludedModules.push_back(
2953cfca06d7SDimitry Andric           std::string(Tok.getString()));
295413cc256eSDimitry Andric       consumeToken();
295513cc256eSDimitry Andric       break;
295613cc256eSDimitry Andric 
295713cc256eSDimitry Andric     case MMToken::ExportKeyword:
295813cc256eSDimitry Andric       if (!ActiveModule) {
295913cc256eSDimitry Andric         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
29609f4dbff6SDimitry Andric           << (ActiveModule != nullptr);
296113cc256eSDimitry Andric         consumeToken();
296213cc256eSDimitry Andric         break;
296313cc256eSDimitry Andric       }
296413cc256eSDimitry Andric 
2965dbe13110SDimitry Andric       consumeToken();
2966dbe13110SDimitry Andric       if (Tok.is(MMToken::Star))
2967dbe13110SDimitry Andric         ActiveModule->InferExportWildcard = true;
2968dbe13110SDimitry Andric       else
2969dbe13110SDimitry Andric         Diags.Report(Tok.getLocation(),
2970dbe13110SDimitry Andric                      diag::err_mmap_expected_export_wildcard);
2971dbe13110SDimitry Andric       consumeToken();
2972dbe13110SDimitry Andric       break;
2973dbe13110SDimitry Andric 
2974dbe13110SDimitry Andric     case MMToken::ExplicitKeyword:
2975dbe13110SDimitry Andric     case MMToken::ModuleKeyword:
2976dbe13110SDimitry Andric     case MMToken::HeaderKeyword:
2977bfef3995SDimitry Andric     case MMToken::PrivateKeyword:
2978dbe13110SDimitry Andric     case MMToken::UmbrellaKeyword:
2979dbe13110SDimitry Andric     default:
298013cc256eSDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
29819f4dbff6SDimitry Andric           << (ActiveModule != nullptr);
2982dbe13110SDimitry Andric       consumeToken();
2983dbe13110SDimitry Andric       break;
2984dbe13110SDimitry Andric     }
2985dbe13110SDimitry Andric   } while (!Done);
2986dbe13110SDimitry Andric 
2987dbe13110SDimitry Andric   if (Tok.is(MMToken::RBrace))
2988dbe13110SDimitry Andric     consumeToken();
2989dbe13110SDimitry Andric   else {
2990dbe13110SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2991dbe13110SDimitry Andric     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2992dbe13110SDimitry Andric     HadError = true;
2993dbe13110SDimitry Andric   }
2994dbe13110SDimitry Andric }
2995dbe13110SDimitry Andric 
299648675466SDimitry Andric /// Parse optional attributes.
299713cc256eSDimitry Andric ///
299813cc256eSDimitry Andric ///   attributes:
299913cc256eSDimitry Andric ///     attribute attributes
300013cc256eSDimitry Andric ///     attribute
300113cc256eSDimitry Andric ///
300213cc256eSDimitry Andric ///   attribute:
300313cc256eSDimitry Andric ///     [ identifier ]
300413cc256eSDimitry Andric ///
300513cc256eSDimitry Andric /// \param Attrs Will be filled in with the parsed attributes.
300613cc256eSDimitry Andric ///
300713cc256eSDimitry Andric /// \returns true if an error occurred, false otherwise.
parseOptionalAttributes(Attributes & Attrs)300813cc256eSDimitry Andric bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
300913cc256eSDimitry Andric   bool HadError = false;
301013cc256eSDimitry Andric 
301113cc256eSDimitry Andric   while (Tok.is(MMToken::LSquare)) {
301213cc256eSDimitry Andric     // Consume the '['.
301313cc256eSDimitry Andric     SourceLocation LSquareLoc = consumeToken();
301413cc256eSDimitry Andric 
301513cc256eSDimitry Andric     // Check whether we have an attribute name here.
301613cc256eSDimitry Andric     if (!Tok.is(MMToken::Identifier)) {
301713cc256eSDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
301813cc256eSDimitry Andric       skipUntil(MMToken::RSquare);
301913cc256eSDimitry Andric       if (Tok.is(MMToken::RSquare))
302013cc256eSDimitry Andric         consumeToken();
302113cc256eSDimitry Andric       HadError = true;
302213cc256eSDimitry Andric     }
302313cc256eSDimitry Andric 
302413cc256eSDimitry Andric     // Decode the attribute name.
302513cc256eSDimitry Andric     AttributeKind Attribute
302613cc256eSDimitry Andric       = llvm::StringSwitch<AttributeKind>(Tok.getString())
3027809500fcSDimitry Andric           .Case("exhaustive", AT_exhaustive)
30289f4dbff6SDimitry Andric           .Case("extern_c", AT_extern_c)
3029bab175ecSDimitry Andric           .Case("no_undeclared_includes", AT_no_undeclared_includes)
303013cc256eSDimitry Andric           .Case("system", AT_system)
303113cc256eSDimitry Andric           .Default(AT_unknown);
303213cc256eSDimitry Andric     switch (Attribute) {
303313cc256eSDimitry Andric     case AT_unknown:
303413cc256eSDimitry Andric       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
303513cc256eSDimitry Andric         << Tok.getString();
303613cc256eSDimitry Andric       break;
303713cc256eSDimitry Andric 
303813cc256eSDimitry Andric     case AT_system:
303913cc256eSDimitry Andric       Attrs.IsSystem = true;
304013cc256eSDimitry Andric       break;
3041809500fcSDimitry Andric 
30429f4dbff6SDimitry Andric     case AT_extern_c:
30439f4dbff6SDimitry Andric       Attrs.IsExternC = true;
30449f4dbff6SDimitry Andric       break;
30459f4dbff6SDimitry Andric 
3046809500fcSDimitry Andric     case AT_exhaustive:
3047809500fcSDimitry Andric       Attrs.IsExhaustive = true;
3048809500fcSDimitry Andric       break;
3049bab175ecSDimitry Andric 
3050bab175ecSDimitry Andric     case AT_no_undeclared_includes:
3051bab175ecSDimitry Andric       Attrs.NoUndeclaredIncludes = true;
3052bab175ecSDimitry Andric       break;
305313cc256eSDimitry Andric     }
305413cc256eSDimitry Andric     consumeToken();
305513cc256eSDimitry Andric 
305613cc256eSDimitry Andric     // Consume the ']'.
305713cc256eSDimitry Andric     if (!Tok.is(MMToken::RSquare)) {
305813cc256eSDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
305913cc256eSDimitry Andric       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
306013cc256eSDimitry Andric       skipUntil(MMToken::RSquare);
306113cc256eSDimitry Andric       HadError = true;
306213cc256eSDimitry Andric     }
306313cc256eSDimitry Andric 
306413cc256eSDimitry Andric     if (Tok.is(MMToken::RSquare))
306513cc256eSDimitry Andric       consumeToken();
306613cc256eSDimitry Andric   }
306713cc256eSDimitry Andric 
306813cc256eSDimitry Andric   return HadError;
306913cc256eSDimitry Andric }
307013cc256eSDimitry Andric 
307148675466SDimitry Andric /// Parse a module map file.
3072dbe13110SDimitry Andric ///
3073dbe13110SDimitry Andric ///   module-map-file:
3074dbe13110SDimitry Andric ///     module-declaration*
parseModuleMapFile()3075dbe13110SDimitry Andric bool ModuleMapParser::parseModuleMapFile() {
3076dbe13110SDimitry Andric   do {
3077dbe13110SDimitry Andric     switch (Tok.Kind) {
3078dbe13110SDimitry Andric     case MMToken::EndOfFile:
3079dbe13110SDimitry Andric       return HadError;
3080dbe13110SDimitry Andric 
3081dbe13110SDimitry Andric     case MMToken::ExplicitKeyword:
3082bfef3995SDimitry Andric     case MMToken::ExternKeyword:
3083dbe13110SDimitry Andric     case MMToken::ModuleKeyword:
3084dbe13110SDimitry Andric     case MMToken::FrameworkKeyword:
3085dbe13110SDimitry Andric       parseModuleDecl();
3086dbe13110SDimitry Andric       break;
3087dbe13110SDimitry Andric 
3088dbe13110SDimitry Andric     case MMToken::Comma:
3089809500fcSDimitry Andric     case MMToken::ConfigMacros:
3090809500fcSDimitry Andric     case MMToken::Conflict:
3091bfef3995SDimitry Andric     case MMToken::Exclaim:
309213cc256eSDimitry Andric     case MMToken::ExcludeKeyword:
3093dbe13110SDimitry Andric     case MMToken::ExportKeyword:
3094461a67faSDimitry Andric     case MMToken::ExportAsKeyword:
3095dbe13110SDimitry Andric     case MMToken::HeaderKeyword:
3096dbe13110SDimitry Andric     case MMToken::Identifier:
3097dbe13110SDimitry Andric     case MMToken::LBrace:
3098809500fcSDimitry Andric     case MMToken::LinkKeyword:
3099dbe13110SDimitry Andric     case MMToken::LSquare:
3100dbe13110SDimitry Andric     case MMToken::Period:
3101bfef3995SDimitry Andric     case MMToken::PrivateKeyword:
3102dbe13110SDimitry Andric     case MMToken::RBrace:
3103dbe13110SDimitry Andric     case MMToken::RSquare:
3104dbe13110SDimitry Andric     case MMToken::RequiresKeyword:
3105dbe13110SDimitry Andric     case MMToken::Star:
3106dbe13110SDimitry Andric     case MMToken::StringLiteral:
3107551c6985SDimitry Andric     case MMToken::IntegerLiteral:
310806d4ba38SDimitry Andric     case MMToken::TextualKeyword:
3109dbe13110SDimitry Andric     case MMToken::UmbrellaKeyword:
3110bfef3995SDimitry Andric     case MMToken::UseKeyword:
3111dbe13110SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
3112dbe13110SDimitry Andric       HadError = true;
3113dbe13110SDimitry Andric       consumeToken();
3114dbe13110SDimitry Andric       break;
3115dbe13110SDimitry Andric     }
3116dbe13110SDimitry Andric   } while (true);
3117dbe13110SDimitry Andric }
3118dbe13110SDimitry Andric 
parseModuleMapFile(FileEntryRef File,bool IsSystem,DirectoryEntryRef Dir,FileID ID,unsigned * Offset,SourceLocation ExternModuleLoc)3119b1c73532SDimitry Andric bool ModuleMap::parseModuleMapFile(FileEntryRef File, bool IsSystem,
31207fa27ce4SDimitry Andric                                    DirectoryEntryRef Dir, FileID ID,
31210a5fb09bSDimitry Andric                                    unsigned *Offset,
312251ece4aaSDimitry Andric                                    SourceLocation ExternModuleLoc) {
31230a5fb09bSDimitry Andric   assert(Target && "Missing target information");
3124809500fcSDimitry Andric   llvm::DenseMap<const FileEntry *, bool>::iterator Known
3125809500fcSDimitry Andric     = ParsedModuleMap.find(File);
3126809500fcSDimitry Andric   if (Known != ParsedModuleMap.end())
3127809500fcSDimitry Andric     return Known->second;
3128809500fcSDimitry Andric 
31290a5fb09bSDimitry Andric   // If the module map file wasn't already entered, do so now.
31300a5fb09bSDimitry Andric   if (ID.isInvalid()) {
3131cf1b4019SDimitry Andric     auto FileCharacter =
3132cf1b4019SDimitry Andric         IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
31330a5fb09bSDimitry Andric     ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
31340a5fb09bSDimitry Andric   }
31350a5fb09bSDimitry Andric 
31360a5fb09bSDimitry Andric   assert(Target && "Missing target information");
3137e3b55780SDimitry Andric   std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
3138dbe13110SDimitry Andric   if (!Buffer)
3139809500fcSDimitry Andric     return ParsedModuleMap[File] = true;
31400a5fb09bSDimitry Andric   assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
31410a5fb09bSDimitry Andric          "invalid buffer offset");
3142dbe13110SDimitry Andric 
3143dbe13110SDimitry Andric   // Parse this module map file.
31440a5fb09bSDimitry Andric   Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
31450a5fb09bSDimitry Andric           Buffer->getBufferStart(),
31460a5fb09bSDimitry Andric           Buffer->getBufferStart() + (Offset ? *Offset : 0),
31470a5fb09bSDimitry Andric           Buffer->getBufferEnd());
314845b53394SDimitry Andric   SourceLocation Start = L.getSourceLocation();
3149ac9a064cSDimitry Andric   ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, ID, Dir, IsSystem);
3150dbe13110SDimitry Andric   bool Result = Parser.parseModuleMapFile();
3151809500fcSDimitry Andric   ParsedModuleMap[File] = Result;
315245b53394SDimitry Andric 
31530a5fb09bSDimitry Andric   if (Offset) {
31540a5fb09bSDimitry Andric     auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
31550a5fb09bSDimitry Andric     assert(Loc.first == ID && "stopped in a different file?");
31560a5fb09bSDimitry Andric     *Offset = Loc.second;
31570a5fb09bSDimitry Andric   }
31580a5fb09bSDimitry Andric 
315945b53394SDimitry Andric   // Notify callbacks that we parsed it.
316045b53394SDimitry Andric   for (const auto &Cb : Callbacks)
3161b1c73532SDimitry Andric     Cb->moduleMapFileRead(Start, File, IsSystem);
316248675466SDimitry Andric 
3163dbe13110SDimitry Andric   return Result;
3164dbe13110SDimitry Andric }
3165