10b57cec5SDimitry Andric //===- ModuleMap.cpp - Describe the layout of modules ---------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines the ModuleMap implementation, which describes the layout
100b57cec5SDimitry Andric // of a module as it relates to headers.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "clang/Lex/ModuleMap.h"
150b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h"
160b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h"
170b57cec5SDimitry Andric #include "clang/Basic/FileManager.h"
180b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
190b57cec5SDimitry Andric #include "clang/Basic/LangOptions.h"
200b57cec5SDimitry Andric #include "clang/Basic/Module.h"
210b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h"
220b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
230b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h"
240b57cec5SDimitry Andric #include "clang/Lex/HeaderSearch.h"
250b57cec5SDimitry Andric #include "clang/Lex/HeaderSearchOptions.h"
260b57cec5SDimitry Andric #include "clang/Lex/LexDiagnostic.h"
270b57cec5SDimitry Andric #include "clang/Lex/Lexer.h"
280b57cec5SDimitry Andric #include "clang/Lex/LiteralSupport.h"
290b57cec5SDimitry Andric #include "clang/Lex/Token.h"
300b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
310b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
320b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
330b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
340b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
350b57cec5SDimitry Andric #include "llvm/ADT/StringMap.h"
360b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
370b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
380b57cec5SDimitry Andric #include "llvm/Support/Allocator.h"
390b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
400b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
410b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
420b57cec5SDimitry Andric #include "llvm/Support/Path.h"
430b57cec5SDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
440b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
450b57cec5SDimitry Andric #include <algorithm>
460b57cec5SDimitry Andric #include <cassert>
470b57cec5SDimitry Andric #include <cstdint>
480b57cec5SDimitry Andric #include <cstring>
49bdd1243dSDimitry Andric #include <optional>
500b57cec5SDimitry Andric #include <string>
510b57cec5SDimitry Andric #include <system_error>
520b57cec5SDimitry Andric #include <utility>
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric using namespace clang;
550b57cec5SDimitry Andric 
anchor()560b57cec5SDimitry Andric void ModuleMapCallbacks::anchor() {}
570b57cec5SDimitry Andric 
resolveLinkAsDependencies(Module * Mod)580b57cec5SDimitry Andric void ModuleMap::resolveLinkAsDependencies(Module *Mod) {
590b57cec5SDimitry Andric   auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name);
600b57cec5SDimitry Andric   if (PendingLinkAs != PendingLinkAsModule.end()) {
610b57cec5SDimitry Andric     for (auto &Name : PendingLinkAs->second) {
620b57cec5SDimitry Andric       auto *M = findModule(Name.getKey());
630b57cec5SDimitry Andric       if (M)
640b57cec5SDimitry Andric         M->UseExportAsModuleLinkName = true;
650b57cec5SDimitry Andric     }
660b57cec5SDimitry Andric   }
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric 
addLinkAsDependency(Module * Mod)690b57cec5SDimitry Andric void ModuleMap::addLinkAsDependency(Module *Mod) {
700b57cec5SDimitry Andric   if (findModule(Mod->ExportAsModule))
710b57cec5SDimitry Andric     Mod->UseExportAsModuleLinkName = true;
720b57cec5SDimitry Andric   else
730b57cec5SDimitry Andric     PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name);
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric 
headerRoleToKind(ModuleHeaderRole Role)760b57cec5SDimitry Andric Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
770b57cec5SDimitry Andric   switch ((int)Role) {
780b57cec5SDimitry Andric   case NormalHeader:
790b57cec5SDimitry Andric     return Module::HK_Normal;
800b57cec5SDimitry Andric   case PrivateHeader:
810b57cec5SDimitry Andric     return Module::HK_Private;
820b57cec5SDimitry Andric   case TextualHeader:
830b57cec5SDimitry Andric     return Module::HK_Textual;
840b57cec5SDimitry Andric   case PrivateHeader | TextualHeader:
850b57cec5SDimitry Andric     return Module::HK_PrivateTextual;
86bdd1243dSDimitry Andric   case ExcludedHeader:
87bdd1243dSDimitry Andric     return Module::HK_Excluded;
880b57cec5SDimitry Andric   }
89bdd1243dSDimitry Andric   llvm_unreachable("unknown header role");
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric ModuleMap::ModuleHeaderRole
headerKindToRole(Module::HeaderKind Kind)930b57cec5SDimitry Andric ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
940b57cec5SDimitry Andric   switch ((int)Kind) {
950b57cec5SDimitry Andric   case Module::HK_Normal:
960b57cec5SDimitry Andric     return NormalHeader;
970b57cec5SDimitry Andric   case Module::HK_Private:
980b57cec5SDimitry Andric     return PrivateHeader;
990b57cec5SDimitry Andric   case Module::HK_Textual:
1000b57cec5SDimitry Andric     return TextualHeader;
1010b57cec5SDimitry Andric   case Module::HK_PrivateTextual:
1020b57cec5SDimitry Andric     return ModuleHeaderRole(PrivateHeader | TextualHeader);
1030b57cec5SDimitry Andric   case Module::HK_Excluded:
104bdd1243dSDimitry Andric     return ExcludedHeader;
1050b57cec5SDimitry Andric   }
1060b57cec5SDimitry Andric   llvm_unreachable("unknown header kind");
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric 
isModular(ModuleHeaderRole Role)109bdd1243dSDimitry Andric bool ModuleMap::isModular(ModuleHeaderRole Role) {
110bdd1243dSDimitry Andric   return !(Role & (ModuleMap::TextualHeader | ModuleMap::ExcludedHeader));
111bdd1243dSDimitry Andric }
112bdd1243dSDimitry Andric 
1130b57cec5SDimitry Andric Module::ExportDecl
resolveExport(Module * Mod,const Module::UnresolvedExportDecl & Unresolved,bool Complain) const1140b57cec5SDimitry Andric ModuleMap::resolveExport(Module *Mod,
1150b57cec5SDimitry Andric                          const Module::UnresolvedExportDecl &Unresolved,
1160b57cec5SDimitry Andric                          bool Complain) const {
1170b57cec5SDimitry Andric   // We may have just a wildcard.
1180b57cec5SDimitry Andric   if (Unresolved.Id.empty()) {
1190b57cec5SDimitry Andric     assert(Unresolved.Wildcard && "Invalid unresolved export");
1200b57cec5SDimitry Andric     return Module::ExportDecl(nullptr, true);
1210b57cec5SDimitry Andric   }
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric   // Resolve the module-id.
1240b57cec5SDimitry Andric   Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
1250b57cec5SDimitry Andric   if (!Context)
1260b57cec5SDimitry Andric     return {};
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   return Module::ExportDecl(Context, Unresolved.Wildcard);
1290b57cec5SDimitry Andric }
1300b57cec5SDimitry Andric 
resolveModuleId(const ModuleId & Id,Module * Mod,bool Complain) const1310b57cec5SDimitry Andric Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
1320b57cec5SDimitry Andric                                    bool Complain) const {
1330b57cec5SDimitry Andric   // Find the starting module.
1340b57cec5SDimitry Andric   Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
1350b57cec5SDimitry Andric   if (!Context) {
1360b57cec5SDimitry Andric     if (Complain)
1370b57cec5SDimitry Andric       Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
1380b57cec5SDimitry Andric       << Id[0].first << Mod->getFullModuleName();
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric     return nullptr;
1410b57cec5SDimitry Andric   }
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   // Dig into the module path.
1440b57cec5SDimitry Andric   for (unsigned I = 1, N = Id.size(); I != N; ++I) {
1450b57cec5SDimitry Andric     Module *Sub = lookupModuleQualified(Id[I].first, Context);
1460b57cec5SDimitry Andric     if (!Sub) {
1470b57cec5SDimitry Andric       if (Complain)
1480b57cec5SDimitry Andric         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
1490b57cec5SDimitry Andric         << Id[I].first << Context->getFullModuleName()
1500b57cec5SDimitry Andric         << SourceRange(Id[0].second, Id[I-1].second);
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric       return nullptr;
1530b57cec5SDimitry Andric     }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric     Context = Sub;
1560b57cec5SDimitry Andric   }
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   return Context;
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric /// Append to \p Paths the set of paths needed to get to the
1620b57cec5SDimitry Andric /// subframework in which the given module lives.
appendSubframeworkPaths(Module * Mod,SmallVectorImpl<char> & Path)1630b57cec5SDimitry Andric static void appendSubframeworkPaths(Module *Mod,
1640b57cec5SDimitry Andric                                     SmallVectorImpl<char> &Path) {
1650b57cec5SDimitry Andric   // Collect the framework names from the given module to the top-level module.
1660b57cec5SDimitry Andric   SmallVector<StringRef, 2> Paths;
1670b57cec5SDimitry Andric   for (; Mod; Mod = Mod->Parent) {
1680b57cec5SDimitry Andric     if (Mod->IsFramework)
1690b57cec5SDimitry Andric       Paths.push_back(Mod->Name);
1700b57cec5SDimitry Andric   }
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   if (Paths.empty())
1730b57cec5SDimitry Andric     return;
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   // Add Frameworks/Name.framework for each subframework.
176349cc55cSDimitry Andric   for (StringRef Framework : llvm::drop_begin(llvm::reverse(Paths)))
177349cc55cSDimitry Andric     llvm::sys::path::append(Path, "Frameworks", Framework + ".framework");
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric 
findHeader(Module * M,const Module::UnresolvedHeaderDirective & Header,SmallVectorImpl<char> & RelativePathName,bool & NeedsFramework)180bdd1243dSDimitry Andric OptionalFileEntryRef ModuleMap::findHeader(
1810b57cec5SDimitry Andric     Module *M, const Module::UnresolvedHeaderDirective &Header,
1820b57cec5SDimitry Andric     SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) {
1830b57cec5SDimitry Andric   // Search for the header file within the module's home directory.
184fe013be4SDimitry Andric   auto Directory = M->Directory;
1850b57cec5SDimitry Andric   SmallString<128> FullPathName(Directory->getName());
1860b57cec5SDimitry Andric 
187bdd1243dSDimitry Andric   auto GetFile = [&](StringRef Filename) -> OptionalFileEntryRef {
188e8d8bef9SDimitry Andric     auto File =
189e8d8bef9SDimitry Andric         expectedToOptional(SourceMgr.getFileManager().getFileRef(Filename));
190e8d8bef9SDimitry Andric     if (!File || (Header.Size && File->getSize() != *Header.Size) ||
191e8d8bef9SDimitry Andric         (Header.ModTime && File->getModificationTime() != *Header.ModTime))
192bdd1243dSDimitry Andric       return std::nullopt;
193a7dea167SDimitry Andric     return *File;
1940b57cec5SDimitry Andric   };
1950b57cec5SDimitry Andric 
196bdd1243dSDimitry Andric   auto GetFrameworkFile = [&]() -> OptionalFileEntryRef {
1970b57cec5SDimitry Andric     unsigned FullPathLength = FullPathName.size();
1980b57cec5SDimitry Andric     appendSubframeworkPaths(M, RelativePathName);
1990b57cec5SDimitry Andric     unsigned RelativePathLength = RelativePathName.size();
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric     // Check whether this file is in the public headers.
2020b57cec5SDimitry Andric     llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
2030b57cec5SDimitry Andric     llvm::sys::path::append(FullPathName, RelativePathName);
204e8d8bef9SDimitry Andric     if (auto File = GetFile(FullPathName))
2050b57cec5SDimitry Andric       return File;
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric     // Check whether this file is in the private headers.
2080b57cec5SDimitry Andric     // Ideally, private modules in the form 'FrameworkName.Private' should
2090b57cec5SDimitry Andric     // be defined as 'module FrameworkName.Private', and not as
2100b57cec5SDimitry Andric     // 'framework module FrameworkName.Private', since a 'Private.Framework'
2110b57cec5SDimitry Andric     // does not usually exist. However, since both are currently widely used
2120b57cec5SDimitry Andric     // for private modules, make sure we find the right path in both cases.
2130b57cec5SDimitry Andric     if (M->IsFramework && M->Name == "Private")
2140b57cec5SDimitry Andric       RelativePathName.clear();
2150b57cec5SDimitry Andric     else
2160b57cec5SDimitry Andric       RelativePathName.resize(RelativePathLength);
2170b57cec5SDimitry Andric     FullPathName.resize(FullPathLength);
2180b57cec5SDimitry Andric     llvm::sys::path::append(RelativePathName, "PrivateHeaders",
2190b57cec5SDimitry Andric                             Header.FileName);
2200b57cec5SDimitry Andric     llvm::sys::path::append(FullPathName, RelativePathName);
2210b57cec5SDimitry Andric     return GetFile(FullPathName);
2220b57cec5SDimitry Andric   };
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric   if (llvm::sys::path::is_absolute(Header.FileName)) {
2250b57cec5SDimitry Andric     RelativePathName.clear();
2260b57cec5SDimitry Andric     RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
2270b57cec5SDimitry Andric     return GetFile(Header.FileName);
2280b57cec5SDimitry Andric   }
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric   if (M->isPartOfFramework())
2310b57cec5SDimitry Andric     return GetFrameworkFile();
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric   // Lookup for normal headers.
2340b57cec5SDimitry Andric   llvm::sys::path::append(RelativePathName, Header.FileName);
2350b57cec5SDimitry Andric   llvm::sys::path::append(FullPathName, RelativePathName);
236e8d8bef9SDimitry Andric   auto NormalHdrFile = GetFile(FullPathName);
2370b57cec5SDimitry Andric 
238c9157d92SDimitry Andric   if (!NormalHdrFile && Directory->getName().ends_with(".framework")) {
2390b57cec5SDimitry Andric     // The lack of 'framework' keyword in a module declaration it's a simple
2400b57cec5SDimitry Andric     // mistake we can diagnose when the header exists within the proper
2410b57cec5SDimitry Andric     // framework style path.
2420b57cec5SDimitry Andric     FullPathName.assign(Directory->getName());
2430b57cec5SDimitry Andric     RelativePathName.clear();
2440b57cec5SDimitry Andric     if (GetFrameworkFile()) {
2450b57cec5SDimitry Andric       Diags.Report(Header.FileNameLoc,
2460b57cec5SDimitry Andric                    diag::warn_mmap_incomplete_framework_module_declaration)
2470b57cec5SDimitry Andric           << Header.FileName << M->getFullModuleName();
2480b57cec5SDimitry Andric       NeedsFramework = true;
2490b57cec5SDimitry Andric     }
250bdd1243dSDimitry Andric     return std::nullopt;
2510b57cec5SDimitry Andric   }
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric   return NormalHdrFile;
2540b57cec5SDimitry Andric }
2550b57cec5SDimitry Andric 
256c9157d92SDimitry Andric /// Determine whether the given file name is the name of a builtin
257c9157d92SDimitry Andric /// header, supplied by Clang to replace, override, or augment existing system
258c9157d92SDimitry Andric /// headers.
isBuiltinHeaderName(StringRef FileName)259c9157d92SDimitry Andric static bool isBuiltinHeaderName(StringRef FileName) {
260c9157d92SDimitry Andric   return llvm::StringSwitch<bool>(FileName)
261c9157d92SDimitry Andric            .Case("float.h", true)
262c9157d92SDimitry Andric            .Case("iso646.h", true)
263c9157d92SDimitry Andric            .Case("limits.h", true)
264c9157d92SDimitry Andric            .Case("stdalign.h", true)
265c9157d92SDimitry Andric            .Case("stdarg.h", true)
266c9157d92SDimitry Andric            .Case("stdatomic.h", true)
267c9157d92SDimitry Andric            .Case("stdbool.h", true)
268c9157d92SDimitry Andric            .Case("stddef.h", true)
269c9157d92SDimitry Andric            .Case("stdint.h", true)
270c9157d92SDimitry Andric            .Case("tgmath.h", true)
271c9157d92SDimitry Andric            .Case("unwind.h", true)
272c9157d92SDimitry Andric            .Default(false);
273c9157d92SDimitry Andric }
274c9157d92SDimitry Andric 
275c9157d92SDimitry Andric /// Determine whether the given module name is the name of a builtin
276c9157d92SDimitry Andric /// module that is cyclic with a system module  on some platforms.
isBuiltInModuleName(StringRef ModuleName)277c9157d92SDimitry Andric static bool isBuiltInModuleName(StringRef ModuleName) {
278c9157d92SDimitry Andric   return llvm::StringSwitch<bool>(ModuleName)
279c9157d92SDimitry Andric            .Case("_Builtin_float", true)
280c9157d92SDimitry Andric            .Case("_Builtin_inttypes", true)
281c9157d92SDimitry Andric            .Case("_Builtin_iso646", true)
282c9157d92SDimitry Andric            .Case("_Builtin_limits", true)
283c9157d92SDimitry Andric            .Case("_Builtin_stdalign", true)
284c9157d92SDimitry Andric            .Case("_Builtin_stdarg", true)
285c9157d92SDimitry Andric            .Case("_Builtin_stdatomic", true)
286c9157d92SDimitry Andric            .Case("_Builtin_stdbool", true)
287c9157d92SDimitry Andric            .Case("_Builtin_stddef", true)
288c9157d92SDimitry Andric            .Case("_Builtin_stdint", true)
289c9157d92SDimitry Andric            .Case("_Builtin_stdnoreturn", true)
290c9157d92SDimitry Andric            .Case("_Builtin_tgmath", true)
291c9157d92SDimitry Andric            .Case("_Builtin_unwind", true)
292c9157d92SDimitry Andric            .Default(false);
293c9157d92SDimitry Andric }
294c9157d92SDimitry Andric 
resolveHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header,bool & NeedsFramework)2950b57cec5SDimitry Andric void ModuleMap::resolveHeader(Module *Mod,
2960b57cec5SDimitry Andric                               const Module::UnresolvedHeaderDirective &Header,
2970b57cec5SDimitry Andric                               bool &NeedsFramework) {
2980b57cec5SDimitry Andric   SmallString<128> RelativePathName;
299bdd1243dSDimitry Andric   if (OptionalFileEntryRef File =
3000b57cec5SDimitry Andric           findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
3010b57cec5SDimitry Andric     if (Header.IsUmbrella) {
302e8d8bef9SDimitry Andric       const DirectoryEntry *UmbrellaDir = &File->getDir().getDirEntry();
3030b57cec5SDimitry Andric       if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
3040b57cec5SDimitry Andric         Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
3050b57cec5SDimitry Andric           << UmbrellaMod->getFullModuleName();
3060b57cec5SDimitry Andric       else
3070b57cec5SDimitry Andric         // Record this umbrella header.
308fe013be4SDimitry Andric         setUmbrellaHeaderAsWritten(Mod, *File, Header.FileName,
309fe013be4SDimitry Andric                                    RelativePathName.str());
3100b57cec5SDimitry Andric     } else {
311a58f00eaSDimitry Andric       Module::Header H = {Header.FileName, std::string(RelativePathName),
312fe6060f1SDimitry Andric                           *File};
3130b57cec5SDimitry Andric       addHeader(Mod, H, headerKindToRole(Header.Kind));
3140b57cec5SDimitry Andric     }
3150b57cec5SDimitry Andric   } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
3160b57cec5SDimitry Andric     // There's a builtin header but no corresponding on-disk header. Assume
3170b57cec5SDimitry Andric     // this was supposed to modularize the builtin header alone.
3180b57cec5SDimitry Andric   } else if (Header.Kind == Module::HK_Excluded) {
3190b57cec5SDimitry Andric     // Ignore missing excluded header files. They're optional anyway.
3200b57cec5SDimitry Andric   } else {
3210b57cec5SDimitry Andric     // If we find a module that has a missing header, we mark this module as
3220b57cec5SDimitry Andric     // unavailable and store the header directive for displaying diagnostics.
3230b57cec5SDimitry Andric     Mod->MissingHeaders.push_back(Header);
3240b57cec5SDimitry Andric     // A missing header with stat information doesn't make the module
3250b57cec5SDimitry Andric     // unavailable; this keeps our behavior consistent as headers are lazily
3260b57cec5SDimitry Andric     // resolved. (Such a module still can't be built though, except from
3270b57cec5SDimitry Andric     // preprocessed source.)
3280b57cec5SDimitry Andric     if (!Header.Size && !Header.ModTime)
3295ffd83dbSDimitry Andric       Mod->markUnavailable(/*Unimportable=*/false);
3300b57cec5SDimitry Andric   }
3310b57cec5SDimitry Andric }
3320b57cec5SDimitry Andric 
resolveAsBuiltinHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header)3330b57cec5SDimitry Andric bool ModuleMap::resolveAsBuiltinHeader(
3340b57cec5SDimitry Andric     Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
3350b57cec5SDimitry Andric   if (Header.Kind == Module::HK_Excluded ||
3360b57cec5SDimitry Andric       llvm::sys::path::is_absolute(Header.FileName) ||
3370b57cec5SDimitry Andric       Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
3380b57cec5SDimitry Andric       !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
339c9157d92SDimitry Andric       !LangOpts.BuiltinHeadersInSystemModules || !isBuiltinHeaderName(Header.FileName))
3400b57cec5SDimitry Andric     return false;
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric   // This is a system module with a top-level header. This header
3430b57cec5SDimitry Andric   // may have a counterpart (or replacement) in the set of headers
3440b57cec5SDimitry Andric   // supplied by Clang. Find that builtin header.
3450b57cec5SDimitry Andric   SmallString<128> Path;
3460b57cec5SDimitry Andric   llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
347bdd1243dSDimitry Andric   auto File = SourceMgr.getFileManager().getOptionalFileRef(Path);
3480b57cec5SDimitry Andric   if (!File)
3490b57cec5SDimitry Andric     return false;
3500b57cec5SDimitry Andric 
351c9157d92SDimitry Andric   Module::Header H = {Header.FileName, Header.FileName, *File};
3520b57cec5SDimitry Andric   auto Role = headerKindToRole(Header.Kind);
3530b57cec5SDimitry Andric   addHeader(Mod, H, Role);
3540b57cec5SDimitry Andric   return true;
3550b57cec5SDimitry Andric }
3560b57cec5SDimitry Andric 
ModuleMap(SourceManager & SourceMgr,DiagnosticsEngine & Diags,const LangOptions & LangOpts,const TargetInfo * Target,HeaderSearch & HeaderInfo)3570b57cec5SDimitry Andric ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
3580b57cec5SDimitry Andric                      const LangOptions &LangOpts, const TargetInfo *Target,
3590b57cec5SDimitry Andric                      HeaderSearch &HeaderInfo)
3600b57cec5SDimitry Andric     : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
3610b57cec5SDimitry Andric       HeaderInfo(HeaderInfo) {
3620b57cec5SDimitry Andric   MMapLangOpts.LineComment = true;
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric 
~ModuleMap()3650b57cec5SDimitry Andric ModuleMap::~ModuleMap() {
3660b57cec5SDimitry Andric   for (auto &M : Modules)
3670b57cec5SDimitry Andric     delete M.getValue();
3680b57cec5SDimitry Andric   for (auto *M : ShadowModules)
3690b57cec5SDimitry Andric     delete M;
3700b57cec5SDimitry Andric }
3710b57cec5SDimitry Andric 
setTarget(const TargetInfo & Target)3720b57cec5SDimitry Andric void ModuleMap::setTarget(const TargetInfo &Target) {
3730b57cec5SDimitry Andric   assert((!this->Target || this->Target == &Target) &&
3740b57cec5SDimitry Andric          "Improper target override");
3750b57cec5SDimitry Andric   this->Target = &Target;
3760b57cec5SDimitry Andric }
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric /// "Sanitize" a filename so that it can be used as an identifier.
sanitizeFilenameAsIdentifier(StringRef Name,SmallVectorImpl<char> & Buffer)3790b57cec5SDimitry Andric static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
3800b57cec5SDimitry Andric                                               SmallVectorImpl<char> &Buffer) {
3810b57cec5SDimitry Andric   if (Name.empty())
3820b57cec5SDimitry Andric     return Name;
3830b57cec5SDimitry Andric 
384349cc55cSDimitry Andric   if (!isValidAsciiIdentifier(Name)) {
3850b57cec5SDimitry Andric     // If we don't already have something with the form of an identifier,
3860b57cec5SDimitry Andric     // create a buffer with the sanitized name.
3870b57cec5SDimitry Andric     Buffer.clear();
3880b57cec5SDimitry Andric     if (isDigit(Name[0]))
3890b57cec5SDimitry Andric       Buffer.push_back('_');
3900b57cec5SDimitry Andric     Buffer.reserve(Buffer.size() + Name.size());
3910b57cec5SDimitry Andric     for (unsigned I = 0, N = Name.size(); I != N; ++I) {
392349cc55cSDimitry Andric       if (isAsciiIdentifierContinue(Name[I]))
3930b57cec5SDimitry Andric         Buffer.push_back(Name[I]);
3940b57cec5SDimitry Andric       else
3950b57cec5SDimitry Andric         Buffer.push_back('_');
3960b57cec5SDimitry Andric     }
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric     Name = StringRef(Buffer.data(), Buffer.size());
3990b57cec5SDimitry Andric   }
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric   while (llvm::StringSwitch<bool>(Name)
4020b57cec5SDimitry Andric #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
4030b57cec5SDimitry Andric #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
4040b57cec5SDimitry Andric #include "clang/Basic/TokenKinds.def"
4050b57cec5SDimitry Andric            .Default(false)) {
4060b57cec5SDimitry Andric     if (Name.data() != Buffer.data())
4070b57cec5SDimitry Andric       Buffer.append(Name.begin(), Name.end());
4080b57cec5SDimitry Andric     Buffer.push_back('_');
4090b57cec5SDimitry Andric     Name = StringRef(Buffer.data(), Buffer.size());
4100b57cec5SDimitry Andric   }
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric   return Name;
4130b57cec5SDimitry Andric }
4140b57cec5SDimitry Andric 
isBuiltinHeader(FileEntryRef File)415c9157d92SDimitry Andric bool ModuleMap::isBuiltinHeader(FileEntryRef File) {
416c9157d92SDimitry Andric   return File.getDir() == BuiltinIncludeDir && LangOpts.BuiltinHeadersInSystemModules &&
417c9157d92SDimitry Andric          isBuiltinHeaderName(llvm::sys::path::filename(File.getName()));
4180b57cec5SDimitry Andric }
4190b57cec5SDimitry Andric 
shouldImportRelativeToBuiltinIncludeDir(StringRef FileName,Module * Module) const420c9157d92SDimitry Andric bool ModuleMap::shouldImportRelativeToBuiltinIncludeDir(StringRef FileName,
421c9157d92SDimitry Andric                                                         Module *Module) const {
422c9157d92SDimitry Andric   return LangOpts.BuiltinHeadersInSystemModules && BuiltinIncludeDir &&
423c9157d92SDimitry Andric          Module->IsSystem && !Module->isPartOfFramework() &&
424c9157d92SDimitry Andric          isBuiltinHeaderName(FileName);
4255ffd83dbSDimitry Andric }
4265ffd83dbSDimitry Andric 
findKnownHeader(FileEntryRef File)427c9157d92SDimitry Andric ModuleMap::HeadersMap::iterator ModuleMap::findKnownHeader(FileEntryRef File) {
4280b57cec5SDimitry Andric   resolveHeaderDirectives(File);
4290b57cec5SDimitry Andric   HeadersMap::iterator Known = Headers.find(File);
4300b57cec5SDimitry Andric   if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
4315ffd83dbSDimitry Andric       Known == Headers.end() && ModuleMap::isBuiltinHeader(File)) {
4320b57cec5SDimitry Andric     HeaderInfo.loadTopLevelSystemModules();
4330b57cec5SDimitry Andric     return Headers.find(File);
4340b57cec5SDimitry Andric   }
4350b57cec5SDimitry Andric   return Known;
4360b57cec5SDimitry Andric }
4370b57cec5SDimitry Andric 
findHeaderInUmbrellaDirs(FileEntryRef File,SmallVectorImpl<DirectoryEntryRef> & IntermediateDirs)438fe013be4SDimitry Andric ModuleMap::KnownHeader ModuleMap::findHeaderInUmbrellaDirs(
439fe013be4SDimitry Andric     FileEntryRef File, SmallVectorImpl<DirectoryEntryRef> &IntermediateDirs) {
4400b57cec5SDimitry Andric   if (UmbrellaDirs.empty())
4410b57cec5SDimitry Andric     return {};
4420b57cec5SDimitry Andric 
443fe013be4SDimitry Andric   OptionalDirectoryEntryRef Dir = File.getDir();
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric   // Note: as an egregious but useful hack we use the real path here, because
4460b57cec5SDimitry Andric   // frameworks moving from top-level frameworks to embedded frameworks tend
4470b57cec5SDimitry Andric   // to be symlinked from the top-level location to the embedded location,
4480b57cec5SDimitry Andric   // and we need to resolve lookups as if we had found the embedded location.
449fe013be4SDimitry Andric   StringRef DirName = SourceMgr.getFileManager().getCanonicalName(*Dir);
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric   // Keep walking up the directory hierarchy, looking for a directory with
4520b57cec5SDimitry Andric   // an umbrella header.
4530b57cec5SDimitry Andric   do {
454fe013be4SDimitry Andric     auto KnownDir = UmbrellaDirs.find(*Dir);
4550b57cec5SDimitry Andric     if (KnownDir != UmbrellaDirs.end())
4560b57cec5SDimitry Andric       return KnownHeader(KnownDir->second, NormalHeader);
4570b57cec5SDimitry Andric 
458fe013be4SDimitry Andric     IntermediateDirs.push_back(*Dir);
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric     // Retrieve our parent path.
4610b57cec5SDimitry Andric     DirName = llvm::sys::path::parent_path(DirName);
4620b57cec5SDimitry Andric     if (DirName.empty())
4630b57cec5SDimitry Andric       break;
4640b57cec5SDimitry Andric 
4650b57cec5SDimitry Andric     // Resolve the parent path to a directory entry.
466fe013be4SDimitry Andric     Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
4670b57cec5SDimitry Andric   } while (Dir);
4680b57cec5SDimitry Andric   return {};
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric 
violatesPrivateInclude(Module * RequestingModule,const FileEntry * IncFileEnt,ModuleMap::KnownHeader Header)4710b57cec5SDimitry Andric static bool violatesPrivateInclude(Module *RequestingModule,
4720b57cec5SDimitry Andric                                    const FileEntry *IncFileEnt,
4730b57cec5SDimitry Andric                                    ModuleMap::KnownHeader Header) {
4740b57cec5SDimitry Andric #ifndef NDEBUG
4750b57cec5SDimitry Andric   if (Header.getRole() & ModuleMap::PrivateHeader) {
4760b57cec5SDimitry Andric     // Check for consistency between the module header role
4770b57cec5SDimitry Andric     // as obtained from the lookup and as obtained from the module.
4780b57cec5SDimitry Andric     // This check is not cheap, so enable it only for debugging.
4790b57cec5SDimitry Andric     bool IsPrivate = false;
4800b57cec5SDimitry Andric     SmallVectorImpl<Module::Header> *HeaderList[] = {
4810b57cec5SDimitry Andric         &Header.getModule()->Headers[Module::HK_Private],
4820b57cec5SDimitry Andric         &Header.getModule()->Headers[Module::HK_PrivateTextual]};
4830b57cec5SDimitry Andric     for (auto *Hs : HeaderList)
484fcaf7f86SDimitry Andric       IsPrivate |= llvm::any_of(
485fcaf7f86SDimitry Andric           *Hs, [&](const Module::Header &H) { return H.Entry == IncFileEnt; });
4860b57cec5SDimitry Andric     assert(IsPrivate && "inconsistent headers and roles");
4870b57cec5SDimitry Andric   }
4880b57cec5SDimitry Andric #endif
4890b57cec5SDimitry Andric   return !Header.isAccessibleFrom(RequestingModule);
4900b57cec5SDimitry Andric }
4910b57cec5SDimitry Andric 
getTopLevelOrNull(Module * M)4920b57cec5SDimitry Andric static Module *getTopLevelOrNull(Module *M) {
4930b57cec5SDimitry Andric   return M ? M->getTopLevelModule() : nullptr;
4940b57cec5SDimitry Andric }
4950b57cec5SDimitry Andric 
diagnoseHeaderInclusion(Module * RequestingModule,bool RequestingModuleIsModuleInterface,SourceLocation FilenameLoc,StringRef Filename,FileEntryRef File)4960b57cec5SDimitry Andric void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
4970b57cec5SDimitry Andric                                         bool RequestingModuleIsModuleInterface,
4980b57cec5SDimitry Andric                                         SourceLocation FilenameLoc,
49981ad6265SDimitry Andric                                         StringRef Filename, FileEntryRef File) {
5000b57cec5SDimitry Andric   // No errors for indirect modules. This may be a bit of a problem for modules
5010b57cec5SDimitry Andric   // with no source files.
5020b57cec5SDimitry Andric   if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
5030b57cec5SDimitry Andric     return;
5040b57cec5SDimitry Andric 
5050b57cec5SDimitry Andric   if (RequestingModule) {
5060b57cec5SDimitry Andric     resolveUses(RequestingModule, /*Complain=*/false);
507bdd1243dSDimitry Andric     resolveHeaderDirectives(RequestingModule, /*File=*/std::nullopt);
5080b57cec5SDimitry Andric   }
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric   bool Excluded = false;
5110b57cec5SDimitry Andric   Module *Private = nullptr;
5120b57cec5SDimitry Andric   Module *NotUsed = nullptr;
5130b57cec5SDimitry Andric 
5140b57cec5SDimitry Andric   HeadersMap::iterator Known = findKnownHeader(File);
5150b57cec5SDimitry Andric   if (Known != Headers.end()) {
5160b57cec5SDimitry Andric     for (const KnownHeader &Header : Known->second) {
517bdd1243dSDimitry Andric       // Excluded headers don't really belong to a module.
518bdd1243dSDimitry Andric       if (Header.getRole() == ModuleMap::ExcludedHeader) {
519bdd1243dSDimitry Andric         Excluded = true;
520bdd1243dSDimitry Andric         continue;
521bdd1243dSDimitry Andric       }
522bdd1243dSDimitry Andric 
5230b57cec5SDimitry Andric       // Remember private headers for later printing of a diagnostic.
5240b57cec5SDimitry Andric       if (violatesPrivateInclude(RequestingModule, File, Header)) {
5250b57cec5SDimitry Andric         Private = Header.getModule();
5260b57cec5SDimitry Andric         continue;
5270b57cec5SDimitry Andric       }
5280b57cec5SDimitry Andric 
5290b57cec5SDimitry Andric       // If uses need to be specified explicitly, we are only allowed to return
5300b57cec5SDimitry Andric       // modules that are explicitly used by the requesting module.
5310b57cec5SDimitry Andric       if (RequestingModule && LangOpts.ModulesDeclUse &&
5320b57cec5SDimitry Andric           !RequestingModule->directlyUses(Header.getModule())) {
5330b57cec5SDimitry Andric         NotUsed = Header.getModule();
5340b57cec5SDimitry Andric         continue;
5350b57cec5SDimitry Andric       }
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric       // We have found a module that we can happily use.
5380b57cec5SDimitry Andric       return;
5390b57cec5SDimitry Andric     }
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric     Excluded = true;
5420b57cec5SDimitry Andric   }
5430b57cec5SDimitry Andric 
5440b57cec5SDimitry Andric   // We have found a header, but it is private.
5450b57cec5SDimitry Andric   if (Private) {
5460b57cec5SDimitry Andric     Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
5470b57cec5SDimitry Andric         << Filename;
5480b57cec5SDimitry Andric     return;
5490b57cec5SDimitry Andric   }
5500b57cec5SDimitry Andric 
5510b57cec5SDimitry Andric   // We have found a module, but we don't use it.
5520b57cec5SDimitry Andric   if (NotUsed) {
553fe013be4SDimitry Andric     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module_indirect)
554fe013be4SDimitry Andric         << RequestingModule->getTopLevelModule()->Name << Filename
555fe013be4SDimitry Andric         << NotUsed->Name;
5560b57cec5SDimitry Andric     return;
5570b57cec5SDimitry Andric   }
5580b57cec5SDimitry Andric 
5590b57cec5SDimitry Andric   if (Excluded || isHeaderInUmbrellaDirs(File))
5600b57cec5SDimitry Andric     return;
5610b57cec5SDimitry Andric 
5620b57cec5SDimitry Andric   // At this point, only non-modular includes remain.
5630b57cec5SDimitry Andric 
5640b57cec5SDimitry Andric   if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
5650b57cec5SDimitry Andric     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5660b57cec5SDimitry Andric         << RequestingModule->getTopLevelModule()->Name << Filename;
5670b57cec5SDimitry Andric   } else if (RequestingModule && RequestingModuleIsModuleInterface &&
5680b57cec5SDimitry Andric              LangOpts.isCompilingModule()) {
5690b57cec5SDimitry Andric     // Do not diagnose when we are not compiling a module.
5700b57cec5SDimitry Andric     diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
5710b57cec5SDimitry Andric         diag::warn_non_modular_include_in_framework_module :
5720b57cec5SDimitry Andric         diag::warn_non_modular_include_in_module;
5730b57cec5SDimitry Andric     Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
57481ad6265SDimitry Andric         << File.getName();
5750b57cec5SDimitry Andric   }
5760b57cec5SDimitry Andric }
5770b57cec5SDimitry Andric 
isBetterKnownHeader(const ModuleMap::KnownHeader & New,const ModuleMap::KnownHeader & Old)5780b57cec5SDimitry Andric static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
5790b57cec5SDimitry Andric                                 const ModuleMap::KnownHeader &Old) {
5800b57cec5SDimitry Andric   // Prefer available modules.
5815ffd83dbSDimitry Andric   // FIXME: Considering whether the module is available rather than merely
5825ffd83dbSDimitry Andric   // importable is non-hermetic and can result in surprising behavior for
5835ffd83dbSDimitry Andric   // prebuilt modules. Consider only checking for importability here.
5840b57cec5SDimitry Andric   if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
5850b57cec5SDimitry Andric     return true;
5860b57cec5SDimitry Andric 
5870b57cec5SDimitry Andric   // Prefer a public header over a private header.
5880b57cec5SDimitry Andric   if ((New.getRole() & ModuleMap::PrivateHeader) !=
5890b57cec5SDimitry Andric       (Old.getRole() & ModuleMap::PrivateHeader))
5900b57cec5SDimitry Andric     return !(New.getRole() & ModuleMap::PrivateHeader);
5910b57cec5SDimitry Andric 
5920b57cec5SDimitry Andric   // Prefer a non-textual header over a textual header.
5930b57cec5SDimitry Andric   if ((New.getRole() & ModuleMap::TextualHeader) !=
5940b57cec5SDimitry Andric       (Old.getRole() & ModuleMap::TextualHeader))
5950b57cec5SDimitry Andric     return !(New.getRole() & ModuleMap::TextualHeader);
5960b57cec5SDimitry Andric 
597bdd1243dSDimitry Andric   // Prefer a non-excluded header over an excluded header.
598bdd1243dSDimitry Andric   if ((New.getRole() == ModuleMap::ExcludedHeader) !=
599bdd1243dSDimitry Andric       (Old.getRole() == ModuleMap::ExcludedHeader))
600bdd1243dSDimitry Andric     return New.getRole() != ModuleMap::ExcludedHeader;
601bdd1243dSDimitry Andric 
6020b57cec5SDimitry Andric   // Don't have a reason to choose between these. Just keep the first one.
6030b57cec5SDimitry Andric   return false;
6040b57cec5SDimitry Andric }
6050b57cec5SDimitry Andric 
findModuleForHeader(FileEntryRef File,bool AllowTextual,bool AllowExcluded)606fe013be4SDimitry Andric ModuleMap::KnownHeader ModuleMap::findModuleForHeader(FileEntryRef File,
607bdd1243dSDimitry Andric                                                       bool AllowTextual,
608bdd1243dSDimitry Andric                                                       bool AllowExcluded) {
6090b57cec5SDimitry Andric   auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
6100b57cec5SDimitry Andric     if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
6110b57cec5SDimitry Andric       return {};
6120b57cec5SDimitry Andric     return R;
6130b57cec5SDimitry Andric   };
6140b57cec5SDimitry Andric 
6150b57cec5SDimitry Andric   HeadersMap::iterator Known = findKnownHeader(File);
6160b57cec5SDimitry Andric   if (Known != Headers.end()) {
6170b57cec5SDimitry Andric     ModuleMap::KnownHeader Result;
6180b57cec5SDimitry Andric     // Iterate over all modules that 'File' is part of to find the best fit.
6190b57cec5SDimitry Andric     for (KnownHeader &H : Known->second) {
620bdd1243dSDimitry Andric       // Cannot use a module if the header is excluded in it.
621bdd1243dSDimitry Andric       if (!AllowExcluded && H.getRole() == ModuleMap::ExcludedHeader)
622bdd1243dSDimitry Andric         continue;
6230b57cec5SDimitry Andric       // Prefer a header from the source module over all others.
6240b57cec5SDimitry Andric       if (H.getModule()->getTopLevelModule() == SourceModule)
6250b57cec5SDimitry Andric         return MakeResult(H);
6260b57cec5SDimitry Andric       if (!Result || isBetterKnownHeader(H, Result))
6270b57cec5SDimitry Andric         Result = H;
6280b57cec5SDimitry Andric     }
6290b57cec5SDimitry Andric     return MakeResult(Result);
6300b57cec5SDimitry Andric   }
6310b57cec5SDimitry Andric 
6320b57cec5SDimitry Andric   return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
6330b57cec5SDimitry Andric }
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric ModuleMap::KnownHeader
findOrCreateModuleForHeaderInUmbrellaDir(FileEntryRef File)636fe013be4SDimitry Andric ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(FileEntryRef File) {
6370b57cec5SDimitry Andric   assert(!Headers.count(File) && "already have a module for this header");
6380b57cec5SDimitry Andric 
639fe013be4SDimitry Andric   SmallVector<DirectoryEntryRef, 2> SkippedDirs;
6400b57cec5SDimitry Andric   KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
6410b57cec5SDimitry Andric   if (H) {
6420b57cec5SDimitry Andric     Module *Result = H.getModule();
6430b57cec5SDimitry Andric 
6440b57cec5SDimitry Andric     // Search up the module stack until we find a module with an umbrella
6450b57cec5SDimitry Andric     // directory.
6460b57cec5SDimitry Andric     Module *UmbrellaModule = Result;
647fe013be4SDimitry Andric     while (!UmbrellaModule->getEffectiveUmbrellaDir() && UmbrellaModule->Parent)
6480b57cec5SDimitry Andric       UmbrellaModule = UmbrellaModule->Parent;
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric     if (UmbrellaModule->InferSubmodules) {
651c9157d92SDimitry Andric       OptionalFileEntryRef UmbrellaModuleMap =
6520b57cec5SDimitry Andric           getModuleMapFileForUniquing(UmbrellaModule);
6530b57cec5SDimitry Andric 
6540b57cec5SDimitry Andric       // Infer submodules for each of the directories we found between
6550b57cec5SDimitry Andric       // the directory of the umbrella header and the directory where
6560b57cec5SDimitry Andric       // the actual header is located.
6570b57cec5SDimitry Andric       bool Explicit = UmbrellaModule->InferExplicitSubmodules;
6580b57cec5SDimitry Andric 
659fe013be4SDimitry Andric       for (DirectoryEntryRef SkippedDir : llvm::reverse(SkippedDirs)) {
6600b57cec5SDimitry Andric         // Find or create the module that corresponds to this directory name.
6610b57cec5SDimitry Andric         SmallString<32> NameBuf;
6620b57cec5SDimitry Andric         StringRef Name = sanitizeFilenameAsIdentifier(
663fe013be4SDimitry Andric             llvm::sys::path::stem(SkippedDir.getName()), NameBuf);
6640b57cec5SDimitry Andric         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6650b57cec5SDimitry Andric                                     Explicit).first;
6660b57cec5SDimitry Andric         InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
6670b57cec5SDimitry Andric         Result->IsInferred = true;
6680b57cec5SDimitry Andric 
6690b57cec5SDimitry Andric         // Associate the module and the directory.
670349cc55cSDimitry Andric         UmbrellaDirs[SkippedDir] = Result;
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric         // If inferred submodules export everything they import, add a
6730b57cec5SDimitry Andric         // wildcard to the set of exports.
6740b57cec5SDimitry Andric         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
6750b57cec5SDimitry Andric           Result->Exports.push_back(Module::ExportDecl(nullptr, true));
6760b57cec5SDimitry Andric       }
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric       // Infer a submodule with the same name as this header file.
6790b57cec5SDimitry Andric       SmallString<32> NameBuf;
6800b57cec5SDimitry Andric       StringRef Name = sanitizeFilenameAsIdentifier(
681fe013be4SDimitry Andric                          llvm::sys::path::stem(File.getName()), NameBuf);
6820b57cec5SDimitry Andric       Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6830b57cec5SDimitry Andric                                   Explicit).first;
6840b57cec5SDimitry Andric       InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
6850b57cec5SDimitry Andric       Result->IsInferred = true;
6860b57cec5SDimitry Andric       Result->addTopHeader(File);
6870b57cec5SDimitry Andric 
6880b57cec5SDimitry Andric       // If inferred submodules export everything they import, add a
6890b57cec5SDimitry Andric       // wildcard to the set of exports.
6900b57cec5SDimitry Andric       if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
6910b57cec5SDimitry Andric         Result->Exports.push_back(Module::ExportDecl(nullptr, true));
6920b57cec5SDimitry Andric     } else {
6930b57cec5SDimitry Andric       // Record each of the directories we stepped through as being part of
6940b57cec5SDimitry Andric       // the module we found, since the umbrella header covers them all.
6950b57cec5SDimitry Andric       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
6960b57cec5SDimitry Andric         UmbrellaDirs[SkippedDirs[I]] = Result;
6970b57cec5SDimitry Andric     }
6980b57cec5SDimitry Andric 
6990b57cec5SDimitry Andric     KnownHeader Header(Result, NormalHeader);
7000b57cec5SDimitry Andric     Headers[File].push_back(Header);
7010b57cec5SDimitry Andric     return Header;
7020b57cec5SDimitry Andric   }
7030b57cec5SDimitry Andric 
7040b57cec5SDimitry Andric   return {};
7050b57cec5SDimitry Andric }
7060b57cec5SDimitry Andric 
7070b57cec5SDimitry Andric ArrayRef<ModuleMap::KnownHeader>
findAllModulesForHeader(FileEntryRef File)708fe013be4SDimitry Andric ModuleMap::findAllModulesForHeader(FileEntryRef File) {
7095ffd83dbSDimitry Andric   HeadersMap::iterator Known = findKnownHeader(File);
7105ffd83dbSDimitry Andric   if (Known != Headers.end())
7115ffd83dbSDimitry Andric     return Known->second;
7125ffd83dbSDimitry Andric 
7135ffd83dbSDimitry Andric   if (findOrCreateModuleForHeaderInUmbrellaDir(File))
7145ffd83dbSDimitry Andric     return Headers.find(File)->second;
7155ffd83dbSDimitry Andric 
716bdd1243dSDimitry Andric   return std::nullopt;
7175ffd83dbSDimitry Andric }
7185ffd83dbSDimitry Andric 
7195ffd83dbSDimitry Andric ArrayRef<ModuleMap::KnownHeader>
findResolvedModulesForHeader(FileEntryRef File) const720c9157d92SDimitry Andric ModuleMap::findResolvedModulesForHeader(FileEntryRef File) const {
7215ffd83dbSDimitry Andric   // FIXME: Is this necessary?
7220b57cec5SDimitry Andric   resolveHeaderDirectives(File);
7230b57cec5SDimitry Andric   auto It = Headers.find(File);
7240b57cec5SDimitry Andric   if (It == Headers.end())
725bdd1243dSDimitry Andric     return std::nullopt;
7260b57cec5SDimitry Andric   return It->second;
7270b57cec5SDimitry Andric }
7280b57cec5SDimitry Andric 
isHeaderInUnavailableModule(FileEntryRef Header) const729fe013be4SDimitry Andric bool ModuleMap::isHeaderInUnavailableModule(FileEntryRef Header) const {
7300b57cec5SDimitry Andric   return isHeaderUnavailableInModule(Header, nullptr);
7310b57cec5SDimitry Andric }
7320b57cec5SDimitry Andric 
isHeaderUnavailableInModule(FileEntryRef Header,const Module * RequestingModule) const733fe013be4SDimitry Andric bool ModuleMap::isHeaderUnavailableInModule(
734fe013be4SDimitry Andric     FileEntryRef Header, const Module *RequestingModule) const {
7350b57cec5SDimitry Andric   resolveHeaderDirectives(Header);
7360b57cec5SDimitry Andric   HeadersMap::const_iterator Known = Headers.find(Header);
7370b57cec5SDimitry Andric   if (Known != Headers.end()) {
7380b57cec5SDimitry Andric     for (SmallVectorImpl<KnownHeader>::const_iterator
7390b57cec5SDimitry Andric              I = Known->second.begin(),
7400b57cec5SDimitry Andric              E = Known->second.end();
7410b57cec5SDimitry Andric          I != E; ++I) {
7420b57cec5SDimitry Andric 
743bdd1243dSDimitry Andric       if (I->getRole() == ModuleMap::ExcludedHeader)
744bdd1243dSDimitry Andric         continue;
745bdd1243dSDimitry Andric 
7460b57cec5SDimitry Andric       if (I->isAvailable() &&
7470b57cec5SDimitry Andric           (!RequestingModule ||
7480b57cec5SDimitry Andric            I->getModule()->isSubModuleOf(RequestingModule))) {
7490b57cec5SDimitry Andric         // When no requesting module is available, the caller is looking if a
7500b57cec5SDimitry Andric         // header is part a module by only looking into the module map. This is
7510b57cec5SDimitry Andric         // done by warn_uncovered_module_header checks; don't consider textual
7520b57cec5SDimitry Andric         // headers part of it in this mode, otherwise we get misleading warnings
7530b57cec5SDimitry Andric         // that a umbrella header is not including a textual header.
7540b57cec5SDimitry Andric         if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
7550b57cec5SDimitry Andric           continue;
7560b57cec5SDimitry Andric         return false;
7570b57cec5SDimitry Andric       }
7580b57cec5SDimitry Andric     }
7590b57cec5SDimitry Andric     return true;
7600b57cec5SDimitry Andric   }
7610b57cec5SDimitry Andric 
762fe013be4SDimitry Andric   OptionalDirectoryEntryRef Dir = Header.getDir();
763fe013be4SDimitry Andric   SmallVector<DirectoryEntryRef, 2> SkippedDirs;
7640b57cec5SDimitry Andric   StringRef DirName = Dir->getName();
7650b57cec5SDimitry Andric 
7660b57cec5SDimitry Andric   auto IsUnavailable = [&](const Module *M) {
7670b57cec5SDimitry Andric     return !M->isAvailable() && (!RequestingModule ||
7680b57cec5SDimitry Andric                                  M->isSubModuleOf(RequestingModule));
7690b57cec5SDimitry Andric   };
7700b57cec5SDimitry Andric 
7710b57cec5SDimitry Andric   // Keep walking up the directory hierarchy, looking for a directory with
7720b57cec5SDimitry Andric   // an umbrella header.
7730b57cec5SDimitry Andric   do {
774fe013be4SDimitry Andric     auto KnownDir = UmbrellaDirs.find(*Dir);
7750b57cec5SDimitry Andric     if (KnownDir != UmbrellaDirs.end()) {
7760b57cec5SDimitry Andric       Module *Found = KnownDir->second;
7770b57cec5SDimitry Andric       if (IsUnavailable(Found))
7780b57cec5SDimitry Andric         return true;
7790b57cec5SDimitry Andric 
7800b57cec5SDimitry Andric       // Search up the module stack until we find a module with an umbrella
7810b57cec5SDimitry Andric       // directory.
7820b57cec5SDimitry Andric       Module *UmbrellaModule = Found;
783fe013be4SDimitry Andric       while (!UmbrellaModule->getEffectiveUmbrellaDir() &&
784fe013be4SDimitry Andric              UmbrellaModule->Parent)
7850b57cec5SDimitry Andric         UmbrellaModule = UmbrellaModule->Parent;
7860b57cec5SDimitry Andric 
7870b57cec5SDimitry Andric       if (UmbrellaModule->InferSubmodules) {
788fe013be4SDimitry Andric         for (DirectoryEntryRef SkippedDir : llvm::reverse(SkippedDirs)) {
7890b57cec5SDimitry Andric           // Find or create the module that corresponds to this directory name.
7900b57cec5SDimitry Andric           SmallString<32> NameBuf;
7910b57cec5SDimitry Andric           StringRef Name = sanitizeFilenameAsIdentifier(
792fe013be4SDimitry Andric               llvm::sys::path::stem(SkippedDir.getName()), NameBuf);
7930b57cec5SDimitry Andric           Found = lookupModuleQualified(Name, Found);
7940b57cec5SDimitry Andric           if (!Found)
7950b57cec5SDimitry Andric             return false;
7960b57cec5SDimitry Andric           if (IsUnavailable(Found))
7970b57cec5SDimitry Andric             return true;
7980b57cec5SDimitry Andric         }
7990b57cec5SDimitry Andric 
8000b57cec5SDimitry Andric         // Infer a submodule with the same name as this header file.
8010b57cec5SDimitry Andric         SmallString<32> NameBuf;
8020b57cec5SDimitry Andric         StringRef Name = sanitizeFilenameAsIdentifier(
803fe013be4SDimitry Andric                            llvm::sys::path::stem(Header.getName()),
8040b57cec5SDimitry Andric                            NameBuf);
8050b57cec5SDimitry Andric         Found = lookupModuleQualified(Name, Found);
8060b57cec5SDimitry Andric         if (!Found)
8070b57cec5SDimitry Andric           return false;
8080b57cec5SDimitry Andric       }
8090b57cec5SDimitry Andric 
8100b57cec5SDimitry Andric       return IsUnavailable(Found);
8110b57cec5SDimitry Andric     }
8120b57cec5SDimitry Andric 
813fe013be4SDimitry Andric     SkippedDirs.push_back(*Dir);
8140b57cec5SDimitry Andric 
8150b57cec5SDimitry Andric     // Retrieve our parent path.
8160b57cec5SDimitry Andric     DirName = llvm::sys::path::parent_path(DirName);
8170b57cec5SDimitry Andric     if (DirName.empty())
8180b57cec5SDimitry Andric       break;
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric     // Resolve the parent path to a directory entry.
821fe013be4SDimitry Andric     Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
8220b57cec5SDimitry Andric   } while (Dir);
8230b57cec5SDimitry Andric 
8240b57cec5SDimitry Andric   return false;
8250b57cec5SDimitry Andric }
8260b57cec5SDimitry Andric 
findModule(StringRef Name) const8270b57cec5SDimitry Andric Module *ModuleMap::findModule(StringRef Name) const {
8280b57cec5SDimitry Andric   llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
8290b57cec5SDimitry Andric   if (Known != Modules.end())
8300b57cec5SDimitry Andric     return Known->getValue();
8310b57cec5SDimitry Andric 
8320b57cec5SDimitry Andric   return nullptr;
8330b57cec5SDimitry Andric }
8340b57cec5SDimitry Andric 
lookupModuleUnqualified(StringRef Name,Module * Context) const8350b57cec5SDimitry Andric Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
8360b57cec5SDimitry Andric                                            Module *Context) const {
8370b57cec5SDimitry Andric   for(; Context; Context = Context->Parent) {
8380b57cec5SDimitry Andric     if (Module *Sub = lookupModuleQualified(Name, Context))
8390b57cec5SDimitry Andric       return Sub;
8400b57cec5SDimitry Andric   }
8410b57cec5SDimitry Andric 
8420b57cec5SDimitry Andric   return findModule(Name);
8430b57cec5SDimitry Andric }
8440b57cec5SDimitry Andric 
lookupModuleQualified(StringRef Name,Module * Context) const8450b57cec5SDimitry Andric Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
8460b57cec5SDimitry Andric   if (!Context)
8470b57cec5SDimitry Andric     return findModule(Name);
8480b57cec5SDimitry Andric 
8490b57cec5SDimitry Andric   return Context->findSubmodule(Name);
8500b57cec5SDimitry Andric }
8510b57cec5SDimitry Andric 
findOrCreateModule(StringRef Name,Module * Parent,bool IsFramework,bool IsExplicit)8520b57cec5SDimitry Andric std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
8530b57cec5SDimitry Andric                                                         Module *Parent,
8540b57cec5SDimitry Andric                                                         bool IsFramework,
8550b57cec5SDimitry Andric                                                         bool IsExplicit) {
8560b57cec5SDimitry Andric   // Try to find an existing module with this name.
8570b57cec5SDimitry Andric   if (Module *Sub = lookupModuleQualified(Name, Parent))
8580b57cec5SDimitry Andric     return std::make_pair(Sub, false);
8590b57cec5SDimitry Andric 
8600b57cec5SDimitry Andric   // Create a new module with this name.
8610b57cec5SDimitry Andric   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
8620b57cec5SDimitry Andric                               IsExplicit, NumCreatedModules++);
8630b57cec5SDimitry Andric   if (!Parent) {
8640b57cec5SDimitry Andric     if (LangOpts.CurrentModule == Name)
8650b57cec5SDimitry Andric       SourceModule = Result;
8660b57cec5SDimitry Andric     Modules[Name] = Result;
8670b57cec5SDimitry Andric     ModuleScopeIDs[Result] = CurrentModuleScopeID;
8680b57cec5SDimitry Andric   }
8690b57cec5SDimitry Andric   return std::make_pair(Result, true);
8700b57cec5SDimitry Andric }
8710b57cec5SDimitry Andric 
createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,Module * Parent)8720eae32dcSDimitry Andric Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
8730eae32dcSDimitry Andric                                                            Module *Parent) {
8740eae32dcSDimitry Andric   auto *Result = new Module("<global>", Loc, Parent, /*IsFramework*/ false,
8750eae32dcSDimitry Andric                             /*IsExplicit*/ true, NumCreatedModules++);
876fe013be4SDimitry Andric   Result->Kind = Module::ExplicitGlobalModuleFragment;
8770eae32dcSDimitry Andric   // If the created module isn't owned by a parent, send it to PendingSubmodules
8780eae32dcSDimitry Andric   // to wait for its parent.
8790eae32dcSDimitry Andric   if (!Result->Parent)
8800eae32dcSDimitry Andric     PendingSubmodules.emplace_back(Result);
8810eae32dcSDimitry Andric   return Result;
8820b57cec5SDimitry Andric }
8830b57cec5SDimitry Andric 
884c9157d92SDimitry Andric Module *
createImplicitGlobalModuleFragmentForModuleUnit(SourceLocation Loc,Module * Parent)885c9157d92SDimitry Andric ModuleMap::createImplicitGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
886c9157d92SDimitry Andric                                                            Module *Parent) {
887fe013be4SDimitry Andric   assert(Parent && "We should only create an implicit global module fragment "
888fe013be4SDimitry Andric                    "in a module purview");
889fe013be4SDimitry Andric   // Note: Here the `IsExplicit` parameter refers to the semantics in clang
890fe013be4SDimitry Andric   // modules. All the non-explicit submodules in clang modules will be exported
891fe013be4SDimitry Andric   // too. Here we simplify the implementation by using the concept.
892c9157d92SDimitry Andric   auto *Result =
893c9157d92SDimitry Andric       new Module("<implicit global>", Loc, Parent, /*IsFramework=*/false,
894c9157d92SDimitry Andric                  /*IsExplicit=*/false, NumCreatedModules++);
895fe013be4SDimitry Andric   Result->Kind = Module::ImplicitGlobalModuleFragment;
896fe013be4SDimitry Andric   return Result;
897fe013be4SDimitry Andric }
898fe013be4SDimitry Andric 
8990b57cec5SDimitry Andric Module *
createPrivateModuleFragmentForInterfaceUnit(Module * Parent,SourceLocation Loc)9000b57cec5SDimitry Andric ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
9010b57cec5SDimitry Andric                                                        SourceLocation Loc) {
9020b57cec5SDimitry Andric   auto *Result =
9030b57cec5SDimitry Andric       new Module("<private>", Loc, Parent, /*IsFramework*/ false,
9040b57cec5SDimitry Andric                  /*IsExplicit*/ true, NumCreatedModules++);
9050b57cec5SDimitry Andric   Result->Kind = Module::PrivateModuleFragment;
9060b57cec5SDimitry Andric   return Result;
9070b57cec5SDimitry Andric }
9080b57cec5SDimitry Andric 
createModuleUnitWithKind(SourceLocation Loc,StringRef Name,Module::ModuleKind Kind)909fe013be4SDimitry Andric Module *ModuleMap::createModuleUnitWithKind(SourceLocation Loc, StringRef Name,
910fe013be4SDimitry Andric                                             Module::ModuleKind Kind) {
911fe013be4SDimitry Andric   auto *Result =
912fe013be4SDimitry Andric       new Module(Name, Loc, nullptr, /*IsFramework*/ false,
913fe013be4SDimitry Andric                  /*IsExplicit*/ false, NumCreatedModules++);
914fe013be4SDimitry Andric   Result->Kind = Kind;
915fe013be4SDimitry Andric 
916fe013be4SDimitry Andric   // Reparent any current global module fragment as a submodule of this module.
917fe013be4SDimitry Andric   for (auto &Submodule : PendingSubmodules) {
918fe013be4SDimitry Andric     Submodule->setParent(Result);
919fe013be4SDimitry Andric     Submodule.release(); // now owned by parent
920fe013be4SDimitry Andric   }
921fe013be4SDimitry Andric   PendingSubmodules.clear();
922fe013be4SDimitry Andric   return Result;
923fe013be4SDimitry Andric }
924fe013be4SDimitry Andric 
createModuleForInterfaceUnit(SourceLocation Loc,StringRef Name)9250b57cec5SDimitry Andric Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
926bdd1243dSDimitry Andric                                                 StringRef Name) {
9270b57cec5SDimitry Andric   assert(LangOpts.CurrentModule == Name && "module name mismatch");
9280b57cec5SDimitry Andric   assert(!Modules[Name] && "redefining existing module");
9290b57cec5SDimitry Andric 
9300b57cec5SDimitry Andric   auto *Result =
931fe013be4SDimitry Andric       createModuleUnitWithKind(Loc, Name, Module::ModuleInterfaceUnit);
9320b57cec5SDimitry Andric   Modules[Name] = SourceModule = Result;
9330b57cec5SDimitry Andric 
9340b57cec5SDimitry Andric   // Mark the main source file as being within the newly-created module so that
9350b57cec5SDimitry Andric   // declarations and macros are properly visibility-restricted to it.
936c9157d92SDimitry Andric   auto MainFile = SourceMgr.getFileEntryRefForID(SourceMgr.getMainFileID());
9370b57cec5SDimitry Andric   assert(MainFile && "no input file for module interface");
938c9157d92SDimitry Andric   Headers[*MainFile].push_back(KnownHeader(Result, PrivateHeader));
9390b57cec5SDimitry Andric 
9400b57cec5SDimitry Andric   return Result;
9410b57cec5SDimitry Andric }
9420b57cec5SDimitry Andric 
createModuleForImplementationUnit(SourceLocation Loc,StringRef Name)943fe013be4SDimitry Andric Module *ModuleMap::createModuleForImplementationUnit(SourceLocation Loc,
944fe013be4SDimitry Andric                                                      StringRef Name) {
945fe013be4SDimitry Andric   assert(LangOpts.CurrentModule == Name && "module name mismatch");
946fe013be4SDimitry Andric   // The interface for this implementation must exist and be loaded.
947fe013be4SDimitry Andric   assert(Modules[Name] && Modules[Name]->Kind == Module::ModuleInterfaceUnit &&
948fe013be4SDimitry Andric          "creating implementation module without an interface");
949fe013be4SDimitry Andric 
950fe013be4SDimitry Andric   // Create an entry in the modules map to own the implementation unit module.
951fe013be4SDimitry Andric   // User module names must not start with a period (so that this cannot clash
952fe013be4SDimitry Andric   // with any legal user-defined module name).
953fe013be4SDimitry Andric   StringRef IName = ".ImplementationUnit";
954fe013be4SDimitry Andric   assert(!Modules[IName] && "multiple implementation units?");
955fe013be4SDimitry Andric 
956fe013be4SDimitry Andric   auto *Result =
957fe013be4SDimitry Andric       createModuleUnitWithKind(Loc, Name, Module::ModuleImplementationUnit);
958fe013be4SDimitry Andric   Modules[IName] = SourceModule = Result;
959fe013be4SDimitry Andric 
960fe013be4SDimitry Andric   // Check that the main file is present.
961fe013be4SDimitry Andric   assert(SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()) &&
962fe013be4SDimitry Andric          "no input file for module implementation");
963fe013be4SDimitry Andric 
964fe013be4SDimitry Andric   return Result;
965fe013be4SDimitry Andric }
966fe013be4SDimitry Andric 
createHeaderUnit(SourceLocation Loc,StringRef Name,Module::Header H)96781ad6265SDimitry Andric Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name,
96881ad6265SDimitry Andric                                     Module::Header H) {
96981ad6265SDimitry Andric   assert(LangOpts.CurrentModule == Name && "module name mismatch");
97081ad6265SDimitry Andric   assert(!Modules[Name] && "redefining existing module");
97181ad6265SDimitry Andric 
97281ad6265SDimitry Andric   auto *Result = new Module(Name, Loc, nullptr, /*IsFramework*/ false,
97381ad6265SDimitry Andric                             /*IsExplicit*/ false, NumCreatedModules++);
97481ad6265SDimitry Andric   Result->Kind = Module::ModuleHeaderUnit;
97581ad6265SDimitry Andric   Modules[Name] = SourceModule = Result;
97681ad6265SDimitry Andric   addHeader(Result, H, NormalHeader);
97781ad6265SDimitry Andric   return Result;
97881ad6265SDimitry Andric }
97981ad6265SDimitry Andric 
9800b57cec5SDimitry Andric /// For a framework module, infer the framework against which we
9810b57cec5SDimitry Andric /// should link.
inferFrameworkLink(Module * Mod)982fe013be4SDimitry Andric static void inferFrameworkLink(Module *Mod) {
9830b57cec5SDimitry Andric   assert(Mod->IsFramework && "Can only infer linking for framework modules");
9840b57cec5SDimitry Andric   assert(!Mod->isSubFramework() &&
9850b57cec5SDimitry Andric          "Can only infer linking for top-level frameworks");
9860b57cec5SDimitry Andric 
987cdc20ff6SDimitry Andric   StringRef FrameworkName(Mod->Name);
988cdc20ff6SDimitry Andric   FrameworkName.consume_back("_Private");
989cdc20ff6SDimitry Andric   Mod->LinkLibraries.push_back(Module::LinkLibrary(FrameworkName.str(),
9900b57cec5SDimitry Andric                                                    /*IsFramework=*/true));
9910b57cec5SDimitry Andric }
9920b57cec5SDimitry Andric 
inferFrameworkModule(DirectoryEntryRef FrameworkDir,bool IsSystem,Module * Parent)993fe013be4SDimitry Andric Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
9940b57cec5SDimitry Andric                                         bool IsSystem, Module *Parent) {
9950b57cec5SDimitry Andric   Attributes Attrs;
9960b57cec5SDimitry Andric   Attrs.IsSystem = IsSystem;
9970b57cec5SDimitry Andric   return inferFrameworkModule(FrameworkDir, Attrs, Parent);
9980b57cec5SDimitry Andric }
9990b57cec5SDimitry Andric 
inferFrameworkModule(DirectoryEntryRef FrameworkDir,Attributes Attrs,Module * Parent)1000fe013be4SDimitry Andric Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
10010b57cec5SDimitry Andric                                         Attributes Attrs, Module *Parent) {
10020b57cec5SDimitry Andric   // Note: as an egregious but useful hack we use the real path here, because
10030b57cec5SDimitry Andric   // we might be looking at an embedded framework that symlinks out to a
10040b57cec5SDimitry Andric   // top-level framework, and we need to infer as if we were naming the
10050b57cec5SDimitry Andric   // top-level framework.
10060b57cec5SDimitry Andric   StringRef FrameworkDirName =
10070b57cec5SDimitry Andric       SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
10080b57cec5SDimitry Andric 
10090b57cec5SDimitry Andric   // In case this is a case-insensitive filesystem, use the canonical
10100b57cec5SDimitry Andric   // directory name as the ModuleName, since modules are case-sensitive.
10110b57cec5SDimitry Andric   // FIXME: we should be able to give a fix-it hint for the correct spelling.
10120b57cec5SDimitry Andric   SmallString<32> ModuleNameStorage;
10130b57cec5SDimitry Andric   StringRef ModuleName = sanitizeFilenameAsIdentifier(
10140b57cec5SDimitry Andric       llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
10150b57cec5SDimitry Andric 
10160b57cec5SDimitry Andric   // Check whether we've already found this module.
10170b57cec5SDimitry Andric   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
10180b57cec5SDimitry Andric     return Mod;
10190b57cec5SDimitry Andric 
10200b57cec5SDimitry Andric   FileManager &FileMgr = SourceMgr.getFileManager();
10210b57cec5SDimitry Andric 
10220b57cec5SDimitry Andric   // If the framework has a parent path from which we're allowed to infer
10230b57cec5SDimitry Andric   // a framework module, do so.
1024c9157d92SDimitry Andric   OptionalFileEntryRef ModuleMapFile;
10250b57cec5SDimitry Andric   if (!Parent) {
10260b57cec5SDimitry Andric     // Determine whether we're allowed to infer a module map.
10270b57cec5SDimitry Andric     bool canInfer = false;
10280b57cec5SDimitry Andric     if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
10290b57cec5SDimitry Andric       // Figure out the parent path.
10300b57cec5SDimitry Andric       StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
1031fe013be4SDimitry Andric       if (auto ParentDir = FileMgr.getOptionalDirectoryRef(Parent)) {
10320b57cec5SDimitry Andric         // Check whether we have already looked into the parent directory
10330b57cec5SDimitry Andric         // for a module map.
10340b57cec5SDimitry Andric         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
1035a7dea167SDimitry Andric           inferred = InferredDirectories.find(*ParentDir);
10360b57cec5SDimitry Andric         if (inferred == InferredDirectories.end()) {
10370b57cec5SDimitry Andric           // We haven't looked here before. Load a module map, if there is
10380b57cec5SDimitry Andric           // one.
1039c9157d92SDimitry Andric           bool IsFrameworkDir = Parent.ends_with(".framework");
1040fe013be4SDimitry Andric           if (OptionalFileEntryRef ModMapFile =
1041a7dea167SDimitry Andric                   HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) {
1042fe013be4SDimitry Andric             parseModuleMapFile(*ModMapFile, Attrs.IsSystem, *ParentDir);
1043a7dea167SDimitry Andric             inferred = InferredDirectories.find(*ParentDir);
10440b57cec5SDimitry Andric           }
10450b57cec5SDimitry Andric 
10460b57cec5SDimitry Andric           if (inferred == InferredDirectories.end())
10470b57cec5SDimitry Andric             inferred = InferredDirectories.insert(
1048a7dea167SDimitry Andric                          std::make_pair(*ParentDir, InferredDirectory())).first;
10490b57cec5SDimitry Andric         }
10500b57cec5SDimitry Andric 
10510b57cec5SDimitry Andric         if (inferred->second.InferModules) {
10520b57cec5SDimitry Andric           // We're allowed to infer for this directory, but make sure it's okay
10530b57cec5SDimitry Andric           // to infer this particular module.
10540b57cec5SDimitry Andric           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
1055349cc55cSDimitry Andric           canInfer =
1056349cc55cSDimitry Andric               !llvm::is_contained(inferred->second.ExcludedModules, Name);
10570b57cec5SDimitry Andric 
10580b57cec5SDimitry Andric           Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
10590b57cec5SDimitry Andric           Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
10600b57cec5SDimitry Andric           Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
10610b57cec5SDimitry Andric           Attrs.NoUndeclaredIncludes |=
10620b57cec5SDimitry Andric               inferred->second.Attrs.NoUndeclaredIncludes;
10630b57cec5SDimitry Andric           ModuleMapFile = inferred->second.ModuleMapFile;
10640b57cec5SDimitry Andric         }
10650b57cec5SDimitry Andric       }
10660b57cec5SDimitry Andric     }
10670b57cec5SDimitry Andric 
10680b57cec5SDimitry Andric     // If we're not allowed to infer a framework module, don't.
10690b57cec5SDimitry Andric     if (!canInfer)
10700b57cec5SDimitry Andric       return nullptr;
1071bdd1243dSDimitry Andric   } else {
1072c9157d92SDimitry Andric     ModuleMapFile = getModuleMapFileForUniquing(Parent);
1073bdd1243dSDimitry Andric   }
10740b57cec5SDimitry Andric 
10750b57cec5SDimitry Andric   // Look for an umbrella header.
1076fe013be4SDimitry Andric   SmallString<128> UmbrellaName = FrameworkDir.getName();
10770b57cec5SDimitry Andric   llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
1078bdd1243dSDimitry Andric   auto UmbrellaHeader = FileMgr.getOptionalFileRef(UmbrellaName);
10790b57cec5SDimitry Andric 
10800b57cec5SDimitry Andric   // FIXME: If there's no umbrella header, we could probably scan the
10810b57cec5SDimitry Andric   // framework to load *everything*. But, it's not clear that this is a good
10820b57cec5SDimitry Andric   // idea.
10830b57cec5SDimitry Andric   if (!UmbrellaHeader)
10840b57cec5SDimitry Andric     return nullptr;
10850b57cec5SDimitry Andric 
10860b57cec5SDimitry Andric   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
10870b57cec5SDimitry Andric                               /*IsFramework=*/true, /*IsExplicit=*/false,
10880b57cec5SDimitry Andric                               NumCreatedModules++);
10890b57cec5SDimitry Andric   InferredModuleAllowedBy[Result] = ModuleMapFile;
10900b57cec5SDimitry Andric   Result->IsInferred = true;
10910b57cec5SDimitry Andric   if (!Parent) {
10920b57cec5SDimitry Andric     if (LangOpts.CurrentModule == ModuleName)
10930b57cec5SDimitry Andric       SourceModule = Result;
10940b57cec5SDimitry Andric     Modules[ModuleName] = Result;
10950b57cec5SDimitry Andric     ModuleScopeIDs[Result] = CurrentModuleScopeID;
10960b57cec5SDimitry Andric   }
10970b57cec5SDimitry Andric 
10980b57cec5SDimitry Andric   Result->IsSystem |= Attrs.IsSystem;
10990b57cec5SDimitry Andric   Result->IsExternC |= Attrs.IsExternC;
11000b57cec5SDimitry Andric   Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
11010b57cec5SDimitry Andric   Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
11020b57cec5SDimitry Andric   Result->Directory = FrameworkDir;
11030b57cec5SDimitry Andric 
1104fe6060f1SDimitry Andric   // Chop off the first framework bit, as that is implied.
1105fe6060f1SDimitry Andric   StringRef RelativePath = UmbrellaName.str().substr(
1106fe6060f1SDimitry Andric       Result->getTopLevelModule()->Directory->getName().size());
1107fe6060f1SDimitry Andric   RelativePath = llvm::sys::path::relative_path(RelativePath);
1108fe6060f1SDimitry Andric 
11090b57cec5SDimitry Andric   // umbrella header "umbrella-header-name"
1110fe013be4SDimitry Andric   setUmbrellaHeaderAsWritten(Result, *UmbrellaHeader, ModuleName + ".h",
1111fe013be4SDimitry Andric                              RelativePath);
11120b57cec5SDimitry Andric 
11130b57cec5SDimitry Andric   // export *
11140b57cec5SDimitry Andric   Result->Exports.push_back(Module::ExportDecl(nullptr, true));
11150b57cec5SDimitry Andric 
11160b57cec5SDimitry Andric   // module * { export * }
11170b57cec5SDimitry Andric   Result->InferSubmodules = true;
11180b57cec5SDimitry Andric   Result->InferExportWildcard = true;
11190b57cec5SDimitry Andric 
11200b57cec5SDimitry Andric   // Look for subframeworks.
11210b57cec5SDimitry Andric   std::error_code EC;
1122fe013be4SDimitry Andric   SmallString<128> SubframeworksDirName = FrameworkDir.getName();
11230b57cec5SDimitry Andric   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
11240b57cec5SDimitry Andric   llvm::sys::path::native(SubframeworksDirName);
11250b57cec5SDimitry Andric   llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
11260b57cec5SDimitry Andric   for (llvm::vfs::directory_iterator
11270b57cec5SDimitry Andric            Dir = FS.dir_begin(SubframeworksDirName, EC),
11280b57cec5SDimitry Andric            DirEnd;
11290b57cec5SDimitry Andric        Dir != DirEnd && !EC; Dir.increment(EC)) {
1130c9157d92SDimitry Andric     if (!StringRef(Dir->path()).ends_with(".framework"))
11310b57cec5SDimitry Andric       continue;
11320b57cec5SDimitry Andric 
1133fe013be4SDimitry Andric     if (auto SubframeworkDir = FileMgr.getOptionalDirectoryRef(Dir->path())) {
11340b57cec5SDimitry Andric       // Note: as an egregious but useful hack, we use the real path here and
11350b57cec5SDimitry Andric       // check whether it is actually a subdirectory of the parent directory.
11360b57cec5SDimitry Andric       // This will not be the case if the 'subframework' is actually a symlink
11370b57cec5SDimitry Andric       // out to a top-level framework.
1138a7dea167SDimitry Andric       StringRef SubframeworkDirName =
1139a7dea167SDimitry Andric           FileMgr.getCanonicalName(*SubframeworkDir);
11400b57cec5SDimitry Andric       bool FoundParent = false;
11410b57cec5SDimitry Andric       do {
11420b57cec5SDimitry Andric         // Get the parent directory name.
11430b57cec5SDimitry Andric         SubframeworkDirName
11440b57cec5SDimitry Andric           = llvm::sys::path::parent_path(SubframeworkDirName);
11450b57cec5SDimitry Andric         if (SubframeworkDirName.empty())
11460b57cec5SDimitry Andric           break;
11470b57cec5SDimitry Andric 
1148a7dea167SDimitry Andric         if (auto SubDir = FileMgr.getDirectory(SubframeworkDirName)) {
1149a7dea167SDimitry Andric           if (*SubDir == FrameworkDir) {
11500b57cec5SDimitry Andric             FoundParent = true;
11510b57cec5SDimitry Andric             break;
11520b57cec5SDimitry Andric           }
1153a7dea167SDimitry Andric         }
11540b57cec5SDimitry Andric       } while (true);
11550b57cec5SDimitry Andric 
11560b57cec5SDimitry Andric       if (!FoundParent)
11570b57cec5SDimitry Andric         continue;
11580b57cec5SDimitry Andric 
11590b57cec5SDimitry Andric       // FIXME: Do we want to warn about subframeworks without umbrella headers?
1160a7dea167SDimitry Andric       inferFrameworkModule(*SubframeworkDir, Attrs, Result);
11610b57cec5SDimitry Andric     }
11620b57cec5SDimitry Andric   }
11630b57cec5SDimitry Andric 
11640b57cec5SDimitry Andric   // If the module is a top-level framework, automatically link against the
11650b57cec5SDimitry Andric   // framework.
1166fe013be4SDimitry Andric   if (!Result->isSubFramework())
1167fe013be4SDimitry Andric     inferFrameworkLink(Result);
11680b57cec5SDimitry Andric 
11690b57cec5SDimitry Andric   return Result;
11700b57cec5SDimitry Andric }
11710b57cec5SDimitry Andric 
createShadowedModule(StringRef Name,bool IsFramework,Module * ShadowingModule)11720b57cec5SDimitry Andric Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
11730b57cec5SDimitry Andric                                         Module *ShadowingModule) {
11740b57cec5SDimitry Andric 
11750b57cec5SDimitry Andric   // Create a new module with this name.
11760b57cec5SDimitry Andric   Module *Result =
11770b57cec5SDimitry Andric       new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
11780b57cec5SDimitry Andric                  /*IsExplicit=*/false, NumCreatedModules++);
11790b57cec5SDimitry Andric   Result->ShadowingModule = ShadowingModule;
11805ffd83dbSDimitry Andric   Result->markUnavailable(/*Unimportable*/true);
11810b57cec5SDimitry Andric   ModuleScopeIDs[Result] = CurrentModuleScopeID;
11820b57cec5SDimitry Andric   ShadowModules.push_back(Result);
11830b57cec5SDimitry Andric 
11840b57cec5SDimitry Andric   return Result;
11850b57cec5SDimitry Andric }
11860b57cec5SDimitry Andric 
setUmbrellaHeaderAsWritten(Module * Mod,FileEntryRef UmbrellaHeader,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)1187fe013be4SDimitry Andric void ModuleMap::setUmbrellaHeaderAsWritten(
1188bdd1243dSDimitry Andric     Module *Mod, FileEntryRef UmbrellaHeader, const Twine &NameAsWritten,
1189fe6060f1SDimitry Andric     const Twine &PathRelativeToRootModuleDirectory) {
11900b57cec5SDimitry Andric   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
1191fe013be4SDimitry Andric   Mod->Umbrella = UmbrellaHeader;
11920b57cec5SDimitry Andric   Mod->UmbrellaAsWritten = NameAsWritten.str();
1193fe6060f1SDimitry Andric   Mod->UmbrellaRelativeToRootModuleDirectory =
1194fe6060f1SDimitry Andric       PathRelativeToRootModuleDirectory.str();
1195bdd1243dSDimitry Andric   UmbrellaDirs[UmbrellaHeader.getDir()] = Mod;
11960b57cec5SDimitry Andric 
11970b57cec5SDimitry Andric   // Notify callbacks that we just added a new header.
11980b57cec5SDimitry Andric   for (const auto &Cb : Callbacks)
1199fe013be4SDimitry Andric     Cb->moduleMapAddUmbrellaHeader(UmbrellaHeader);
12000b57cec5SDimitry Andric }
12010b57cec5SDimitry Andric 
setUmbrellaDirAsWritten(Module * Mod,DirectoryEntryRef UmbrellaDir,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)1202fe013be4SDimitry Andric void ModuleMap::setUmbrellaDirAsWritten(
1203fe013be4SDimitry Andric     Module *Mod, DirectoryEntryRef UmbrellaDir, const Twine &NameAsWritten,
1204fe6060f1SDimitry Andric     const Twine &PathRelativeToRootModuleDirectory) {
1205fe6060f1SDimitry Andric   Mod->Umbrella = UmbrellaDir;
12060b57cec5SDimitry Andric   Mod->UmbrellaAsWritten = NameAsWritten.str();
1207fe6060f1SDimitry Andric   Mod->UmbrellaRelativeToRootModuleDirectory =
1208fe6060f1SDimitry Andric       PathRelativeToRootModuleDirectory.str();
12090b57cec5SDimitry Andric   UmbrellaDirs[UmbrellaDir] = Mod;
12100b57cec5SDimitry Andric }
12110b57cec5SDimitry Andric 
addUnresolvedHeader(Module * Mod,Module::UnresolvedHeaderDirective Header,bool & NeedsFramework)12120b57cec5SDimitry Andric void ModuleMap::addUnresolvedHeader(Module *Mod,
12130b57cec5SDimitry Andric                                     Module::UnresolvedHeaderDirective Header,
12140b57cec5SDimitry Andric                                     bool &NeedsFramework) {
12150b57cec5SDimitry Andric   // If there is a builtin counterpart to this file, add it now so it can
12160b57cec5SDimitry Andric   // wrap the system header.
12170b57cec5SDimitry Andric   if (resolveAsBuiltinHeader(Mod, Header)) {
12180b57cec5SDimitry Andric     // If we have both a builtin and system version of the file, the
12190b57cec5SDimitry Andric     // builtin version may want to inject macros into the system header, so
12200b57cec5SDimitry Andric     // force the system header to be treated as a textual header in this
12210b57cec5SDimitry Andric     // case.
12220b57cec5SDimitry Andric     Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
12230b57cec5SDimitry Andric         headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
12240b57cec5SDimitry Andric     Header.HasBuiltinHeader = true;
12250b57cec5SDimitry Andric   }
12260b57cec5SDimitry Andric 
12270b57cec5SDimitry Andric   // If possible, don't stat the header until we need to. This requires the
12280b57cec5SDimitry Andric   // user to have provided us with some stat information about the file.
12290b57cec5SDimitry Andric   // FIXME: Add support for lazily stat'ing umbrella headers and excluded
12300b57cec5SDimitry Andric   // headers.
12310b57cec5SDimitry Andric   if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
12320b57cec5SDimitry Andric       Header.Kind != Module::HK_Excluded) {
12330b57cec5SDimitry Andric     // We expect more variation in mtime than size, so if we're given both,
12340b57cec5SDimitry Andric     // use the mtime as the key.
12350b57cec5SDimitry Andric     if (Header.ModTime)
12360b57cec5SDimitry Andric       LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
12370b57cec5SDimitry Andric     else
12380b57cec5SDimitry Andric       LazyHeadersBySize[*Header.Size].push_back(Mod);
12390b57cec5SDimitry Andric     Mod->UnresolvedHeaders.push_back(Header);
12400b57cec5SDimitry Andric     return;
12410b57cec5SDimitry Andric   }
12420b57cec5SDimitry Andric 
12430b57cec5SDimitry Andric   // We don't have stat information or can't defer looking this file up.
12440b57cec5SDimitry Andric   // Perform the lookup now.
12450b57cec5SDimitry Andric   resolveHeader(Mod, Header, NeedsFramework);
12460b57cec5SDimitry Andric }
12470b57cec5SDimitry Andric 
resolveHeaderDirectives(const FileEntry * File) const12480b57cec5SDimitry Andric void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
12490b57cec5SDimitry Andric   auto BySize = LazyHeadersBySize.find(File->getSize());
12500b57cec5SDimitry Andric   if (BySize != LazyHeadersBySize.end()) {
12510b57cec5SDimitry Andric     for (auto *M : BySize->second)
125281ad6265SDimitry Andric       resolveHeaderDirectives(M, File);
12530b57cec5SDimitry Andric     LazyHeadersBySize.erase(BySize);
12540b57cec5SDimitry Andric   }
12550b57cec5SDimitry Andric 
12560b57cec5SDimitry Andric   auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
12570b57cec5SDimitry Andric   if (ByModTime != LazyHeadersByModTime.end()) {
12580b57cec5SDimitry Andric     for (auto *M : ByModTime->second)
125981ad6265SDimitry Andric       resolveHeaderDirectives(M, File);
12600b57cec5SDimitry Andric     LazyHeadersByModTime.erase(ByModTime);
12610b57cec5SDimitry Andric   }
12620b57cec5SDimitry Andric }
12630b57cec5SDimitry Andric 
resolveHeaderDirectives(Module * Mod,std::optional<const FileEntry * > File) const126481ad6265SDimitry Andric void ModuleMap::resolveHeaderDirectives(
1265bdd1243dSDimitry Andric     Module *Mod, std::optional<const FileEntry *> File) const {
12660b57cec5SDimitry Andric   bool NeedsFramework = false;
126781ad6265SDimitry Andric   SmallVector<Module::UnresolvedHeaderDirective, 1> NewHeaders;
1268bdd1243dSDimitry Andric   const auto Size = File ? (*File)->getSize() : 0;
1269bdd1243dSDimitry Andric   const auto ModTime = File ? (*File)->getModificationTime() : 0;
127081ad6265SDimitry Andric 
127181ad6265SDimitry Andric   for (auto &Header : Mod->UnresolvedHeaders) {
127281ad6265SDimitry Andric     if (File && ((Header.ModTime && Header.ModTime != ModTime) ||
127381ad6265SDimitry Andric                  (Header.Size && Header.Size != Size)))
127481ad6265SDimitry Andric       NewHeaders.push_back(Header);
127581ad6265SDimitry Andric     else
12760b57cec5SDimitry Andric       // This operation is logically const; we're just changing how we represent
12770b57cec5SDimitry Andric       // the header information for this file.
12780b57cec5SDimitry Andric       const_cast<ModuleMap *>(this)->resolveHeader(Mod, Header, NeedsFramework);
127981ad6265SDimitry Andric   }
128081ad6265SDimitry Andric   Mod->UnresolvedHeaders.swap(NewHeaders);
12810b57cec5SDimitry Andric }
12820b57cec5SDimitry Andric 
addHeader(Module * Mod,Module::Header Header,ModuleHeaderRole Role,bool Imported)12830b57cec5SDimitry Andric void ModuleMap::addHeader(Module *Mod, Module::Header Header,
12840b57cec5SDimitry Andric                           ModuleHeaderRole Role, bool Imported) {
12850b57cec5SDimitry Andric   KnownHeader KH(Mod, Role);
12860b57cec5SDimitry Andric 
12870b57cec5SDimitry Andric   // Only add each header to the headers list once.
12880b57cec5SDimitry Andric   // FIXME: Should we diagnose if a header is listed twice in the
12890b57cec5SDimitry Andric   // same module definition?
12900b57cec5SDimitry Andric   auto &HeaderList = Headers[Header.Entry];
1291349cc55cSDimitry Andric   if (llvm::is_contained(HeaderList, KH))
12920b57cec5SDimitry Andric     return;
12930b57cec5SDimitry Andric 
12940b57cec5SDimitry Andric   HeaderList.push_back(KH);
12950b57cec5SDimitry Andric   Mod->Headers[headerRoleToKind(Role)].push_back(Header);
12960b57cec5SDimitry Andric 
1297c9157d92SDimitry Andric   bool isCompilingModuleHeader = Mod->isForBuilding(LangOpts);
12980b57cec5SDimitry Andric   if (!Imported || isCompilingModuleHeader) {
12990b57cec5SDimitry Andric     // When we import HeaderFileInfo, the external source is expected to
13000b57cec5SDimitry Andric     // set the isModuleHeader flag itself.
13010b57cec5SDimitry Andric     HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
13020b57cec5SDimitry Andric                                     isCompilingModuleHeader);
13030b57cec5SDimitry Andric   }
13040b57cec5SDimitry Andric 
13050b57cec5SDimitry Andric   // Notify callbacks that we just added a new header.
13060b57cec5SDimitry Andric   for (const auto &Cb : Callbacks)
1307fe013be4SDimitry Andric     Cb->moduleMapAddHeader(Header.Entry.getName());
13080b57cec5SDimitry Andric }
13090b57cec5SDimitry Andric 
1310bdd1243dSDimitry Andric OptionalFileEntryRef
getContainingModuleMapFile(const Module * Module) const13110b57cec5SDimitry Andric ModuleMap::getContainingModuleMapFile(const Module *Module) const {
13120b57cec5SDimitry Andric   if (Module->DefinitionLoc.isInvalid())
1313bdd1243dSDimitry Andric     return std::nullopt;
13140b57cec5SDimitry Andric 
1315bdd1243dSDimitry Andric   return SourceMgr.getFileEntryRefForID(
13160b57cec5SDimitry Andric       SourceMgr.getFileID(Module->DefinitionLoc));
13170b57cec5SDimitry Andric }
13180b57cec5SDimitry Andric 
1319bdd1243dSDimitry Andric OptionalFileEntryRef
getModuleMapFileForUniquing(const Module * M) const1320bdd1243dSDimitry Andric ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
13210b57cec5SDimitry Andric   if (M->IsInferred) {
13220b57cec5SDimitry Andric     assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
1323c9157d92SDimitry Andric     return InferredModuleAllowedBy.find(M)->second;
13240b57cec5SDimitry Andric   }
13250b57cec5SDimitry Andric   return getContainingModuleMapFile(M);
13260b57cec5SDimitry Andric }
13270b57cec5SDimitry Andric 
setInferredModuleAllowedBy(Module * M,OptionalFileEntryRef ModMap)1328c9157d92SDimitry Andric void ModuleMap::setInferredModuleAllowedBy(Module *M,
1329c9157d92SDimitry Andric                                            OptionalFileEntryRef ModMap) {
13300b57cec5SDimitry Andric   assert(M->IsInferred && "module not inferred");
13310b57cec5SDimitry Andric   InferredModuleAllowedBy[M] = ModMap;
13320b57cec5SDimitry Andric }
13330b57cec5SDimitry Andric 
1334bdd1243dSDimitry Andric std::error_code
canonicalizeModuleMapPath(SmallVectorImpl<char> & Path)1335bdd1243dSDimitry Andric ModuleMap::canonicalizeModuleMapPath(SmallVectorImpl<char> &Path) {
1336bdd1243dSDimitry Andric   StringRef Dir = llvm::sys::path::parent_path({Path.data(), Path.size()});
1337bdd1243dSDimitry Andric 
1338bdd1243dSDimitry Andric   // Do not canonicalize within the framework; the module map parser expects
1339bdd1243dSDimitry Andric   // Modules/ not Versions/A/Modules.
1340bdd1243dSDimitry Andric   if (llvm::sys::path::filename(Dir) == "Modules") {
1341bdd1243dSDimitry Andric     StringRef Parent = llvm::sys::path::parent_path(Dir);
1342c9157d92SDimitry Andric     if (Parent.ends_with(".framework"))
1343bdd1243dSDimitry Andric       Dir = Parent;
1344bdd1243dSDimitry Andric   }
1345bdd1243dSDimitry Andric 
1346bdd1243dSDimitry Andric   FileManager &FM = SourceMgr.getFileManager();
1347fe013be4SDimitry Andric   auto DirEntry = FM.getDirectoryRef(Dir.empty() ? "." : Dir);
1348bdd1243dSDimitry Andric   if (!DirEntry)
1349fe013be4SDimitry Andric     return llvm::errorToErrorCode(DirEntry.takeError());
1350bdd1243dSDimitry Andric 
1351bdd1243dSDimitry Andric   // Canonicalize the directory.
1352bdd1243dSDimitry Andric   StringRef CanonicalDir = FM.getCanonicalName(*DirEntry);
1353fe013be4SDimitry Andric   if (CanonicalDir != Dir)
1354fe013be4SDimitry Andric     llvm::sys::path::replace_path_prefix(Path, Dir, CanonicalDir);
1355bdd1243dSDimitry Andric 
1356bdd1243dSDimitry Andric   // In theory, the filename component should also be canonicalized if it
1357bdd1243dSDimitry Andric   // on a case-insensitive filesystem. However, the extra canonicalization is
1358bdd1243dSDimitry Andric   // expensive and if clang looked up the filename it will always be lowercase.
1359bdd1243dSDimitry Andric 
1360bdd1243dSDimitry Andric   // Remove ., remove redundant separators, and switch to native separators.
1361bdd1243dSDimitry Andric   // This is needed for separators between CanonicalDir and the filename.
1362bdd1243dSDimitry Andric   llvm::sys::path::remove_dots(Path);
1363bdd1243dSDimitry Andric 
1364bdd1243dSDimitry Andric   return std::error_code();
1365bdd1243dSDimitry Andric }
1366bdd1243dSDimitry Andric 
addAdditionalModuleMapFile(const Module * M,FileEntryRef ModuleMap)13675ffd83dbSDimitry Andric void ModuleMap::addAdditionalModuleMapFile(const Module *M,
1368c9157d92SDimitry Andric                                            FileEntryRef ModuleMap) {
13695ffd83dbSDimitry Andric   AdditionalModMaps[M].insert(ModuleMap);
13705ffd83dbSDimitry Andric }
13715ffd83dbSDimitry Andric 
dump()13720b57cec5SDimitry Andric LLVM_DUMP_METHOD void ModuleMap::dump() {
13730b57cec5SDimitry Andric   llvm::errs() << "Modules:";
13740b57cec5SDimitry Andric   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
13750b57cec5SDimitry Andric                                         MEnd = Modules.end();
13760b57cec5SDimitry Andric        M != MEnd; ++M)
13770b57cec5SDimitry Andric     M->getValue()->print(llvm::errs(), 2);
13780b57cec5SDimitry Andric 
13790b57cec5SDimitry Andric   llvm::errs() << "Headers:";
13800b57cec5SDimitry Andric   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
13810b57cec5SDimitry Andric        H != HEnd; ++H) {
1382c9157d92SDimitry Andric     llvm::errs() << "  \"" << H->first.getName() << "\" -> ";
13830b57cec5SDimitry Andric     for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
13840b57cec5SDimitry Andric                                                       E = H->second.end();
13850b57cec5SDimitry Andric          I != E; ++I) {
13860b57cec5SDimitry Andric       if (I != H->second.begin())
13870b57cec5SDimitry Andric         llvm::errs() << ",";
13880b57cec5SDimitry Andric       llvm::errs() << I->getModule()->getFullModuleName();
13890b57cec5SDimitry Andric     }
13900b57cec5SDimitry Andric     llvm::errs() << "\n";
13910b57cec5SDimitry Andric   }
13920b57cec5SDimitry Andric }
13930b57cec5SDimitry Andric 
resolveExports(Module * Mod,bool Complain)13940b57cec5SDimitry Andric bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
13950b57cec5SDimitry Andric   auto Unresolved = std::move(Mod->UnresolvedExports);
13960b57cec5SDimitry Andric   Mod->UnresolvedExports.clear();
13970b57cec5SDimitry Andric   for (auto &UE : Unresolved) {
13980b57cec5SDimitry Andric     Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
13990b57cec5SDimitry Andric     if (Export.getPointer() || Export.getInt())
14000b57cec5SDimitry Andric       Mod->Exports.push_back(Export);
14010b57cec5SDimitry Andric     else
14020b57cec5SDimitry Andric       Mod->UnresolvedExports.push_back(UE);
14030b57cec5SDimitry Andric   }
14040b57cec5SDimitry Andric   return !Mod->UnresolvedExports.empty();
14050b57cec5SDimitry Andric }
14060b57cec5SDimitry Andric 
resolveUses(Module * Mod,bool Complain)14070b57cec5SDimitry Andric bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
1408c9157d92SDimitry Andric   auto *Top = Mod->getTopLevelModule();
1409c9157d92SDimitry Andric   auto Unresolved = std::move(Top->UnresolvedDirectUses);
1410c9157d92SDimitry Andric   Top->UnresolvedDirectUses.clear();
14110b57cec5SDimitry Andric   for (auto &UDU : Unresolved) {
1412c9157d92SDimitry Andric     Module *DirectUse = resolveModuleId(UDU, Top, Complain);
14130b57cec5SDimitry Andric     if (DirectUse)
1414c9157d92SDimitry Andric       Top->DirectUses.push_back(DirectUse);
14150b57cec5SDimitry Andric     else
1416c9157d92SDimitry Andric       Top->UnresolvedDirectUses.push_back(UDU);
14170b57cec5SDimitry Andric   }
1418c9157d92SDimitry Andric   return !Top->UnresolvedDirectUses.empty();
14190b57cec5SDimitry Andric }
14200b57cec5SDimitry Andric 
resolveConflicts(Module * Mod,bool Complain)14210b57cec5SDimitry Andric bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
14220b57cec5SDimitry Andric   auto Unresolved = std::move(Mod->UnresolvedConflicts);
14230b57cec5SDimitry Andric   Mod->UnresolvedConflicts.clear();
14240b57cec5SDimitry Andric   for (auto &UC : Unresolved) {
14250b57cec5SDimitry Andric     if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
14260b57cec5SDimitry Andric       Module::Conflict Conflict;
14270b57cec5SDimitry Andric       Conflict.Other = OtherMod;
14280b57cec5SDimitry Andric       Conflict.Message = UC.Message;
14290b57cec5SDimitry Andric       Mod->Conflicts.push_back(Conflict);
14300b57cec5SDimitry Andric     } else
14310b57cec5SDimitry Andric       Mod->UnresolvedConflicts.push_back(UC);
14320b57cec5SDimitry Andric   }
14330b57cec5SDimitry Andric   return !Mod->UnresolvedConflicts.empty();
14340b57cec5SDimitry Andric }
14350b57cec5SDimitry Andric 
14360b57cec5SDimitry Andric //----------------------------------------------------------------------------//
14370b57cec5SDimitry Andric // Module map file parser
14380b57cec5SDimitry Andric //----------------------------------------------------------------------------//
14390b57cec5SDimitry Andric 
14400b57cec5SDimitry Andric namespace clang {
14410b57cec5SDimitry Andric 
14420b57cec5SDimitry Andric   /// A token in a module map file.
14430b57cec5SDimitry Andric   struct MMToken {
14440b57cec5SDimitry Andric     enum TokenKind {
14450b57cec5SDimitry Andric       Comma,
14460b57cec5SDimitry Andric       ConfigMacros,
14470b57cec5SDimitry Andric       Conflict,
14480b57cec5SDimitry Andric       EndOfFile,
14490b57cec5SDimitry Andric       HeaderKeyword,
14500b57cec5SDimitry Andric       Identifier,
14510b57cec5SDimitry Andric       Exclaim,
14520b57cec5SDimitry Andric       ExcludeKeyword,
14530b57cec5SDimitry Andric       ExplicitKeyword,
14540b57cec5SDimitry Andric       ExportKeyword,
14550b57cec5SDimitry Andric       ExportAsKeyword,
14560b57cec5SDimitry Andric       ExternKeyword,
14570b57cec5SDimitry Andric       FrameworkKeyword,
14580b57cec5SDimitry Andric       LinkKeyword,
14590b57cec5SDimitry Andric       ModuleKeyword,
14600b57cec5SDimitry Andric       Period,
14610b57cec5SDimitry Andric       PrivateKeyword,
14620b57cec5SDimitry Andric       UmbrellaKeyword,
14630b57cec5SDimitry Andric       UseKeyword,
14640b57cec5SDimitry Andric       RequiresKeyword,
14650b57cec5SDimitry Andric       Star,
14660b57cec5SDimitry Andric       StringLiteral,
14670b57cec5SDimitry Andric       IntegerLiteral,
14680b57cec5SDimitry Andric       TextualKeyword,
14690b57cec5SDimitry Andric       LBrace,
14700b57cec5SDimitry Andric       RBrace,
14710b57cec5SDimitry Andric       LSquare,
14720b57cec5SDimitry Andric       RSquare
14730b57cec5SDimitry Andric     } Kind;
14740b57cec5SDimitry Andric 
1475fe6060f1SDimitry Andric     SourceLocation::UIntTy Location;
14760b57cec5SDimitry Andric     unsigned StringLength;
14770b57cec5SDimitry Andric     union {
14780b57cec5SDimitry Andric       // If Kind != IntegerLiteral.
14790b57cec5SDimitry Andric       const char *StringData;
14800b57cec5SDimitry Andric 
14810b57cec5SDimitry Andric       // If Kind == IntegerLiteral.
14820b57cec5SDimitry Andric       uint64_t IntegerValue;
14830b57cec5SDimitry Andric     };
14840b57cec5SDimitry Andric 
clearclang::MMToken14850b57cec5SDimitry Andric     void clear() {
14860b57cec5SDimitry Andric       Kind = EndOfFile;
14870b57cec5SDimitry Andric       Location = 0;
14880b57cec5SDimitry Andric       StringLength = 0;
14890b57cec5SDimitry Andric       StringData = nullptr;
14900b57cec5SDimitry Andric     }
14910b57cec5SDimitry Andric 
isclang::MMToken14920b57cec5SDimitry Andric     bool is(TokenKind K) const { return Kind == K; }
14930b57cec5SDimitry Andric 
getLocationclang::MMToken14940b57cec5SDimitry Andric     SourceLocation getLocation() const {
14950b57cec5SDimitry Andric       return SourceLocation::getFromRawEncoding(Location);
14960b57cec5SDimitry Andric     }
14970b57cec5SDimitry Andric 
getIntegerclang::MMToken14980b57cec5SDimitry Andric     uint64_t getInteger() const {
14990b57cec5SDimitry Andric       return Kind == IntegerLiteral ? IntegerValue : 0;
15000b57cec5SDimitry Andric     }
15010b57cec5SDimitry Andric 
getStringclang::MMToken15020b57cec5SDimitry Andric     StringRef getString() const {
15030b57cec5SDimitry Andric       return Kind == IntegerLiteral ? StringRef()
15040b57cec5SDimitry Andric                                     : StringRef(StringData, StringLength);
15050b57cec5SDimitry Andric     }
15060b57cec5SDimitry Andric   };
15070b57cec5SDimitry Andric 
15080b57cec5SDimitry Andric   class ModuleMapParser {
15090b57cec5SDimitry Andric     Lexer &L;
15100b57cec5SDimitry Andric     SourceManager &SourceMgr;
15110b57cec5SDimitry Andric 
15120b57cec5SDimitry Andric     /// Default target information, used only for string literal
15130b57cec5SDimitry Andric     /// parsing.
15140b57cec5SDimitry Andric     const TargetInfo *Target;
15150b57cec5SDimitry Andric 
15160b57cec5SDimitry Andric     DiagnosticsEngine &Diags;
15170b57cec5SDimitry Andric     ModuleMap &Map;
15180b57cec5SDimitry Andric 
15190b57cec5SDimitry Andric     /// The current module map file.
1520c9157d92SDimitry Andric     FileEntryRef ModuleMapFile;
15210b57cec5SDimitry Andric 
15220b57cec5SDimitry Andric     /// Source location of most recent parsed module declaration
15230b57cec5SDimitry Andric     SourceLocation CurrModuleDeclLoc;
15240b57cec5SDimitry Andric 
15250b57cec5SDimitry Andric     /// The directory that file names in this module map file should
15260b57cec5SDimitry Andric     /// be resolved relative to.
1527fe013be4SDimitry Andric     DirectoryEntryRef Directory;
15280b57cec5SDimitry Andric 
15290b57cec5SDimitry Andric     /// Whether this module map is in a system header directory.
15300b57cec5SDimitry Andric     bool IsSystem;
15310b57cec5SDimitry Andric 
15320b57cec5SDimitry Andric     /// Whether an error occurred.
15330b57cec5SDimitry Andric     bool HadError = false;
15340b57cec5SDimitry Andric 
15350b57cec5SDimitry Andric     /// Stores string data for the various string literals referenced
15360b57cec5SDimitry Andric     /// during parsing.
15370b57cec5SDimitry Andric     llvm::BumpPtrAllocator StringData;
15380b57cec5SDimitry Andric 
15390b57cec5SDimitry Andric     /// The current token.
15400b57cec5SDimitry Andric     MMToken Tok;
15410b57cec5SDimitry Andric 
15420b57cec5SDimitry Andric     /// The active module.
15430b57cec5SDimitry Andric     Module *ActiveModule = nullptr;
15440b57cec5SDimitry Andric 
15450b57cec5SDimitry Andric     /// Whether a module uses the 'requires excluded' hack to mark its
15460b57cec5SDimitry Andric     /// contents as 'textual'.
15470b57cec5SDimitry Andric     ///
15480b57cec5SDimitry Andric     /// On older Darwin SDK versions, 'requires excluded' is used to mark the
15490b57cec5SDimitry Andric     /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
15500b57cec5SDimitry Andric     /// non-modular headers.  For backwards compatibility, we continue to
15510b57cec5SDimitry Andric     /// support this idiom for just these modules, and map the headers to
15520b57cec5SDimitry Andric     /// 'textual' to match the original intent.
15530b57cec5SDimitry Andric     llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
15540b57cec5SDimitry Andric 
15550b57cec5SDimitry Andric     /// Consume the current token and return its location.
15560b57cec5SDimitry Andric     SourceLocation consumeToken();
15570b57cec5SDimitry Andric 
15580b57cec5SDimitry Andric     /// Skip tokens until we reach the a token with the given kind
15590b57cec5SDimitry Andric     /// (or the end of the file).
15600b57cec5SDimitry Andric     void skipUntil(MMToken::TokenKind K);
15610b57cec5SDimitry Andric 
15620b57cec5SDimitry Andric     bool parseModuleId(ModuleId &Id);
15630b57cec5SDimitry Andric     void parseModuleDecl();
15640b57cec5SDimitry Andric     void parseExternModuleDecl();
15650b57cec5SDimitry Andric     void parseRequiresDecl();
15660b57cec5SDimitry Andric     void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
15670b57cec5SDimitry Andric     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
15680b57cec5SDimitry Andric     void parseExportDecl();
15690b57cec5SDimitry Andric     void parseExportAsDecl();
15700b57cec5SDimitry Andric     void parseUseDecl();
15710b57cec5SDimitry Andric     void parseLinkDecl();
15720b57cec5SDimitry Andric     void parseConfigMacros();
15730b57cec5SDimitry Andric     void parseConflict();
15740b57cec5SDimitry Andric     void parseInferredModuleDecl(bool Framework, bool Explicit);
15750b57cec5SDimitry Andric 
15760b57cec5SDimitry Andric     /// Private modules are canonicalized as Foo_Private. Clang provides extra
15770b57cec5SDimitry Andric     /// module map search logic to find the appropriate private module when PCH
15780b57cec5SDimitry Andric     /// is used with implicit module maps. Warn when private modules are written
15790b57cec5SDimitry Andric     /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
15800b57cec5SDimitry Andric     void diagnosePrivateModules(SourceLocation ExplicitLoc,
15810b57cec5SDimitry Andric                                 SourceLocation FrameworkLoc);
15820b57cec5SDimitry Andric 
15830b57cec5SDimitry Andric     using Attributes = ModuleMap::Attributes;
15840b57cec5SDimitry Andric 
15850b57cec5SDimitry Andric     bool parseOptionalAttributes(Attributes &Attrs);
15860b57cec5SDimitry Andric 
15870b57cec5SDimitry Andric   public:
ModuleMapParser(Lexer & L,SourceManager & SourceMgr,const TargetInfo * Target,DiagnosticsEngine & Diags,ModuleMap & Map,FileEntryRef ModuleMapFile,DirectoryEntryRef Directory,bool IsSystem)15880b57cec5SDimitry Andric     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
15890b57cec5SDimitry Andric                              const TargetInfo *Target, DiagnosticsEngine &Diags,
1590c9157d92SDimitry Andric                              ModuleMap &Map, FileEntryRef ModuleMapFile,
1591fe013be4SDimitry Andric                              DirectoryEntryRef Directory, bool IsSystem)
15920b57cec5SDimitry Andric         : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
15930b57cec5SDimitry Andric           ModuleMapFile(ModuleMapFile), Directory(Directory),
15940b57cec5SDimitry Andric           IsSystem(IsSystem) {
15950b57cec5SDimitry Andric       Tok.clear();
15960b57cec5SDimitry Andric       consumeToken();
15970b57cec5SDimitry Andric     }
15980b57cec5SDimitry Andric 
15990b57cec5SDimitry Andric     bool parseModuleMapFile();
16000b57cec5SDimitry Andric 
terminatedByDirective()16010b57cec5SDimitry Andric     bool terminatedByDirective() { return false; }
getLocation()16020b57cec5SDimitry Andric     SourceLocation getLocation() { return Tok.getLocation(); }
16030b57cec5SDimitry Andric   };
16040b57cec5SDimitry Andric 
16050b57cec5SDimitry Andric } // namespace clang
16060b57cec5SDimitry Andric 
consumeToken()16070b57cec5SDimitry Andric SourceLocation ModuleMapParser::consumeToken() {
16080b57cec5SDimitry Andric   SourceLocation Result = Tok.getLocation();
16090b57cec5SDimitry Andric 
16100b57cec5SDimitry Andric retry:
16110b57cec5SDimitry Andric   Tok.clear();
16120b57cec5SDimitry Andric   Token LToken;
16130b57cec5SDimitry Andric   L.LexFromRawLexer(LToken);
16140b57cec5SDimitry Andric   Tok.Location = LToken.getLocation().getRawEncoding();
16150b57cec5SDimitry Andric   switch (LToken.getKind()) {
16160b57cec5SDimitry Andric   case tok::raw_identifier: {
16170b57cec5SDimitry Andric     StringRef RI = LToken.getRawIdentifier();
16180b57cec5SDimitry Andric     Tok.StringData = RI.data();
16190b57cec5SDimitry Andric     Tok.StringLength = RI.size();
16200b57cec5SDimitry Andric     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
16210b57cec5SDimitry Andric                  .Case("config_macros", MMToken::ConfigMacros)
16220b57cec5SDimitry Andric                  .Case("conflict", MMToken::Conflict)
16230b57cec5SDimitry Andric                  .Case("exclude", MMToken::ExcludeKeyword)
16240b57cec5SDimitry Andric                  .Case("explicit", MMToken::ExplicitKeyword)
16250b57cec5SDimitry Andric                  .Case("export", MMToken::ExportKeyword)
16260b57cec5SDimitry Andric                  .Case("export_as", MMToken::ExportAsKeyword)
16270b57cec5SDimitry Andric                  .Case("extern", MMToken::ExternKeyword)
16280b57cec5SDimitry Andric                  .Case("framework", MMToken::FrameworkKeyword)
16290b57cec5SDimitry Andric                  .Case("header", MMToken::HeaderKeyword)
16300b57cec5SDimitry Andric                  .Case("link", MMToken::LinkKeyword)
16310b57cec5SDimitry Andric                  .Case("module", MMToken::ModuleKeyword)
16320b57cec5SDimitry Andric                  .Case("private", MMToken::PrivateKeyword)
16330b57cec5SDimitry Andric                  .Case("requires", MMToken::RequiresKeyword)
16340b57cec5SDimitry Andric                  .Case("textual", MMToken::TextualKeyword)
16350b57cec5SDimitry Andric                  .Case("umbrella", MMToken::UmbrellaKeyword)
16360b57cec5SDimitry Andric                  .Case("use", MMToken::UseKeyword)
16370b57cec5SDimitry Andric                  .Default(MMToken::Identifier);
16380b57cec5SDimitry Andric     break;
16390b57cec5SDimitry Andric   }
16400b57cec5SDimitry Andric 
16410b57cec5SDimitry Andric   case tok::comma:
16420b57cec5SDimitry Andric     Tok.Kind = MMToken::Comma;
16430b57cec5SDimitry Andric     break;
16440b57cec5SDimitry Andric 
16450b57cec5SDimitry Andric   case tok::eof:
16460b57cec5SDimitry Andric     Tok.Kind = MMToken::EndOfFile;
16470b57cec5SDimitry Andric     break;
16480b57cec5SDimitry Andric 
16490b57cec5SDimitry Andric   case tok::l_brace:
16500b57cec5SDimitry Andric     Tok.Kind = MMToken::LBrace;
16510b57cec5SDimitry Andric     break;
16520b57cec5SDimitry Andric 
16530b57cec5SDimitry Andric   case tok::l_square:
16540b57cec5SDimitry Andric     Tok.Kind = MMToken::LSquare;
16550b57cec5SDimitry Andric     break;
16560b57cec5SDimitry Andric 
16570b57cec5SDimitry Andric   case tok::period:
16580b57cec5SDimitry Andric     Tok.Kind = MMToken::Period;
16590b57cec5SDimitry Andric     break;
16600b57cec5SDimitry Andric 
16610b57cec5SDimitry Andric   case tok::r_brace:
16620b57cec5SDimitry Andric     Tok.Kind = MMToken::RBrace;
16630b57cec5SDimitry Andric     break;
16640b57cec5SDimitry Andric 
16650b57cec5SDimitry Andric   case tok::r_square:
16660b57cec5SDimitry Andric     Tok.Kind = MMToken::RSquare;
16670b57cec5SDimitry Andric     break;
16680b57cec5SDimitry Andric 
16690b57cec5SDimitry Andric   case tok::star:
16700b57cec5SDimitry Andric     Tok.Kind = MMToken::Star;
16710b57cec5SDimitry Andric     break;
16720b57cec5SDimitry Andric 
16730b57cec5SDimitry Andric   case tok::exclaim:
16740b57cec5SDimitry Andric     Tok.Kind = MMToken::Exclaim;
16750b57cec5SDimitry Andric     break;
16760b57cec5SDimitry Andric 
16770b57cec5SDimitry Andric   case tok::string_literal: {
16780b57cec5SDimitry Andric     if (LToken.hasUDSuffix()) {
16790b57cec5SDimitry Andric       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
16800b57cec5SDimitry Andric       HadError = true;
16810b57cec5SDimitry Andric       goto retry;
16820b57cec5SDimitry Andric     }
16830b57cec5SDimitry Andric 
16840b57cec5SDimitry Andric     // Parse the string literal.
16850b57cec5SDimitry Andric     LangOptions LangOpts;
16860b57cec5SDimitry Andric     StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
16870b57cec5SDimitry Andric     if (StringLiteral.hadError)
16880b57cec5SDimitry Andric       goto retry;
16890b57cec5SDimitry Andric 
16900b57cec5SDimitry Andric     // Copy the string literal into our string data allocator.
16910b57cec5SDimitry Andric     unsigned Length = StringLiteral.GetStringLength();
16920b57cec5SDimitry Andric     char *Saved = StringData.Allocate<char>(Length + 1);
16930b57cec5SDimitry Andric     memcpy(Saved, StringLiteral.GetString().data(), Length);
16940b57cec5SDimitry Andric     Saved[Length] = 0;
16950b57cec5SDimitry Andric 
16960b57cec5SDimitry Andric     // Form the token.
16970b57cec5SDimitry Andric     Tok.Kind = MMToken::StringLiteral;
16980b57cec5SDimitry Andric     Tok.StringData = Saved;
16990b57cec5SDimitry Andric     Tok.StringLength = Length;
17000b57cec5SDimitry Andric     break;
17010b57cec5SDimitry Andric   }
17020b57cec5SDimitry Andric 
17030b57cec5SDimitry Andric   case tok::numeric_constant: {
17040b57cec5SDimitry Andric     // We don't support any suffixes or other complications.
17050b57cec5SDimitry Andric     SmallString<32> SpellingBuffer;
17060b57cec5SDimitry Andric     SpellingBuffer.resize(LToken.getLength() + 1);
17070b57cec5SDimitry Andric     const char *Start = SpellingBuffer.data();
17080b57cec5SDimitry Andric     unsigned Length =
170981ad6265SDimitry Andric         Lexer::getSpelling(LToken, Start, SourceMgr, Map.LangOpts);
17100b57cec5SDimitry Andric     uint64_t Value;
17110b57cec5SDimitry Andric     if (StringRef(Start, Length).getAsInteger(0, Value)) {
17120b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
17130b57cec5SDimitry Andric       HadError = true;
17140b57cec5SDimitry Andric       goto retry;
17150b57cec5SDimitry Andric     }
17160b57cec5SDimitry Andric 
17170b57cec5SDimitry Andric     Tok.Kind = MMToken::IntegerLiteral;
17180b57cec5SDimitry Andric     Tok.IntegerValue = Value;
17190b57cec5SDimitry Andric     break;
17200b57cec5SDimitry Andric   }
17210b57cec5SDimitry Andric 
17220b57cec5SDimitry Andric   case tok::comment:
17230b57cec5SDimitry Andric     goto retry;
17240b57cec5SDimitry Andric 
17250b57cec5SDimitry Andric   case tok::hash:
17260b57cec5SDimitry Andric     // A module map can be terminated prematurely by
17270b57cec5SDimitry Andric     //   #pragma clang module contents
17280b57cec5SDimitry Andric     // When building the module, we'll treat the rest of the file as the
17290b57cec5SDimitry Andric     // contents of the module.
17300b57cec5SDimitry Andric     {
17310b57cec5SDimitry Andric       auto NextIsIdent = [&](StringRef Str) -> bool {
17320b57cec5SDimitry Andric         L.LexFromRawLexer(LToken);
17330b57cec5SDimitry Andric         return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
17340b57cec5SDimitry Andric                LToken.getRawIdentifier() == Str;
17350b57cec5SDimitry Andric       };
17360b57cec5SDimitry Andric       if (NextIsIdent("pragma") && NextIsIdent("clang") &&
17370b57cec5SDimitry Andric           NextIsIdent("module") && NextIsIdent("contents")) {
17380b57cec5SDimitry Andric         Tok.Kind = MMToken::EndOfFile;
17390b57cec5SDimitry Andric         break;
17400b57cec5SDimitry Andric       }
17410b57cec5SDimitry Andric     }
1742bdd1243dSDimitry Andric     [[fallthrough]];
17430b57cec5SDimitry Andric 
17440b57cec5SDimitry Andric   default:
17450b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
17460b57cec5SDimitry Andric     HadError = true;
17470b57cec5SDimitry Andric     goto retry;
17480b57cec5SDimitry Andric   }
17490b57cec5SDimitry Andric 
17500b57cec5SDimitry Andric   return Result;
17510b57cec5SDimitry Andric }
17520b57cec5SDimitry Andric 
skipUntil(MMToken::TokenKind K)17530b57cec5SDimitry Andric void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
17540b57cec5SDimitry Andric   unsigned braceDepth = 0;
17550b57cec5SDimitry Andric   unsigned squareDepth = 0;
17560b57cec5SDimitry Andric   do {
17570b57cec5SDimitry Andric     switch (Tok.Kind) {
17580b57cec5SDimitry Andric     case MMToken::EndOfFile:
17590b57cec5SDimitry Andric       return;
17600b57cec5SDimitry Andric 
17610b57cec5SDimitry Andric     case MMToken::LBrace:
17620b57cec5SDimitry Andric       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
17630b57cec5SDimitry Andric         return;
17640b57cec5SDimitry Andric 
17650b57cec5SDimitry Andric       ++braceDepth;
17660b57cec5SDimitry Andric       break;
17670b57cec5SDimitry Andric 
17680b57cec5SDimitry Andric     case MMToken::LSquare:
17690b57cec5SDimitry Andric       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
17700b57cec5SDimitry Andric         return;
17710b57cec5SDimitry Andric 
17720b57cec5SDimitry Andric       ++squareDepth;
17730b57cec5SDimitry Andric       break;
17740b57cec5SDimitry Andric 
17750b57cec5SDimitry Andric     case MMToken::RBrace:
17760b57cec5SDimitry Andric       if (braceDepth > 0)
17770b57cec5SDimitry Andric         --braceDepth;
17780b57cec5SDimitry Andric       else if (Tok.is(K))
17790b57cec5SDimitry Andric         return;
17800b57cec5SDimitry Andric       break;
17810b57cec5SDimitry Andric 
17820b57cec5SDimitry Andric     case MMToken::RSquare:
17830b57cec5SDimitry Andric       if (squareDepth > 0)
17840b57cec5SDimitry Andric         --squareDepth;
17850b57cec5SDimitry Andric       else if (Tok.is(K))
17860b57cec5SDimitry Andric         return;
17870b57cec5SDimitry Andric       break;
17880b57cec5SDimitry Andric 
17890b57cec5SDimitry Andric     default:
17900b57cec5SDimitry Andric       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
17910b57cec5SDimitry Andric         return;
17920b57cec5SDimitry Andric       break;
17930b57cec5SDimitry Andric     }
17940b57cec5SDimitry Andric 
17950b57cec5SDimitry Andric    consumeToken();
17960b57cec5SDimitry Andric   } while (true);
17970b57cec5SDimitry Andric }
17980b57cec5SDimitry Andric 
17990b57cec5SDimitry Andric /// Parse a module-id.
18000b57cec5SDimitry Andric ///
18010b57cec5SDimitry Andric ///   module-id:
18020b57cec5SDimitry Andric ///     identifier
18030b57cec5SDimitry Andric ///     identifier '.' module-id
18040b57cec5SDimitry Andric ///
18050b57cec5SDimitry Andric /// \returns true if an error occurred, false otherwise.
parseModuleId(ModuleId & Id)18060b57cec5SDimitry Andric bool ModuleMapParser::parseModuleId(ModuleId &Id) {
18070b57cec5SDimitry Andric   Id.clear();
18080b57cec5SDimitry Andric   do {
18090b57cec5SDimitry Andric     if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
18105ffd83dbSDimitry Andric       Id.push_back(
18115ffd83dbSDimitry Andric           std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
18120b57cec5SDimitry Andric       consumeToken();
18130b57cec5SDimitry Andric     } else {
18140b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
18150b57cec5SDimitry Andric       return true;
18160b57cec5SDimitry Andric     }
18170b57cec5SDimitry Andric 
18180b57cec5SDimitry Andric     if (!Tok.is(MMToken::Period))
18190b57cec5SDimitry Andric       break;
18200b57cec5SDimitry Andric 
18210b57cec5SDimitry Andric     consumeToken();
18220b57cec5SDimitry Andric   } while (true);
18230b57cec5SDimitry Andric 
18240b57cec5SDimitry Andric   return false;
18250b57cec5SDimitry Andric }
18260b57cec5SDimitry Andric 
18270b57cec5SDimitry Andric namespace {
18280b57cec5SDimitry Andric 
18290b57cec5SDimitry Andric   /// Enumerates the known attributes.
18300b57cec5SDimitry Andric   enum AttributeKind {
18310b57cec5SDimitry Andric     /// An unknown attribute.
18320b57cec5SDimitry Andric     AT_unknown,
18330b57cec5SDimitry Andric 
18340b57cec5SDimitry Andric     /// The 'system' attribute.
18350b57cec5SDimitry Andric     AT_system,
18360b57cec5SDimitry Andric 
18370b57cec5SDimitry Andric     /// The 'extern_c' attribute.
18380b57cec5SDimitry Andric     AT_extern_c,
18390b57cec5SDimitry Andric 
18400b57cec5SDimitry Andric     /// The 'exhaustive' attribute.
18410b57cec5SDimitry Andric     AT_exhaustive,
18420b57cec5SDimitry Andric 
18430b57cec5SDimitry Andric     /// The 'no_undeclared_includes' attribute.
18440b57cec5SDimitry Andric     AT_no_undeclared_includes
18450b57cec5SDimitry Andric   };
18460b57cec5SDimitry Andric 
18470b57cec5SDimitry Andric } // namespace
18480b57cec5SDimitry Andric 
18490b57cec5SDimitry Andric /// Private modules are canonicalized as Foo_Private. Clang provides extra
18500b57cec5SDimitry Andric /// module map search logic to find the appropriate private module when PCH
18510b57cec5SDimitry Andric /// is used with implicit module maps. Warn when private modules are written
18520b57cec5SDimitry Andric /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
diagnosePrivateModules(SourceLocation ExplicitLoc,SourceLocation FrameworkLoc)18530b57cec5SDimitry Andric void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
18540b57cec5SDimitry Andric                                              SourceLocation FrameworkLoc) {
18550b57cec5SDimitry Andric   auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
18560b57cec5SDimitry Andric                              const Module *M, SourceRange ReplLoc) {
18570b57cec5SDimitry Andric     auto D = Diags.Report(ActiveModule->DefinitionLoc,
18580b57cec5SDimitry Andric                           diag::note_mmap_rename_top_level_private_module);
18590b57cec5SDimitry Andric     D << BadName << M->Name;
18600b57cec5SDimitry Andric     D << FixItHint::CreateReplacement(ReplLoc, Canonical);
18610b57cec5SDimitry Andric   };
18620b57cec5SDimitry Andric 
18630b57cec5SDimitry Andric   for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
18640b57cec5SDimitry Andric     auto const *M = E->getValue();
18650b57cec5SDimitry Andric     if (M->Directory != ActiveModule->Directory)
18660b57cec5SDimitry Andric       continue;
18670b57cec5SDimitry Andric 
18680b57cec5SDimitry Andric     SmallString<128> FullName(ActiveModule->getFullModuleName());
1869c9157d92SDimitry Andric     if (!FullName.starts_with(M->Name) && !FullName.ends_with("Private"))
18700b57cec5SDimitry Andric       continue;
18710b57cec5SDimitry Andric     SmallString<128> FixedPrivModDecl;
18720b57cec5SDimitry Andric     SmallString<128> Canonical(M->Name);
18730b57cec5SDimitry Andric     Canonical.append("_Private");
18740b57cec5SDimitry Andric 
18750b57cec5SDimitry Andric     // Foo.Private -> Foo_Private
18760b57cec5SDimitry Andric     if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
18770b57cec5SDimitry Andric         M->Name == ActiveModule->Parent->Name) {
18780b57cec5SDimitry Andric       Diags.Report(ActiveModule->DefinitionLoc,
18790b57cec5SDimitry Andric                    diag::warn_mmap_mismatched_private_submodule)
18800b57cec5SDimitry Andric           << FullName;
18810b57cec5SDimitry Andric 
18820b57cec5SDimitry Andric       SourceLocation FixItInitBegin = CurrModuleDeclLoc;
18830b57cec5SDimitry Andric       if (FrameworkLoc.isValid())
18840b57cec5SDimitry Andric         FixItInitBegin = FrameworkLoc;
18850b57cec5SDimitry Andric       if (ExplicitLoc.isValid())
18860b57cec5SDimitry Andric         FixItInitBegin = ExplicitLoc;
18870b57cec5SDimitry Andric 
18880b57cec5SDimitry Andric       if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
18890b57cec5SDimitry Andric         FixedPrivModDecl.append("framework ");
18900b57cec5SDimitry Andric       FixedPrivModDecl.append("module ");
18910b57cec5SDimitry Andric       FixedPrivModDecl.append(Canonical);
18920b57cec5SDimitry Andric 
18930b57cec5SDimitry Andric       GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
18940b57cec5SDimitry Andric                       SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
18950b57cec5SDimitry Andric       continue;
18960b57cec5SDimitry Andric     }
18970b57cec5SDimitry Andric 
18980b57cec5SDimitry Andric     // FooPrivate and whatnots -> Foo_Private
18990b57cec5SDimitry Andric     if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
19000b57cec5SDimitry Andric         ActiveModule->Name != Canonical) {
19010b57cec5SDimitry Andric       Diags.Report(ActiveModule->DefinitionLoc,
19020b57cec5SDimitry Andric                    diag::warn_mmap_mismatched_private_module_name)
19030b57cec5SDimitry Andric           << ActiveModule->Name;
19040b57cec5SDimitry Andric       GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
19050b57cec5SDimitry Andric                       SourceRange(ActiveModule->DefinitionLoc));
19060b57cec5SDimitry Andric     }
19070b57cec5SDimitry Andric   }
19080b57cec5SDimitry Andric }
19090b57cec5SDimitry Andric 
19100b57cec5SDimitry Andric /// Parse a module declaration.
19110b57cec5SDimitry Andric ///
19120b57cec5SDimitry Andric ///   module-declaration:
19130b57cec5SDimitry Andric ///     'extern' 'module' module-id string-literal
19140b57cec5SDimitry Andric ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
19150b57cec5SDimitry Andric ///       { module-member* }
19160b57cec5SDimitry Andric ///
19170b57cec5SDimitry Andric ///   module-member:
19180b57cec5SDimitry Andric ///     requires-declaration
19190b57cec5SDimitry Andric ///     header-declaration
19200b57cec5SDimitry Andric ///     submodule-declaration
19210b57cec5SDimitry Andric ///     export-declaration
19220b57cec5SDimitry Andric ///     export-as-declaration
19230b57cec5SDimitry Andric ///     link-declaration
19240b57cec5SDimitry Andric ///
19250b57cec5SDimitry Andric ///   submodule-declaration:
19260b57cec5SDimitry Andric ///     module-declaration
19270b57cec5SDimitry Andric ///     inferred-submodule-declaration
parseModuleDecl()19280b57cec5SDimitry Andric void ModuleMapParser::parseModuleDecl() {
19290b57cec5SDimitry Andric   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
19300b57cec5SDimitry Andric          Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
19310b57cec5SDimitry Andric   if (Tok.is(MMToken::ExternKeyword)) {
19320b57cec5SDimitry Andric     parseExternModuleDecl();
19330b57cec5SDimitry Andric     return;
19340b57cec5SDimitry Andric   }
19350b57cec5SDimitry Andric 
19360b57cec5SDimitry Andric   // Parse 'explicit' or 'framework' keyword, if present.
19370b57cec5SDimitry Andric   SourceLocation ExplicitLoc;
19380b57cec5SDimitry Andric   SourceLocation FrameworkLoc;
19390b57cec5SDimitry Andric   bool Explicit = false;
19400b57cec5SDimitry Andric   bool Framework = false;
19410b57cec5SDimitry Andric 
19420b57cec5SDimitry Andric   // Parse 'explicit' keyword, if present.
19430b57cec5SDimitry Andric   if (Tok.is(MMToken::ExplicitKeyword)) {
19440b57cec5SDimitry Andric     ExplicitLoc = consumeToken();
19450b57cec5SDimitry Andric     Explicit = true;
19460b57cec5SDimitry Andric   }
19470b57cec5SDimitry Andric 
19480b57cec5SDimitry Andric   // Parse 'framework' keyword, if present.
19490b57cec5SDimitry Andric   if (Tok.is(MMToken::FrameworkKeyword)) {
19500b57cec5SDimitry Andric     FrameworkLoc = consumeToken();
19510b57cec5SDimitry Andric     Framework = true;
19520b57cec5SDimitry Andric   }
19530b57cec5SDimitry Andric 
19540b57cec5SDimitry Andric   // Parse 'module' keyword.
19550b57cec5SDimitry Andric   if (!Tok.is(MMToken::ModuleKeyword)) {
19560b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
19570b57cec5SDimitry Andric     consumeToken();
19580b57cec5SDimitry Andric     HadError = true;
19590b57cec5SDimitry Andric     return;
19600b57cec5SDimitry Andric   }
19610b57cec5SDimitry Andric   CurrModuleDeclLoc = consumeToken(); // 'module' keyword
19620b57cec5SDimitry Andric 
19630b57cec5SDimitry Andric   // If we have a wildcard for the module name, this is an inferred submodule.
19640b57cec5SDimitry Andric   // Parse it.
19650b57cec5SDimitry Andric   if (Tok.is(MMToken::Star))
19660b57cec5SDimitry Andric     return parseInferredModuleDecl(Framework, Explicit);
19670b57cec5SDimitry Andric 
19680b57cec5SDimitry Andric   // Parse the module name.
19690b57cec5SDimitry Andric   ModuleId Id;
19700b57cec5SDimitry Andric   if (parseModuleId(Id)) {
19710b57cec5SDimitry Andric     HadError = true;
19720b57cec5SDimitry Andric     return;
19730b57cec5SDimitry Andric   }
19740b57cec5SDimitry Andric 
19750b57cec5SDimitry Andric   if (ActiveModule) {
19760b57cec5SDimitry Andric     if (Id.size() > 1) {
19770b57cec5SDimitry Andric       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
19780b57cec5SDimitry Andric         << SourceRange(Id.front().second, Id.back().second);
19790b57cec5SDimitry Andric 
19800b57cec5SDimitry Andric       HadError = true;
19810b57cec5SDimitry Andric       return;
19820b57cec5SDimitry Andric     }
19830b57cec5SDimitry Andric   } else if (Id.size() == 1 && Explicit) {
19840b57cec5SDimitry Andric     // Top-level modules can't be explicit.
19850b57cec5SDimitry Andric     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
19860b57cec5SDimitry Andric     Explicit = false;
19870b57cec5SDimitry Andric     ExplicitLoc = SourceLocation();
19880b57cec5SDimitry Andric     HadError = true;
19890b57cec5SDimitry Andric   }
19900b57cec5SDimitry Andric 
19910b57cec5SDimitry Andric   Module *PreviousActiveModule = ActiveModule;
19920b57cec5SDimitry Andric   if (Id.size() > 1) {
19930b57cec5SDimitry Andric     // This module map defines a submodule. Go find the module of which it
19940b57cec5SDimitry Andric     // is a submodule.
19950b57cec5SDimitry Andric     ActiveModule = nullptr;
19960b57cec5SDimitry Andric     const Module *TopLevelModule = nullptr;
19970b57cec5SDimitry Andric     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
19980b57cec5SDimitry Andric       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
19990b57cec5SDimitry Andric         if (I == 0)
20000b57cec5SDimitry Andric           TopLevelModule = Next;
20010b57cec5SDimitry Andric         ActiveModule = Next;
20020b57cec5SDimitry Andric         continue;
20030b57cec5SDimitry Andric       }
20040b57cec5SDimitry Andric 
2005e8d8bef9SDimitry Andric       Diags.Report(Id[I].second, diag::err_mmap_missing_parent_module)
2006e8d8bef9SDimitry Andric           << Id[I].first << (ActiveModule != nullptr)
2007e8d8bef9SDimitry Andric           << (ActiveModule
2008e8d8bef9SDimitry Andric                   ? ActiveModule->getTopLevelModule()->getFullModuleName()
2009e8d8bef9SDimitry Andric                   : "");
20100b57cec5SDimitry Andric       HadError = true;
20110b57cec5SDimitry Andric     }
20120b57cec5SDimitry Andric 
2013e8d8bef9SDimitry Andric     if (TopLevelModule &&
2014e8d8bef9SDimitry Andric         ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
20150b57cec5SDimitry Andric       assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
20160b57cec5SDimitry Andric              "submodule defined in same file as 'module *' that allowed its "
20170b57cec5SDimitry Andric              "top-level module");
20180b57cec5SDimitry Andric       Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
20190b57cec5SDimitry Andric     }
20200b57cec5SDimitry Andric   }
20210b57cec5SDimitry Andric 
20220b57cec5SDimitry Andric   StringRef ModuleName = Id.back().first;
20230b57cec5SDimitry Andric   SourceLocation ModuleNameLoc = Id.back().second;
20240b57cec5SDimitry Andric 
20250b57cec5SDimitry Andric   // Parse the optional attribute list.
20260b57cec5SDimitry Andric   Attributes Attrs;
20270b57cec5SDimitry Andric   if (parseOptionalAttributes(Attrs))
20280b57cec5SDimitry Andric     return;
20290b57cec5SDimitry Andric 
20300b57cec5SDimitry Andric   // Parse the opening brace.
20310b57cec5SDimitry Andric   if (!Tok.is(MMToken::LBrace)) {
20320b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
20330b57cec5SDimitry Andric       << ModuleName;
20340b57cec5SDimitry Andric     HadError = true;
20350b57cec5SDimitry Andric     return;
20360b57cec5SDimitry Andric   }
20370b57cec5SDimitry Andric   SourceLocation LBraceLoc = consumeToken();
20380b57cec5SDimitry Andric 
20390b57cec5SDimitry Andric   // Determine whether this (sub)module has already been defined.
20400b57cec5SDimitry Andric   Module *ShadowingModule = nullptr;
20410b57cec5SDimitry Andric   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
20420b57cec5SDimitry Andric     // We might see a (re)definition of a module that we already have a
2043fe013be4SDimitry Andric     // definition for in four cases:
20440b57cec5SDimitry Andric     //  - If we loaded one definition from an AST file and we've just found a
20450b57cec5SDimitry Andric     //    corresponding definition in a module map file, or
2046fe013be4SDimitry Andric     bool LoadedFromASTFile = Existing->IsFromModuleFile;
2047fe013be4SDimitry Andric     //  - If we previously inferred this module from different module map file.
2048fe013be4SDimitry Andric     bool Inferred = Existing->IsInferred;
2049fe013be4SDimitry Andric     //  - If we're building a framework that vends a module map, we might've
2050fe013be4SDimitry Andric     //    previously seen the one in intermediate products and now the system
2051fe013be4SDimitry Andric     //    one.
2052fe013be4SDimitry Andric     // FIXME: If we're parsing module map file that looks like this:
2053fe013be4SDimitry Andric     //          framework module FW { ... }
2054fe013be4SDimitry Andric     //          module FW.Sub { ... }
2055fe013be4SDimitry Andric     //        We can't check the framework qualifier, since it's not attached to
2056fe013be4SDimitry Andric     //        the definition of Sub. Checking that qualifier on \c Existing is
2057fe013be4SDimitry Andric     //        not correct either, since we might've previously seen:
2058fe013be4SDimitry Andric     //          module FW { ... }
2059fe013be4SDimitry Andric     //          module FW.Sub { ... }
2060fe013be4SDimitry Andric     //        We should enforce consistency of redefinitions so that we can rely
2061fe013be4SDimitry Andric     //        that \c Existing is part of a framework iff the redefinition of FW
2062fe013be4SDimitry Andric     //        we have just skipped had it too. Once we do that, stop checking
2063fe013be4SDimitry Andric     //        the local framework qualifier and only rely on \c Existing.
2064fe013be4SDimitry Andric     bool PartOfFramework = Framework || Existing->isPartOfFramework();
20650b57cec5SDimitry Andric     //  - If we're building a (preprocessed) module and we've just loaded the
20660b57cec5SDimitry Andric     //    module map file from which it was created.
20670b57cec5SDimitry Andric     bool ParsedAsMainInput =
20680b57cec5SDimitry Andric         Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
20690b57cec5SDimitry Andric         Map.LangOpts.CurrentModule == ModuleName &&
20700b57cec5SDimitry Andric         SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
20710b57cec5SDimitry Andric             SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
2072fe013be4SDimitry Andric     if (LoadedFromASTFile || Inferred || PartOfFramework || ParsedAsMainInput) {
2073fe013be4SDimitry Andric       ActiveModule = PreviousActiveModule;
20740b57cec5SDimitry Andric       // Skip the module definition.
20750b57cec5SDimitry Andric       skipUntil(MMToken::RBrace);
20760b57cec5SDimitry Andric       if (Tok.is(MMToken::RBrace))
20770b57cec5SDimitry Andric         consumeToken();
20780b57cec5SDimitry Andric       else {
20790b57cec5SDimitry Andric         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
20800b57cec5SDimitry Andric         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
20810b57cec5SDimitry Andric         HadError = true;
20820b57cec5SDimitry Andric       }
20830b57cec5SDimitry Andric       return;
20840b57cec5SDimitry Andric     }
20850b57cec5SDimitry Andric 
20860b57cec5SDimitry Andric     if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
20870b57cec5SDimitry Andric       ShadowingModule = Existing;
20880b57cec5SDimitry Andric     } else {
20890b57cec5SDimitry Andric       // This is not a shawdowed module decl, it is an illegal redefinition.
20900b57cec5SDimitry Andric       Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
20910b57cec5SDimitry Andric           << ModuleName;
20920b57cec5SDimitry Andric       Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
20930b57cec5SDimitry Andric 
20940b57cec5SDimitry Andric       // Skip the module definition.
20950b57cec5SDimitry Andric       skipUntil(MMToken::RBrace);
20960b57cec5SDimitry Andric       if (Tok.is(MMToken::RBrace))
20970b57cec5SDimitry Andric         consumeToken();
20980b57cec5SDimitry Andric 
20990b57cec5SDimitry Andric       HadError = true;
21000b57cec5SDimitry Andric       return;
21010b57cec5SDimitry Andric     }
21020b57cec5SDimitry Andric   }
21030b57cec5SDimitry Andric 
21040b57cec5SDimitry Andric   // Start defining this module.
21050b57cec5SDimitry Andric   if (ShadowingModule) {
21060b57cec5SDimitry Andric     ActiveModule =
21070b57cec5SDimitry Andric         Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
21080b57cec5SDimitry Andric   } else {
21090b57cec5SDimitry Andric     ActiveModule =
21100b57cec5SDimitry Andric         Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
21110b57cec5SDimitry Andric             .first;
21120b57cec5SDimitry Andric   }
21130b57cec5SDimitry Andric 
21140b57cec5SDimitry Andric   ActiveModule->DefinitionLoc = ModuleNameLoc;
21150b57cec5SDimitry Andric   if (Attrs.IsSystem || IsSystem)
21160b57cec5SDimitry Andric     ActiveModule->IsSystem = true;
21170b57cec5SDimitry Andric   if (Attrs.IsExternC)
21180b57cec5SDimitry Andric     ActiveModule->IsExternC = true;
2119bdd1243dSDimitry Andric   if (Attrs.NoUndeclaredIncludes)
21200b57cec5SDimitry Andric     ActiveModule->NoUndeclaredIncludes = true;
21210b57cec5SDimitry Andric   ActiveModule->Directory = Directory;
21220b57cec5SDimitry Andric 
2123c9157d92SDimitry Andric   StringRef MapFileName(ModuleMapFile.getName());
2124c9157d92SDimitry Andric   if (MapFileName.ends_with("module.private.modulemap") ||
2125c9157d92SDimitry Andric       MapFileName.ends_with("module_private.map")) {
21260b57cec5SDimitry Andric     ActiveModule->ModuleMapIsPrivate = true;
21270b57cec5SDimitry Andric   }
21280b57cec5SDimitry Andric 
21290b57cec5SDimitry Andric   // Private modules named as FooPrivate, Foo.Private or similar are likely a
21300b57cec5SDimitry Andric   // user error; provide warnings, notes and fixits to direct users to use
21310b57cec5SDimitry Andric   // Foo_Private instead.
21320b57cec5SDimitry Andric   SourceLocation StartLoc =
21330b57cec5SDimitry Andric       SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
21340b57cec5SDimitry Andric   if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
21350b57cec5SDimitry Andric       !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
21360b57cec5SDimitry Andric                        StartLoc) &&
21370b57cec5SDimitry Andric       !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
21380b57cec5SDimitry Andric                        StartLoc) &&
21390b57cec5SDimitry Andric       ActiveModule->ModuleMapIsPrivate)
21400b57cec5SDimitry Andric     diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
21410b57cec5SDimitry Andric 
21420b57cec5SDimitry Andric   bool Done = false;
21430b57cec5SDimitry Andric   do {
21440b57cec5SDimitry Andric     switch (Tok.Kind) {
21450b57cec5SDimitry Andric     case MMToken::EndOfFile:
21460b57cec5SDimitry Andric     case MMToken::RBrace:
21470b57cec5SDimitry Andric       Done = true;
21480b57cec5SDimitry Andric       break;
21490b57cec5SDimitry Andric 
21500b57cec5SDimitry Andric     case MMToken::ConfigMacros:
21510b57cec5SDimitry Andric       parseConfigMacros();
21520b57cec5SDimitry Andric       break;
21530b57cec5SDimitry Andric 
21540b57cec5SDimitry Andric     case MMToken::Conflict:
21550b57cec5SDimitry Andric       parseConflict();
21560b57cec5SDimitry Andric       break;
21570b57cec5SDimitry Andric 
21580b57cec5SDimitry Andric     case MMToken::ExplicitKeyword:
21590b57cec5SDimitry Andric     case MMToken::ExternKeyword:
21600b57cec5SDimitry Andric     case MMToken::FrameworkKeyword:
21610b57cec5SDimitry Andric     case MMToken::ModuleKeyword:
21620b57cec5SDimitry Andric       parseModuleDecl();
21630b57cec5SDimitry Andric       break;
21640b57cec5SDimitry Andric 
21650b57cec5SDimitry Andric     case MMToken::ExportKeyword:
21660b57cec5SDimitry Andric       parseExportDecl();
21670b57cec5SDimitry Andric       break;
21680b57cec5SDimitry Andric 
21690b57cec5SDimitry Andric     case MMToken::ExportAsKeyword:
21700b57cec5SDimitry Andric       parseExportAsDecl();
21710b57cec5SDimitry Andric       break;
21720b57cec5SDimitry Andric 
21730b57cec5SDimitry Andric     case MMToken::UseKeyword:
21740b57cec5SDimitry Andric       parseUseDecl();
21750b57cec5SDimitry Andric       break;
21760b57cec5SDimitry Andric 
21770b57cec5SDimitry Andric     case MMToken::RequiresKeyword:
21780b57cec5SDimitry Andric       parseRequiresDecl();
21790b57cec5SDimitry Andric       break;
21800b57cec5SDimitry Andric 
21810b57cec5SDimitry Andric     case MMToken::TextualKeyword:
21820b57cec5SDimitry Andric       parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
21830b57cec5SDimitry Andric       break;
21840b57cec5SDimitry Andric 
21850b57cec5SDimitry Andric     case MMToken::UmbrellaKeyword: {
21860b57cec5SDimitry Andric       SourceLocation UmbrellaLoc = consumeToken();
21870b57cec5SDimitry Andric       if (Tok.is(MMToken::HeaderKeyword))
21880b57cec5SDimitry Andric         parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
21890b57cec5SDimitry Andric       else
21900b57cec5SDimitry Andric         parseUmbrellaDirDecl(UmbrellaLoc);
21910b57cec5SDimitry Andric       break;
21920b57cec5SDimitry Andric     }
21930b57cec5SDimitry Andric 
21940b57cec5SDimitry Andric     case MMToken::ExcludeKeyword:
21950b57cec5SDimitry Andric       parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
21960b57cec5SDimitry Andric       break;
21970b57cec5SDimitry Andric 
21980b57cec5SDimitry Andric     case MMToken::PrivateKeyword:
21990b57cec5SDimitry Andric       parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
22000b57cec5SDimitry Andric       break;
22010b57cec5SDimitry Andric 
22020b57cec5SDimitry Andric     case MMToken::HeaderKeyword:
22030b57cec5SDimitry Andric       parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
22040b57cec5SDimitry Andric       break;
22050b57cec5SDimitry Andric 
22060b57cec5SDimitry Andric     case MMToken::LinkKeyword:
22070b57cec5SDimitry Andric       parseLinkDecl();
22080b57cec5SDimitry Andric       break;
22090b57cec5SDimitry Andric 
22100b57cec5SDimitry Andric     default:
22110b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
22120b57cec5SDimitry Andric       consumeToken();
22130b57cec5SDimitry Andric       break;
22140b57cec5SDimitry Andric     }
22150b57cec5SDimitry Andric   } while (!Done);
22160b57cec5SDimitry Andric 
22170b57cec5SDimitry Andric   if (Tok.is(MMToken::RBrace))
22180b57cec5SDimitry Andric     consumeToken();
22190b57cec5SDimitry Andric   else {
22200b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
22210b57cec5SDimitry Andric     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
22220b57cec5SDimitry Andric     HadError = true;
22230b57cec5SDimitry Andric   }
22240b57cec5SDimitry Andric 
22250b57cec5SDimitry Andric   // If the active module is a top-level framework, and there are no link
22260b57cec5SDimitry Andric   // libraries, automatically link against the framework.
22270b57cec5SDimitry Andric   if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
2228fe013be4SDimitry Andric       ActiveModule->LinkLibraries.empty())
2229fe013be4SDimitry Andric     inferFrameworkLink(ActiveModule);
22300b57cec5SDimitry Andric 
22310b57cec5SDimitry Andric   // If the module meets all requirements but is still unavailable, mark the
22320b57cec5SDimitry Andric   // whole tree as unavailable to prevent it from building.
22335ffd83dbSDimitry Andric   if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
22340b57cec5SDimitry Andric       ActiveModule->Parent) {
22355ffd83dbSDimitry Andric     ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false);
22360b57cec5SDimitry Andric     ActiveModule->getTopLevelModule()->MissingHeaders.append(
22370b57cec5SDimitry Andric       ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
22380b57cec5SDimitry Andric   }
22390b57cec5SDimitry Andric 
22400b57cec5SDimitry Andric   // We're done parsing this module. Pop back to the previous module.
22410b57cec5SDimitry Andric   ActiveModule = PreviousActiveModule;
22420b57cec5SDimitry Andric }
22430b57cec5SDimitry Andric 
22440b57cec5SDimitry Andric /// Parse an extern module declaration.
22450b57cec5SDimitry Andric ///
22460b57cec5SDimitry Andric ///   extern module-declaration:
22470b57cec5SDimitry Andric ///     'extern' 'module' module-id string-literal
parseExternModuleDecl()22480b57cec5SDimitry Andric void ModuleMapParser::parseExternModuleDecl() {
22490b57cec5SDimitry Andric   assert(Tok.is(MMToken::ExternKeyword));
22500b57cec5SDimitry Andric   SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
22510b57cec5SDimitry Andric 
22520b57cec5SDimitry Andric   // Parse 'module' keyword.
22530b57cec5SDimitry Andric   if (!Tok.is(MMToken::ModuleKeyword)) {
22540b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
22550b57cec5SDimitry Andric     consumeToken();
22560b57cec5SDimitry Andric     HadError = true;
22570b57cec5SDimitry Andric     return;
22580b57cec5SDimitry Andric   }
22590b57cec5SDimitry Andric   consumeToken(); // 'module' keyword
22600b57cec5SDimitry Andric 
22610b57cec5SDimitry Andric   // Parse the module name.
22620b57cec5SDimitry Andric   ModuleId Id;
22630b57cec5SDimitry Andric   if (parseModuleId(Id)) {
22640b57cec5SDimitry Andric     HadError = true;
22650b57cec5SDimitry Andric     return;
22660b57cec5SDimitry Andric   }
22670b57cec5SDimitry Andric 
22680b57cec5SDimitry Andric   // Parse the referenced module map file name.
22690b57cec5SDimitry Andric   if (!Tok.is(MMToken::StringLiteral)) {
22700b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
22710b57cec5SDimitry Andric     HadError = true;
22720b57cec5SDimitry Andric     return;
22730b57cec5SDimitry Andric   }
22745ffd83dbSDimitry Andric   std::string FileName = std::string(Tok.getString());
22750b57cec5SDimitry Andric   consumeToken(); // filename
22760b57cec5SDimitry Andric 
22770b57cec5SDimitry Andric   StringRef FileNameRef = FileName;
22780b57cec5SDimitry Andric   SmallString<128> ModuleMapFileName;
22790b57cec5SDimitry Andric   if (llvm::sys::path::is_relative(FileNameRef)) {
2280fe013be4SDimitry Andric     ModuleMapFileName += Directory.getName();
22810b57cec5SDimitry Andric     llvm::sys::path::append(ModuleMapFileName, FileName);
22820b57cec5SDimitry Andric     FileNameRef = ModuleMapFileName;
22830b57cec5SDimitry Andric   }
2284fe013be4SDimitry Andric   if (auto File = SourceMgr.getFileManager().getOptionalFileRef(FileNameRef))
22850b57cec5SDimitry Andric     Map.parseModuleMapFile(
2286349cc55cSDimitry Andric         *File, IsSystem,
22870b57cec5SDimitry Andric         Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
22880b57cec5SDimitry Andric             ? Directory
2289fe013be4SDimitry Andric             : File->getDir(),
22900b57cec5SDimitry Andric         FileID(), nullptr, ExternLoc);
22910b57cec5SDimitry Andric }
22920b57cec5SDimitry Andric 
22930b57cec5SDimitry Andric /// Whether to add the requirement \p Feature to the module \p M.
22940b57cec5SDimitry Andric ///
22950b57cec5SDimitry Andric /// This preserves backwards compatibility for two hacks in the Darwin system
22960b57cec5SDimitry Andric /// module map files:
22970b57cec5SDimitry Andric ///
22980b57cec5SDimitry Andric /// 1. The use of 'requires excluded' to make headers non-modular, which
22990b57cec5SDimitry Andric ///    should really be mapped to 'textual' now that we have this feature.  We
23000b57cec5SDimitry Andric ///    drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
23010b57cec5SDimitry Andric ///    true.  Later, this bit will be used to map all the headers inside this
23020b57cec5SDimitry Andric ///    module to 'textual'.
23030b57cec5SDimitry Andric ///
23040b57cec5SDimitry Andric ///    This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
23050b57cec5SDimitry Andric ///
23060b57cec5SDimitry Andric /// 2. Removes a bogus cplusplus requirement from IOKit.avc.  This requirement
23070b57cec5SDimitry Andric ///    was never correct and causes issues now that we check it, so drop it.
shouldAddRequirement(Module * M,StringRef Feature,bool & IsRequiresExcludedHack)23080b57cec5SDimitry Andric static bool shouldAddRequirement(Module *M, StringRef Feature,
23090b57cec5SDimitry Andric                                  bool &IsRequiresExcludedHack) {
23100b57cec5SDimitry Andric   if (Feature == "excluded" &&
23110b57cec5SDimitry Andric       (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
23120b57cec5SDimitry Andric        M->fullModuleNameIs({"Tcl", "Private"}))) {
23130b57cec5SDimitry Andric     IsRequiresExcludedHack = true;
23140b57cec5SDimitry Andric     return false;
23150b57cec5SDimitry Andric   } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
23160b57cec5SDimitry Andric     return false;
23170b57cec5SDimitry Andric   }
23180b57cec5SDimitry Andric 
23190b57cec5SDimitry Andric   return true;
23200b57cec5SDimitry Andric }
23210b57cec5SDimitry Andric 
23220b57cec5SDimitry Andric /// Parse a requires declaration.
23230b57cec5SDimitry Andric ///
23240b57cec5SDimitry Andric ///   requires-declaration:
23250b57cec5SDimitry Andric ///     'requires' feature-list
23260b57cec5SDimitry Andric ///
23270b57cec5SDimitry Andric ///   feature-list:
23280b57cec5SDimitry Andric ///     feature ',' feature-list
23290b57cec5SDimitry Andric ///     feature
23300b57cec5SDimitry Andric ///
23310b57cec5SDimitry Andric ///   feature:
23320b57cec5SDimitry Andric ///     '!'[opt] identifier
parseRequiresDecl()23330b57cec5SDimitry Andric void ModuleMapParser::parseRequiresDecl() {
23340b57cec5SDimitry Andric   assert(Tok.is(MMToken::RequiresKeyword));
23350b57cec5SDimitry Andric 
23360b57cec5SDimitry Andric   // Parse 'requires' keyword.
23370b57cec5SDimitry Andric   consumeToken();
23380b57cec5SDimitry Andric 
23390b57cec5SDimitry Andric   // Parse the feature-list.
23400b57cec5SDimitry Andric   do {
23410b57cec5SDimitry Andric     bool RequiredState = true;
23420b57cec5SDimitry Andric     if (Tok.is(MMToken::Exclaim)) {
23430b57cec5SDimitry Andric       RequiredState = false;
23440b57cec5SDimitry Andric       consumeToken();
23450b57cec5SDimitry Andric     }
23460b57cec5SDimitry Andric 
23470b57cec5SDimitry Andric     if (!Tok.is(MMToken::Identifier)) {
23480b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
23490b57cec5SDimitry Andric       HadError = true;
23500b57cec5SDimitry Andric       return;
23510b57cec5SDimitry Andric     }
23520b57cec5SDimitry Andric 
23530b57cec5SDimitry Andric     // Consume the feature name.
23545ffd83dbSDimitry Andric     std::string Feature = std::string(Tok.getString());
23550b57cec5SDimitry Andric     consumeToken();
23560b57cec5SDimitry Andric 
23570b57cec5SDimitry Andric     bool IsRequiresExcludedHack = false;
23580b57cec5SDimitry Andric     bool ShouldAddRequirement =
23590b57cec5SDimitry Andric         shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
23600b57cec5SDimitry Andric 
23610b57cec5SDimitry Andric     if (IsRequiresExcludedHack)
23620b57cec5SDimitry Andric       UsesRequiresExcludedHack.insert(ActiveModule);
23630b57cec5SDimitry Andric 
23640b57cec5SDimitry Andric     if (ShouldAddRequirement) {
23650b57cec5SDimitry Andric       // Add this feature.
23660b57cec5SDimitry Andric       ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
23670b57cec5SDimitry Andric                                    *Map.Target);
23680b57cec5SDimitry Andric     }
23690b57cec5SDimitry Andric 
23700b57cec5SDimitry Andric     if (!Tok.is(MMToken::Comma))
23710b57cec5SDimitry Andric       break;
23720b57cec5SDimitry Andric 
23730b57cec5SDimitry Andric     // Consume the comma.
23740b57cec5SDimitry Andric     consumeToken();
23750b57cec5SDimitry Andric   } while (true);
23760b57cec5SDimitry Andric }
23770b57cec5SDimitry Andric 
23780b57cec5SDimitry Andric /// Parse a header declaration.
23790b57cec5SDimitry Andric ///
23800b57cec5SDimitry Andric ///   header-declaration:
23810b57cec5SDimitry Andric ///     'textual'[opt] 'header' string-literal
23820b57cec5SDimitry Andric ///     'private' 'textual'[opt] 'header' string-literal
23830b57cec5SDimitry Andric ///     'exclude' 'header' string-literal
23840b57cec5SDimitry Andric ///     'umbrella' 'header' string-literal
23850b57cec5SDimitry Andric ///
23860b57cec5SDimitry Andric /// FIXME: Support 'private textual header'.
parseHeaderDecl(MMToken::TokenKind LeadingToken,SourceLocation LeadingLoc)23870b57cec5SDimitry Andric void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
23880b57cec5SDimitry Andric                                       SourceLocation LeadingLoc) {
23890b57cec5SDimitry Andric   // We've already consumed the first token.
23900b57cec5SDimitry Andric   ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
2391bdd1243dSDimitry Andric 
23920b57cec5SDimitry Andric   if (LeadingToken == MMToken::PrivateKeyword) {
23930b57cec5SDimitry Andric     Role = ModuleMap::PrivateHeader;
23940b57cec5SDimitry Andric     // 'private' may optionally be followed by 'textual'.
23950b57cec5SDimitry Andric     if (Tok.is(MMToken::TextualKeyword)) {
23960b57cec5SDimitry Andric       LeadingToken = Tok.Kind;
23970b57cec5SDimitry Andric       consumeToken();
23980b57cec5SDimitry Andric     }
2399bdd1243dSDimitry Andric   } else if (LeadingToken == MMToken::ExcludeKeyword) {
2400bdd1243dSDimitry Andric     Role = ModuleMap::ExcludedHeader;
24010b57cec5SDimitry Andric   }
24020b57cec5SDimitry Andric 
24030b57cec5SDimitry Andric   if (LeadingToken == MMToken::TextualKeyword)
24040b57cec5SDimitry Andric     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
24050b57cec5SDimitry Andric 
24060b57cec5SDimitry Andric   if (UsesRequiresExcludedHack.count(ActiveModule)) {
24070b57cec5SDimitry Andric     // Mark this header 'textual' (see doc comment for
24080b57cec5SDimitry Andric     // Module::UsesRequiresExcludedHack).
24090b57cec5SDimitry Andric     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
24100b57cec5SDimitry Andric   }
24110b57cec5SDimitry Andric 
24120b57cec5SDimitry Andric   if (LeadingToken != MMToken::HeaderKeyword) {
24130b57cec5SDimitry Andric     if (!Tok.is(MMToken::HeaderKeyword)) {
24140b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
24150b57cec5SDimitry Andric           << (LeadingToken == MMToken::PrivateKeyword ? "private" :
24160b57cec5SDimitry Andric               LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
24170b57cec5SDimitry Andric               LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
24180b57cec5SDimitry Andric       return;
24190b57cec5SDimitry Andric     }
24200b57cec5SDimitry Andric     consumeToken();
24210b57cec5SDimitry Andric   }
24220b57cec5SDimitry Andric 
24230b57cec5SDimitry Andric   // Parse the header name.
24240b57cec5SDimitry Andric   if (!Tok.is(MMToken::StringLiteral)) {
24250b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
24260b57cec5SDimitry Andric       << "header";
24270b57cec5SDimitry Andric     HadError = true;
24280b57cec5SDimitry Andric     return;
24290b57cec5SDimitry Andric   }
24300b57cec5SDimitry Andric   Module::UnresolvedHeaderDirective Header;
24315ffd83dbSDimitry Andric   Header.FileName = std::string(Tok.getString());
24320b57cec5SDimitry Andric   Header.FileNameLoc = consumeToken();
24330b57cec5SDimitry Andric   Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
2434bdd1243dSDimitry Andric   Header.Kind = Map.headerRoleToKind(Role);
24350b57cec5SDimitry Andric 
24360b57cec5SDimitry Andric   // Check whether we already have an umbrella.
2437c9157d92SDimitry Andric   if (Header.IsUmbrella &&
2438c9157d92SDimitry Andric       !std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
24390b57cec5SDimitry Andric     Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
24400b57cec5SDimitry Andric       << ActiveModule->getFullModuleName();
24410b57cec5SDimitry Andric     HadError = true;
24420b57cec5SDimitry Andric     return;
24430b57cec5SDimitry Andric   }
24440b57cec5SDimitry Andric 
24450b57cec5SDimitry Andric   // If we were given stat information, parse it so we can skip looking for
24460b57cec5SDimitry Andric   // the file.
24470b57cec5SDimitry Andric   if (Tok.is(MMToken::LBrace)) {
24480b57cec5SDimitry Andric     SourceLocation LBraceLoc = consumeToken();
24490b57cec5SDimitry Andric 
24500b57cec5SDimitry Andric     while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
24510b57cec5SDimitry Andric       enum Attribute { Size, ModTime, Unknown };
24520b57cec5SDimitry Andric       StringRef Str = Tok.getString();
24530b57cec5SDimitry Andric       SourceLocation Loc = consumeToken();
24540b57cec5SDimitry Andric       switch (llvm::StringSwitch<Attribute>(Str)
24550b57cec5SDimitry Andric                   .Case("size", Size)
24560b57cec5SDimitry Andric                   .Case("mtime", ModTime)
24570b57cec5SDimitry Andric                   .Default(Unknown)) {
24580b57cec5SDimitry Andric       case Size:
24590b57cec5SDimitry Andric         if (Header.Size)
24600b57cec5SDimitry Andric           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
24610b57cec5SDimitry Andric         if (!Tok.is(MMToken::IntegerLiteral)) {
24620b57cec5SDimitry Andric           Diags.Report(Tok.getLocation(),
24630b57cec5SDimitry Andric                        diag::err_mmap_invalid_header_attribute_value) << Str;
24640b57cec5SDimitry Andric           skipUntil(MMToken::RBrace);
24650b57cec5SDimitry Andric           break;
24660b57cec5SDimitry Andric         }
24670b57cec5SDimitry Andric         Header.Size = Tok.getInteger();
24680b57cec5SDimitry Andric         consumeToken();
24690b57cec5SDimitry Andric         break;
24700b57cec5SDimitry Andric 
24710b57cec5SDimitry Andric       case ModTime:
24720b57cec5SDimitry Andric         if (Header.ModTime)
24730b57cec5SDimitry Andric           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
24740b57cec5SDimitry Andric         if (!Tok.is(MMToken::IntegerLiteral)) {
24750b57cec5SDimitry Andric           Diags.Report(Tok.getLocation(),
24760b57cec5SDimitry Andric                        diag::err_mmap_invalid_header_attribute_value) << Str;
24770b57cec5SDimitry Andric           skipUntil(MMToken::RBrace);
24780b57cec5SDimitry Andric           break;
24790b57cec5SDimitry Andric         }
24800b57cec5SDimitry Andric         Header.ModTime = Tok.getInteger();
24810b57cec5SDimitry Andric         consumeToken();
24820b57cec5SDimitry Andric         break;
24830b57cec5SDimitry Andric 
24840b57cec5SDimitry Andric       case Unknown:
24850b57cec5SDimitry Andric         Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
24860b57cec5SDimitry Andric         skipUntil(MMToken::RBrace);
24870b57cec5SDimitry Andric         break;
24880b57cec5SDimitry Andric       }
24890b57cec5SDimitry Andric     }
24900b57cec5SDimitry Andric 
24910b57cec5SDimitry Andric     if (Tok.is(MMToken::RBrace))
24920b57cec5SDimitry Andric       consumeToken();
24930b57cec5SDimitry Andric     else {
24940b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
24950b57cec5SDimitry Andric       Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
24960b57cec5SDimitry Andric       HadError = true;
24970b57cec5SDimitry Andric     }
24980b57cec5SDimitry Andric   }
24990b57cec5SDimitry Andric 
25000b57cec5SDimitry Andric   bool NeedsFramework = false;
2501*c9eafe97SDimitry Andric   // Don't add headers to the builtin modules if the builtin headers belong to
2502*c9eafe97SDimitry Andric   // the system modules, with the exception of __stddef_max_align_t.h which
2503*c9eafe97SDimitry Andric   // always had its own module.
2504*c9eafe97SDimitry Andric   if (!Map.LangOpts.BuiltinHeadersInSystemModules ||
2505*c9eafe97SDimitry Andric       !isBuiltInModuleName(ActiveModule->getTopLevelModuleName()) ||
2506*c9eafe97SDimitry Andric       ActiveModule->fullModuleNameIs({"_Builtin_stddef", "max_align_t"}))
25070b57cec5SDimitry Andric     Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
25080b57cec5SDimitry Andric 
2509fe013be4SDimitry Andric   if (NeedsFramework)
25100b57cec5SDimitry Andric     Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
25110b57cec5SDimitry Andric       << ActiveModule->getFullModuleName()
25120b57cec5SDimitry Andric       << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
25130b57cec5SDimitry Andric }
25140b57cec5SDimitry Andric 
compareModuleHeaders(const Module::Header & A,const Module::Header & B)25154aee07d5SDimitry Andric static bool compareModuleHeaders(const Module::Header &A,
25164aee07d5SDimitry Andric                                  const Module::Header &B) {
25174aee07d5SDimitry Andric   return A.NameAsWritten < B.NameAsWritten;
25180b57cec5SDimitry Andric }
25190b57cec5SDimitry Andric 
25200b57cec5SDimitry Andric /// Parse an umbrella directory declaration.
25210b57cec5SDimitry Andric ///
25220b57cec5SDimitry Andric ///   umbrella-dir-declaration:
25230b57cec5SDimitry Andric ///     umbrella string-literal
parseUmbrellaDirDecl(SourceLocation UmbrellaLoc)25240b57cec5SDimitry Andric void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
25250b57cec5SDimitry Andric   // Parse the directory name.
25260b57cec5SDimitry Andric   if (!Tok.is(MMToken::StringLiteral)) {
25270b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
25280b57cec5SDimitry Andric       << "umbrella";
25290b57cec5SDimitry Andric     HadError = true;
25300b57cec5SDimitry Andric     return;
25310b57cec5SDimitry Andric   }
25320b57cec5SDimitry Andric 
25335ffd83dbSDimitry Andric   std::string DirName = std::string(Tok.getString());
2534fe6060f1SDimitry Andric   std::string DirNameAsWritten = DirName;
25350b57cec5SDimitry Andric   SourceLocation DirNameLoc = consumeToken();
25360b57cec5SDimitry Andric 
25370b57cec5SDimitry Andric   // Check whether we already have an umbrella.
2538c9157d92SDimitry Andric   if (!std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
25390b57cec5SDimitry Andric     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
25400b57cec5SDimitry Andric       << ActiveModule->getFullModuleName();
25410b57cec5SDimitry Andric     HadError = true;
25420b57cec5SDimitry Andric     return;
25430b57cec5SDimitry Andric   }
25440b57cec5SDimitry Andric 
25450b57cec5SDimitry Andric   // Look for this file.
2546fe013be4SDimitry Andric   OptionalDirectoryEntryRef Dir;
2547a7dea167SDimitry Andric   if (llvm::sys::path::is_absolute(DirName)) {
2548fe013be4SDimitry Andric     Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
2549a7dea167SDimitry Andric   } else {
25500b57cec5SDimitry Andric     SmallString<128> PathName;
2551fe013be4SDimitry Andric     PathName = Directory.getName();
25520b57cec5SDimitry Andric     llvm::sys::path::append(PathName, DirName);
2553fe013be4SDimitry Andric     Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(PathName);
25540b57cec5SDimitry Andric   }
25550b57cec5SDimitry Andric 
25560b57cec5SDimitry Andric   if (!Dir) {
25570b57cec5SDimitry Andric     Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
25580b57cec5SDimitry Andric       << DirName;
25590b57cec5SDimitry Andric     return;
25600b57cec5SDimitry Andric   }
25610b57cec5SDimitry Andric 
25620b57cec5SDimitry Andric   if (UsesRequiresExcludedHack.count(ActiveModule)) {
25630b57cec5SDimitry Andric     // Mark this header 'textual' (see doc comment for
25640b57cec5SDimitry Andric     // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
25650b57cec5SDimitry Andric     // directory is relatively expensive, in practice this only applies to the
25660b57cec5SDimitry Andric     // uncommonly used Tcl module on Darwin platforms.
25670b57cec5SDimitry Andric     std::error_code EC;
25680b57cec5SDimitry Andric     SmallVector<Module::Header, 6> Headers;
25690b57cec5SDimitry Andric     llvm::vfs::FileSystem &FS =
25700b57cec5SDimitry Andric         SourceMgr.getFileManager().getVirtualFileSystem();
25710b57cec5SDimitry Andric     for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
25720b57cec5SDimitry Andric          I != E && !EC; I.increment(EC)) {
2573bdd1243dSDimitry Andric       if (auto FE = SourceMgr.getFileManager().getOptionalFileRef(I->path())) {
2574fe013be4SDimitry Andric         Module::Header Header = {"", std::string(I->path()), *FE};
25750b57cec5SDimitry Andric         Headers.push_back(std::move(Header));
25760b57cec5SDimitry Andric       }
25770b57cec5SDimitry Andric     }
25780b57cec5SDimitry Andric 
25790b57cec5SDimitry Andric     // Sort header paths so that the pcm doesn't depend on iteration order.
25804aee07d5SDimitry Andric     std::stable_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
25810b57cec5SDimitry Andric 
25820b57cec5SDimitry Andric     for (auto &Header : Headers)
25830b57cec5SDimitry Andric       Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
25840b57cec5SDimitry Andric     return;
25850b57cec5SDimitry Andric   }
25860b57cec5SDimitry Andric 
2587fe013be4SDimitry Andric   if (Module *OwningModule = Map.UmbrellaDirs[*Dir]) {
25880b57cec5SDimitry Andric     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
25890b57cec5SDimitry Andric       << OwningModule->getFullModuleName();
25900b57cec5SDimitry Andric     HadError = true;
25910b57cec5SDimitry Andric     return;
25920b57cec5SDimitry Andric   }
25930b57cec5SDimitry Andric 
25940b57cec5SDimitry Andric   // Record this umbrella directory.
2595fe013be4SDimitry Andric   Map.setUmbrellaDirAsWritten(ActiveModule, *Dir, DirNameAsWritten, DirName);
25960b57cec5SDimitry Andric }
25970b57cec5SDimitry Andric 
25980b57cec5SDimitry Andric /// Parse a module export declaration.
25990b57cec5SDimitry Andric ///
26000b57cec5SDimitry Andric ///   export-declaration:
26010b57cec5SDimitry Andric ///     'export' wildcard-module-id
26020b57cec5SDimitry Andric ///
26030b57cec5SDimitry Andric ///   wildcard-module-id:
26040b57cec5SDimitry Andric ///     identifier
26050b57cec5SDimitry Andric ///     '*'
26060b57cec5SDimitry Andric ///     identifier '.' wildcard-module-id
parseExportDecl()26070b57cec5SDimitry Andric void ModuleMapParser::parseExportDecl() {
26080b57cec5SDimitry Andric   assert(Tok.is(MMToken::ExportKeyword));
26090b57cec5SDimitry Andric   SourceLocation ExportLoc = consumeToken();
26100b57cec5SDimitry Andric 
26110b57cec5SDimitry Andric   // Parse the module-id with an optional wildcard at the end.
26120b57cec5SDimitry Andric   ModuleId ParsedModuleId;
26130b57cec5SDimitry Andric   bool Wildcard = false;
26140b57cec5SDimitry Andric   do {
26150b57cec5SDimitry Andric     // FIXME: Support string-literal module names here.
26160b57cec5SDimitry Andric     if (Tok.is(MMToken::Identifier)) {
26175ffd83dbSDimitry Andric       ParsedModuleId.push_back(
26185ffd83dbSDimitry Andric           std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
26190b57cec5SDimitry Andric       consumeToken();
26200b57cec5SDimitry Andric 
26210b57cec5SDimitry Andric       if (Tok.is(MMToken::Period)) {
26220b57cec5SDimitry Andric         consumeToken();
26230b57cec5SDimitry Andric         continue;
26240b57cec5SDimitry Andric       }
26250b57cec5SDimitry Andric 
26260b57cec5SDimitry Andric       break;
26270b57cec5SDimitry Andric     }
26280b57cec5SDimitry Andric 
26290b57cec5SDimitry Andric     if(Tok.is(MMToken::Star)) {
26300b57cec5SDimitry Andric       Wildcard = true;
26310b57cec5SDimitry Andric       consumeToken();
26320b57cec5SDimitry Andric       break;
26330b57cec5SDimitry Andric     }
26340b57cec5SDimitry Andric 
26350b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
26360b57cec5SDimitry Andric     HadError = true;
26370b57cec5SDimitry Andric     return;
26380b57cec5SDimitry Andric   } while (true);
26390b57cec5SDimitry Andric 
26400b57cec5SDimitry Andric   Module::UnresolvedExportDecl Unresolved = {
26410b57cec5SDimitry Andric     ExportLoc, ParsedModuleId, Wildcard
26420b57cec5SDimitry Andric   };
26430b57cec5SDimitry Andric   ActiveModule->UnresolvedExports.push_back(Unresolved);
26440b57cec5SDimitry Andric }
26450b57cec5SDimitry Andric 
26460b57cec5SDimitry Andric /// Parse a module export_as declaration.
26470b57cec5SDimitry Andric ///
26480b57cec5SDimitry Andric ///   export-as-declaration:
26490b57cec5SDimitry Andric ///     'export_as' identifier
parseExportAsDecl()26500b57cec5SDimitry Andric void ModuleMapParser::parseExportAsDecl() {
26510b57cec5SDimitry Andric   assert(Tok.is(MMToken::ExportAsKeyword));
26520b57cec5SDimitry Andric   consumeToken();
26530b57cec5SDimitry Andric 
26540b57cec5SDimitry Andric   if (!Tok.is(MMToken::Identifier)) {
26550b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
26560b57cec5SDimitry Andric     HadError = true;
26570b57cec5SDimitry Andric     return;
26580b57cec5SDimitry Andric   }
26590b57cec5SDimitry Andric 
26600b57cec5SDimitry Andric   if (ActiveModule->Parent) {
26610b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
26620b57cec5SDimitry Andric     consumeToken();
26630b57cec5SDimitry Andric     return;
26640b57cec5SDimitry Andric   }
26650b57cec5SDimitry Andric 
26660b57cec5SDimitry Andric   if (!ActiveModule->ExportAsModule.empty()) {
26670b57cec5SDimitry Andric     if (ActiveModule->ExportAsModule == Tok.getString()) {
26680b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
26690b57cec5SDimitry Andric         << ActiveModule->Name << Tok.getString();
26700b57cec5SDimitry Andric     } else {
26710b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
26720b57cec5SDimitry Andric         << ActiveModule->Name << ActiveModule->ExportAsModule
26730b57cec5SDimitry Andric         << Tok.getString();
26740b57cec5SDimitry Andric     }
26750b57cec5SDimitry Andric   }
26760b57cec5SDimitry Andric 
26775ffd83dbSDimitry Andric   ActiveModule->ExportAsModule = std::string(Tok.getString());
26780b57cec5SDimitry Andric   Map.addLinkAsDependency(ActiveModule);
26790b57cec5SDimitry Andric 
26800b57cec5SDimitry Andric   consumeToken();
26810b57cec5SDimitry Andric }
26820b57cec5SDimitry Andric 
26830b57cec5SDimitry Andric /// Parse a module use declaration.
26840b57cec5SDimitry Andric ///
26850b57cec5SDimitry Andric ///   use-declaration:
26860b57cec5SDimitry Andric ///     'use' wildcard-module-id
parseUseDecl()26870b57cec5SDimitry Andric void ModuleMapParser::parseUseDecl() {
26880b57cec5SDimitry Andric   assert(Tok.is(MMToken::UseKeyword));
26890b57cec5SDimitry Andric   auto KWLoc = consumeToken();
26900b57cec5SDimitry Andric   // Parse the module-id.
26910b57cec5SDimitry Andric   ModuleId ParsedModuleId;
26920b57cec5SDimitry Andric   parseModuleId(ParsedModuleId);
26930b57cec5SDimitry Andric 
26940b57cec5SDimitry Andric   if (ActiveModule->Parent)
26950b57cec5SDimitry Andric     Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
26960b57cec5SDimitry Andric   else
26970b57cec5SDimitry Andric     ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
26980b57cec5SDimitry Andric }
26990b57cec5SDimitry Andric 
27000b57cec5SDimitry Andric /// Parse a link declaration.
27010b57cec5SDimitry Andric ///
27020b57cec5SDimitry Andric ///   module-declaration:
27030b57cec5SDimitry Andric ///     'link' 'framework'[opt] string-literal
parseLinkDecl()27040b57cec5SDimitry Andric void ModuleMapParser::parseLinkDecl() {
27050b57cec5SDimitry Andric   assert(Tok.is(MMToken::LinkKeyword));
27060b57cec5SDimitry Andric   SourceLocation LinkLoc = consumeToken();
27070b57cec5SDimitry Andric 
27080b57cec5SDimitry Andric   // Parse the optional 'framework' keyword.
27090b57cec5SDimitry Andric   bool IsFramework = false;
27100b57cec5SDimitry Andric   if (Tok.is(MMToken::FrameworkKeyword)) {
27110b57cec5SDimitry Andric     consumeToken();
27120b57cec5SDimitry Andric     IsFramework = true;
27130b57cec5SDimitry Andric   }
27140b57cec5SDimitry Andric 
27150b57cec5SDimitry Andric   // Parse the library name
27160b57cec5SDimitry Andric   if (!Tok.is(MMToken::StringLiteral)) {
27170b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
27180b57cec5SDimitry Andric       << IsFramework << SourceRange(LinkLoc);
27190b57cec5SDimitry Andric     HadError = true;
27200b57cec5SDimitry Andric     return;
27210b57cec5SDimitry Andric   }
27220b57cec5SDimitry Andric 
27235ffd83dbSDimitry Andric   std::string LibraryName = std::string(Tok.getString());
27240b57cec5SDimitry Andric   consumeToken();
27250b57cec5SDimitry Andric   ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
27260b57cec5SDimitry Andric                                                             IsFramework));
27270b57cec5SDimitry Andric }
27280b57cec5SDimitry Andric 
27290b57cec5SDimitry Andric /// Parse a configuration macro declaration.
27300b57cec5SDimitry Andric ///
27310b57cec5SDimitry Andric ///   module-declaration:
27320b57cec5SDimitry Andric ///     'config_macros' attributes[opt] config-macro-list?
27330b57cec5SDimitry Andric ///
27340b57cec5SDimitry Andric ///   config-macro-list:
27350b57cec5SDimitry Andric ///     identifier (',' identifier)?
parseConfigMacros()27360b57cec5SDimitry Andric void ModuleMapParser::parseConfigMacros() {
27370b57cec5SDimitry Andric   assert(Tok.is(MMToken::ConfigMacros));
27380b57cec5SDimitry Andric   SourceLocation ConfigMacrosLoc = consumeToken();
27390b57cec5SDimitry Andric 
27400b57cec5SDimitry Andric   // Only top-level modules can have configuration macros.
27410b57cec5SDimitry Andric   if (ActiveModule->Parent) {
27420b57cec5SDimitry Andric     Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
27430b57cec5SDimitry Andric   }
27440b57cec5SDimitry Andric 
27450b57cec5SDimitry Andric   // Parse the optional attributes.
27460b57cec5SDimitry Andric   Attributes Attrs;
27470b57cec5SDimitry Andric   if (parseOptionalAttributes(Attrs))
27480b57cec5SDimitry Andric     return;
27490b57cec5SDimitry Andric 
27500b57cec5SDimitry Andric   if (Attrs.IsExhaustive && !ActiveModule->Parent) {
27510b57cec5SDimitry Andric     ActiveModule->ConfigMacrosExhaustive = true;
27520b57cec5SDimitry Andric   }
27530b57cec5SDimitry Andric 
27540b57cec5SDimitry Andric   // If we don't have an identifier, we're done.
27550b57cec5SDimitry Andric   // FIXME: Support macros with the same name as a keyword here.
27560b57cec5SDimitry Andric   if (!Tok.is(MMToken::Identifier))
27570b57cec5SDimitry Andric     return;
27580b57cec5SDimitry Andric 
27590b57cec5SDimitry Andric   // Consume the first identifier.
27600b57cec5SDimitry Andric   if (!ActiveModule->Parent) {
27610b57cec5SDimitry Andric     ActiveModule->ConfigMacros.push_back(Tok.getString().str());
27620b57cec5SDimitry Andric   }
27630b57cec5SDimitry Andric   consumeToken();
27640b57cec5SDimitry Andric 
27650b57cec5SDimitry Andric   do {
27660b57cec5SDimitry Andric     // If there's a comma, consume it.
27670b57cec5SDimitry Andric     if (!Tok.is(MMToken::Comma))
27680b57cec5SDimitry Andric       break;
27690b57cec5SDimitry Andric     consumeToken();
27700b57cec5SDimitry Andric 
27710b57cec5SDimitry Andric     // We expect to see a macro name here.
27720b57cec5SDimitry Andric     // FIXME: Support macros with the same name as a keyword here.
27730b57cec5SDimitry Andric     if (!Tok.is(MMToken::Identifier)) {
27740b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
27750b57cec5SDimitry Andric       break;
27760b57cec5SDimitry Andric     }
27770b57cec5SDimitry Andric 
27780b57cec5SDimitry Andric     // Consume the macro name.
27790b57cec5SDimitry Andric     if (!ActiveModule->Parent) {
27800b57cec5SDimitry Andric       ActiveModule->ConfigMacros.push_back(Tok.getString().str());
27810b57cec5SDimitry Andric     }
27820b57cec5SDimitry Andric     consumeToken();
27830b57cec5SDimitry Andric   } while (true);
27840b57cec5SDimitry Andric }
27850b57cec5SDimitry Andric 
27860b57cec5SDimitry Andric /// Format a module-id into a string.
formatModuleId(const ModuleId & Id)27870b57cec5SDimitry Andric static std::string formatModuleId(const ModuleId &Id) {
27880b57cec5SDimitry Andric   std::string result;
27890b57cec5SDimitry Andric   {
27900b57cec5SDimitry Andric     llvm::raw_string_ostream OS(result);
27910b57cec5SDimitry Andric 
27920b57cec5SDimitry Andric     for (unsigned I = 0, N = Id.size(); I != N; ++I) {
27930b57cec5SDimitry Andric       if (I)
27940b57cec5SDimitry Andric         OS << ".";
27950b57cec5SDimitry Andric       OS << Id[I].first;
27960b57cec5SDimitry Andric     }
27970b57cec5SDimitry Andric   }
27980b57cec5SDimitry Andric 
27990b57cec5SDimitry Andric   return result;
28000b57cec5SDimitry Andric }
28010b57cec5SDimitry Andric 
28020b57cec5SDimitry Andric /// Parse a conflict declaration.
28030b57cec5SDimitry Andric ///
28040b57cec5SDimitry Andric ///   module-declaration:
28050b57cec5SDimitry Andric ///     'conflict' module-id ',' string-literal
parseConflict()28060b57cec5SDimitry Andric void ModuleMapParser::parseConflict() {
28070b57cec5SDimitry Andric   assert(Tok.is(MMToken::Conflict));
28080b57cec5SDimitry Andric   SourceLocation ConflictLoc = consumeToken();
28090b57cec5SDimitry Andric   Module::UnresolvedConflict Conflict;
28100b57cec5SDimitry Andric 
28110b57cec5SDimitry Andric   // Parse the module-id.
28120b57cec5SDimitry Andric   if (parseModuleId(Conflict.Id))
28130b57cec5SDimitry Andric     return;
28140b57cec5SDimitry Andric 
28150b57cec5SDimitry Andric   // Parse the ','.
28160b57cec5SDimitry Andric   if (!Tok.is(MMToken::Comma)) {
28170b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
28180b57cec5SDimitry Andric       << SourceRange(ConflictLoc);
28190b57cec5SDimitry Andric     return;
28200b57cec5SDimitry Andric   }
28210b57cec5SDimitry Andric   consumeToken();
28220b57cec5SDimitry Andric 
28230b57cec5SDimitry Andric   // Parse the message.
28240b57cec5SDimitry Andric   if (!Tok.is(MMToken::StringLiteral)) {
28250b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
28260b57cec5SDimitry Andric       << formatModuleId(Conflict.Id);
28270b57cec5SDimitry Andric     return;
28280b57cec5SDimitry Andric   }
28290b57cec5SDimitry Andric   Conflict.Message = Tok.getString().str();
28300b57cec5SDimitry Andric   consumeToken();
28310b57cec5SDimitry Andric 
28320b57cec5SDimitry Andric   // Add this unresolved conflict.
28330b57cec5SDimitry Andric   ActiveModule->UnresolvedConflicts.push_back(Conflict);
28340b57cec5SDimitry Andric }
28350b57cec5SDimitry Andric 
28360b57cec5SDimitry Andric /// Parse an inferred module declaration (wildcard modules).
28370b57cec5SDimitry Andric ///
28380b57cec5SDimitry Andric ///   module-declaration:
28390b57cec5SDimitry Andric ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
28400b57cec5SDimitry Andric ///       { inferred-module-member* }
28410b57cec5SDimitry Andric ///
28420b57cec5SDimitry Andric ///   inferred-module-member:
28430b57cec5SDimitry Andric ///     'export' '*'
28440b57cec5SDimitry Andric ///     'exclude' identifier
parseInferredModuleDecl(bool Framework,bool Explicit)28450b57cec5SDimitry Andric void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
28460b57cec5SDimitry Andric   assert(Tok.is(MMToken::Star));
28470b57cec5SDimitry Andric   SourceLocation StarLoc = consumeToken();
28480b57cec5SDimitry Andric   bool Failed = false;
28490b57cec5SDimitry Andric 
28500b57cec5SDimitry Andric   // Inferred modules must be submodules.
28510b57cec5SDimitry Andric   if (!ActiveModule && !Framework) {
28520b57cec5SDimitry Andric     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
28530b57cec5SDimitry Andric     Failed = true;
28540b57cec5SDimitry Andric   }
28550b57cec5SDimitry Andric 
28560b57cec5SDimitry Andric   if (ActiveModule) {
28570b57cec5SDimitry Andric     // Inferred modules must have umbrella directories.
28580b57cec5SDimitry Andric     if (!Failed && ActiveModule->IsAvailable &&
2859fe013be4SDimitry Andric         !ActiveModule->getEffectiveUmbrellaDir()) {
28600b57cec5SDimitry Andric       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
28610b57cec5SDimitry Andric       Failed = true;
28620b57cec5SDimitry Andric     }
28630b57cec5SDimitry Andric 
28640b57cec5SDimitry Andric     // Check for redefinition of an inferred module.
28650b57cec5SDimitry Andric     if (!Failed && ActiveModule->InferSubmodules) {
28660b57cec5SDimitry Andric       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
28670b57cec5SDimitry Andric       if (ActiveModule->InferredSubmoduleLoc.isValid())
28680b57cec5SDimitry Andric         Diags.Report(ActiveModule->InferredSubmoduleLoc,
28690b57cec5SDimitry Andric                      diag::note_mmap_prev_definition);
28700b57cec5SDimitry Andric       Failed = true;
28710b57cec5SDimitry Andric     }
28720b57cec5SDimitry Andric 
28730b57cec5SDimitry Andric     // Check for the 'framework' keyword, which is not permitted here.
28740b57cec5SDimitry Andric     if (Framework) {
28750b57cec5SDimitry Andric       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
28760b57cec5SDimitry Andric       Framework = false;
28770b57cec5SDimitry Andric     }
28780b57cec5SDimitry Andric   } else if (Explicit) {
28790b57cec5SDimitry Andric     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
28800b57cec5SDimitry Andric     Explicit = false;
28810b57cec5SDimitry Andric   }
28820b57cec5SDimitry Andric 
28830b57cec5SDimitry Andric   // If there were any problems with this inferred submodule, skip its body.
28840b57cec5SDimitry Andric   if (Failed) {
28850b57cec5SDimitry Andric     if (Tok.is(MMToken::LBrace)) {
28860b57cec5SDimitry Andric       consumeToken();
28870b57cec5SDimitry Andric       skipUntil(MMToken::RBrace);
28880b57cec5SDimitry Andric       if (Tok.is(MMToken::RBrace))
28890b57cec5SDimitry Andric         consumeToken();
28900b57cec5SDimitry Andric     }
28910b57cec5SDimitry Andric     HadError = true;
28920b57cec5SDimitry Andric     return;
28930b57cec5SDimitry Andric   }
28940b57cec5SDimitry Andric 
28950b57cec5SDimitry Andric   // Parse optional attributes.
28960b57cec5SDimitry Andric   Attributes Attrs;
28970b57cec5SDimitry Andric   if (parseOptionalAttributes(Attrs))
28980b57cec5SDimitry Andric     return;
28990b57cec5SDimitry Andric 
29000b57cec5SDimitry Andric   if (ActiveModule) {
29010b57cec5SDimitry Andric     // Note that we have an inferred submodule.
29020b57cec5SDimitry Andric     ActiveModule->InferSubmodules = true;
29030b57cec5SDimitry Andric     ActiveModule->InferredSubmoduleLoc = StarLoc;
29040b57cec5SDimitry Andric     ActiveModule->InferExplicitSubmodules = Explicit;
29050b57cec5SDimitry Andric   } else {
29060b57cec5SDimitry Andric     // We'll be inferring framework modules for this directory.
29070b57cec5SDimitry Andric     Map.InferredDirectories[Directory].InferModules = true;
29080b57cec5SDimitry Andric     Map.InferredDirectories[Directory].Attrs = Attrs;
29090b57cec5SDimitry Andric     Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
29100b57cec5SDimitry Andric     // FIXME: Handle the 'framework' keyword.
29110b57cec5SDimitry Andric   }
29120b57cec5SDimitry Andric 
29130b57cec5SDimitry Andric   // Parse the opening brace.
29140b57cec5SDimitry Andric   if (!Tok.is(MMToken::LBrace)) {
29150b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
29160b57cec5SDimitry Andric     HadError = true;
29170b57cec5SDimitry Andric     return;
29180b57cec5SDimitry Andric   }
29190b57cec5SDimitry Andric   SourceLocation LBraceLoc = consumeToken();
29200b57cec5SDimitry Andric 
29210b57cec5SDimitry Andric   // Parse the body of the inferred submodule.
29220b57cec5SDimitry Andric   bool Done = false;
29230b57cec5SDimitry Andric   do {
29240b57cec5SDimitry Andric     switch (Tok.Kind) {
29250b57cec5SDimitry Andric     case MMToken::EndOfFile:
29260b57cec5SDimitry Andric     case MMToken::RBrace:
29270b57cec5SDimitry Andric       Done = true;
29280b57cec5SDimitry Andric       break;
29290b57cec5SDimitry Andric 
29300b57cec5SDimitry Andric     case MMToken::ExcludeKeyword:
29310b57cec5SDimitry Andric       if (ActiveModule) {
29320b57cec5SDimitry Andric         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
29330b57cec5SDimitry Andric           << (ActiveModule != nullptr);
29340b57cec5SDimitry Andric         consumeToken();
29350b57cec5SDimitry Andric         break;
29360b57cec5SDimitry Andric       }
29370b57cec5SDimitry Andric 
29380b57cec5SDimitry Andric       consumeToken();
29390b57cec5SDimitry Andric       // FIXME: Support string-literal module names here.
29400b57cec5SDimitry Andric       if (!Tok.is(MMToken::Identifier)) {
29410b57cec5SDimitry Andric         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
29420b57cec5SDimitry Andric         break;
29430b57cec5SDimitry Andric       }
29440b57cec5SDimitry Andric 
29455ffd83dbSDimitry Andric       Map.InferredDirectories[Directory].ExcludedModules.push_back(
29465ffd83dbSDimitry Andric           std::string(Tok.getString()));
29470b57cec5SDimitry Andric       consumeToken();
29480b57cec5SDimitry Andric       break;
29490b57cec5SDimitry Andric 
29500b57cec5SDimitry Andric     case MMToken::ExportKeyword:
29510b57cec5SDimitry Andric       if (!ActiveModule) {
29520b57cec5SDimitry Andric         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
29530b57cec5SDimitry Andric           << (ActiveModule != nullptr);
29540b57cec5SDimitry Andric         consumeToken();
29550b57cec5SDimitry Andric         break;
29560b57cec5SDimitry Andric       }
29570b57cec5SDimitry Andric 
29580b57cec5SDimitry Andric       consumeToken();
29590b57cec5SDimitry Andric       if (Tok.is(MMToken::Star))
29600b57cec5SDimitry Andric         ActiveModule->InferExportWildcard = true;
29610b57cec5SDimitry Andric       else
29620b57cec5SDimitry Andric         Diags.Report(Tok.getLocation(),
29630b57cec5SDimitry Andric                      diag::err_mmap_expected_export_wildcard);
29640b57cec5SDimitry Andric       consumeToken();
29650b57cec5SDimitry Andric       break;
29660b57cec5SDimitry Andric 
29670b57cec5SDimitry Andric     case MMToken::ExplicitKeyword:
29680b57cec5SDimitry Andric     case MMToken::ModuleKeyword:
29690b57cec5SDimitry Andric     case MMToken::HeaderKeyword:
29700b57cec5SDimitry Andric     case MMToken::PrivateKeyword:
29710b57cec5SDimitry Andric     case MMToken::UmbrellaKeyword:
29720b57cec5SDimitry Andric     default:
29730b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
29740b57cec5SDimitry Andric           << (ActiveModule != nullptr);
29750b57cec5SDimitry Andric       consumeToken();
29760b57cec5SDimitry Andric       break;
29770b57cec5SDimitry Andric     }
29780b57cec5SDimitry Andric   } while (!Done);
29790b57cec5SDimitry Andric 
29800b57cec5SDimitry Andric   if (Tok.is(MMToken::RBrace))
29810b57cec5SDimitry Andric     consumeToken();
29820b57cec5SDimitry Andric   else {
29830b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
29840b57cec5SDimitry Andric     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
29850b57cec5SDimitry Andric     HadError = true;
29860b57cec5SDimitry Andric   }
29870b57cec5SDimitry Andric }
29880b57cec5SDimitry Andric 
29890b57cec5SDimitry Andric /// Parse optional attributes.
29900b57cec5SDimitry Andric ///
29910b57cec5SDimitry Andric ///   attributes:
29920b57cec5SDimitry Andric ///     attribute attributes
29930b57cec5SDimitry Andric ///     attribute
29940b57cec5SDimitry Andric ///
29950b57cec5SDimitry Andric ///   attribute:
29960b57cec5SDimitry Andric ///     [ identifier ]
29970b57cec5SDimitry Andric ///
29980b57cec5SDimitry Andric /// \param Attrs Will be filled in with the parsed attributes.
29990b57cec5SDimitry Andric ///
30000b57cec5SDimitry Andric /// \returns true if an error occurred, false otherwise.
parseOptionalAttributes(Attributes & Attrs)30010b57cec5SDimitry Andric bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
30020b57cec5SDimitry Andric   bool HadError = false;
30030b57cec5SDimitry Andric 
30040b57cec5SDimitry Andric   while (Tok.is(MMToken::LSquare)) {
30050b57cec5SDimitry Andric     // Consume the '['.
30060b57cec5SDimitry Andric     SourceLocation LSquareLoc = consumeToken();
30070b57cec5SDimitry Andric 
30080b57cec5SDimitry Andric     // Check whether we have an attribute name here.
30090b57cec5SDimitry Andric     if (!Tok.is(MMToken::Identifier)) {
30100b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
30110b57cec5SDimitry Andric       skipUntil(MMToken::RSquare);
30120b57cec5SDimitry Andric       if (Tok.is(MMToken::RSquare))
30130b57cec5SDimitry Andric         consumeToken();
30140b57cec5SDimitry Andric       HadError = true;
30150b57cec5SDimitry Andric     }
30160b57cec5SDimitry Andric 
30170b57cec5SDimitry Andric     // Decode the attribute name.
30180b57cec5SDimitry Andric     AttributeKind Attribute
30190b57cec5SDimitry Andric       = llvm::StringSwitch<AttributeKind>(Tok.getString())
30200b57cec5SDimitry Andric           .Case("exhaustive", AT_exhaustive)
30210b57cec5SDimitry Andric           .Case("extern_c", AT_extern_c)
30220b57cec5SDimitry Andric           .Case("no_undeclared_includes", AT_no_undeclared_includes)
30230b57cec5SDimitry Andric           .Case("system", AT_system)
30240b57cec5SDimitry Andric           .Default(AT_unknown);
30250b57cec5SDimitry Andric     switch (Attribute) {
30260b57cec5SDimitry Andric     case AT_unknown:
30270b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
30280b57cec5SDimitry Andric         << Tok.getString();
30290b57cec5SDimitry Andric       break;
30300b57cec5SDimitry Andric 
30310b57cec5SDimitry Andric     case AT_system:
30320b57cec5SDimitry Andric       Attrs.IsSystem = true;
30330b57cec5SDimitry Andric       break;
30340b57cec5SDimitry Andric 
30350b57cec5SDimitry Andric     case AT_extern_c:
30360b57cec5SDimitry Andric       Attrs.IsExternC = true;
30370b57cec5SDimitry Andric       break;
30380b57cec5SDimitry Andric 
30390b57cec5SDimitry Andric     case AT_exhaustive:
30400b57cec5SDimitry Andric       Attrs.IsExhaustive = true;
30410b57cec5SDimitry Andric       break;
30420b57cec5SDimitry Andric 
30430b57cec5SDimitry Andric     case AT_no_undeclared_includes:
30440b57cec5SDimitry Andric       Attrs.NoUndeclaredIncludes = true;
30450b57cec5SDimitry Andric       break;
30460b57cec5SDimitry Andric     }
30470b57cec5SDimitry Andric     consumeToken();
30480b57cec5SDimitry Andric 
30490b57cec5SDimitry Andric     // Consume the ']'.
30500b57cec5SDimitry Andric     if (!Tok.is(MMToken::RSquare)) {
30510b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
30520b57cec5SDimitry Andric       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
30530b57cec5SDimitry Andric       skipUntil(MMToken::RSquare);
30540b57cec5SDimitry Andric       HadError = true;
30550b57cec5SDimitry Andric     }
30560b57cec5SDimitry Andric 
30570b57cec5SDimitry Andric     if (Tok.is(MMToken::RSquare))
30580b57cec5SDimitry Andric       consumeToken();
30590b57cec5SDimitry Andric   }
30600b57cec5SDimitry Andric 
30610b57cec5SDimitry Andric   return HadError;
30620b57cec5SDimitry Andric }
30630b57cec5SDimitry Andric 
30640b57cec5SDimitry Andric /// Parse a module map file.
30650b57cec5SDimitry Andric ///
30660b57cec5SDimitry Andric ///   module-map-file:
30670b57cec5SDimitry Andric ///     module-declaration*
parseModuleMapFile()30680b57cec5SDimitry Andric bool ModuleMapParser::parseModuleMapFile() {
30690b57cec5SDimitry Andric   do {
30700b57cec5SDimitry Andric     switch (Tok.Kind) {
30710b57cec5SDimitry Andric     case MMToken::EndOfFile:
30720b57cec5SDimitry Andric       return HadError;
30730b57cec5SDimitry Andric 
30740b57cec5SDimitry Andric     case MMToken::ExplicitKeyword:
30750b57cec5SDimitry Andric     case MMToken::ExternKeyword:
30760b57cec5SDimitry Andric     case MMToken::ModuleKeyword:
30770b57cec5SDimitry Andric     case MMToken::FrameworkKeyword:
30780b57cec5SDimitry Andric       parseModuleDecl();
30790b57cec5SDimitry Andric       break;
30800b57cec5SDimitry Andric 
30810b57cec5SDimitry Andric     case MMToken::Comma:
30820b57cec5SDimitry Andric     case MMToken::ConfigMacros:
30830b57cec5SDimitry Andric     case MMToken::Conflict:
30840b57cec5SDimitry Andric     case MMToken::Exclaim:
30850b57cec5SDimitry Andric     case MMToken::ExcludeKeyword:
30860b57cec5SDimitry Andric     case MMToken::ExportKeyword:
30870b57cec5SDimitry Andric     case MMToken::ExportAsKeyword:
30880b57cec5SDimitry Andric     case MMToken::HeaderKeyword:
30890b57cec5SDimitry Andric     case MMToken::Identifier:
30900b57cec5SDimitry Andric     case MMToken::LBrace:
30910b57cec5SDimitry Andric     case MMToken::LinkKeyword:
30920b57cec5SDimitry Andric     case MMToken::LSquare:
30930b57cec5SDimitry Andric     case MMToken::Period:
30940b57cec5SDimitry Andric     case MMToken::PrivateKeyword:
30950b57cec5SDimitry Andric     case MMToken::RBrace:
30960b57cec5SDimitry Andric     case MMToken::RSquare:
30970b57cec5SDimitry Andric     case MMToken::RequiresKeyword:
30980b57cec5SDimitry Andric     case MMToken::Star:
30990b57cec5SDimitry Andric     case MMToken::StringLiteral:
31000b57cec5SDimitry Andric     case MMToken::IntegerLiteral:
31010b57cec5SDimitry Andric     case MMToken::TextualKeyword:
31020b57cec5SDimitry Andric     case MMToken::UmbrellaKeyword:
31030b57cec5SDimitry Andric     case MMToken::UseKeyword:
31040b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
31050b57cec5SDimitry Andric       HadError = true;
31060b57cec5SDimitry Andric       consumeToken();
31070b57cec5SDimitry Andric       break;
31080b57cec5SDimitry Andric     }
31090b57cec5SDimitry Andric   } while (true);
31100b57cec5SDimitry Andric }
31110b57cec5SDimitry Andric 
parseModuleMapFile(FileEntryRef File,bool IsSystem,DirectoryEntryRef Dir,FileID ID,unsigned * Offset,SourceLocation ExternModuleLoc)3112c9157d92SDimitry Andric bool ModuleMap::parseModuleMapFile(FileEntryRef File, bool IsSystem,
3113fe013be4SDimitry Andric                                    DirectoryEntryRef Dir, FileID ID,
31140b57cec5SDimitry Andric                                    unsigned *Offset,
31150b57cec5SDimitry Andric                                    SourceLocation ExternModuleLoc) {
31160b57cec5SDimitry Andric   assert(Target && "Missing target information");
31170b57cec5SDimitry Andric   llvm::DenseMap<const FileEntry *, bool>::iterator Known
31180b57cec5SDimitry Andric     = ParsedModuleMap.find(File);
31190b57cec5SDimitry Andric   if (Known != ParsedModuleMap.end())
31200b57cec5SDimitry Andric     return Known->second;
31210b57cec5SDimitry Andric 
31220b57cec5SDimitry Andric   // If the module map file wasn't already entered, do so now.
31230b57cec5SDimitry Andric   if (ID.isInvalid()) {
31240b57cec5SDimitry Andric     auto FileCharacter =
31250b57cec5SDimitry Andric         IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
31260b57cec5SDimitry Andric     ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
31270b57cec5SDimitry Andric   }
31280b57cec5SDimitry Andric 
31290b57cec5SDimitry Andric   assert(Target && "Missing target information");
3130bdd1243dSDimitry Andric   std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
31310b57cec5SDimitry Andric   if (!Buffer)
31320b57cec5SDimitry Andric     return ParsedModuleMap[File] = true;
31330b57cec5SDimitry Andric   assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
31340b57cec5SDimitry Andric          "invalid buffer offset");
31350b57cec5SDimitry Andric 
31360b57cec5SDimitry Andric   // Parse this module map file.
31370b57cec5SDimitry Andric   Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
31380b57cec5SDimitry Andric           Buffer->getBufferStart(),
31390b57cec5SDimitry Andric           Buffer->getBufferStart() + (Offset ? *Offset : 0),
31400b57cec5SDimitry Andric           Buffer->getBufferEnd());
31410b57cec5SDimitry Andric   SourceLocation Start = L.getSourceLocation();
31420b57cec5SDimitry Andric   ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
31430b57cec5SDimitry Andric                          IsSystem);
31440b57cec5SDimitry Andric   bool Result = Parser.parseModuleMapFile();
31450b57cec5SDimitry Andric   ParsedModuleMap[File] = Result;
31460b57cec5SDimitry Andric 
31470b57cec5SDimitry Andric   if (Offset) {
31480b57cec5SDimitry Andric     auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
31490b57cec5SDimitry Andric     assert(Loc.first == ID && "stopped in a different file?");
31500b57cec5SDimitry Andric     *Offset = Loc.second;
31510b57cec5SDimitry Andric   }
31520b57cec5SDimitry Andric 
31530b57cec5SDimitry Andric   // Notify callbacks that we parsed it.
31540b57cec5SDimitry Andric   for (const auto &Cb : Callbacks)
3155c9157d92SDimitry Andric     Cb->moduleMapFileRead(Start, File, IsSystem);
31560b57cec5SDimitry Andric 
31570b57cec5SDimitry Andric   return Result;
31580b57cec5SDimitry Andric }
3159