xref: /freebsd-src/contrib/llvm-project/clang/lib/Lex/ModuleMap.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 
560b57cec5SDimitry Andric void ModuleMapCallbacks::anchor() {}
570b57cec5SDimitry Andric 
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 
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 
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
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 
109bdd1243dSDimitry Andric bool ModuleMap::isModular(ModuleHeaderRole Role) {
110bdd1243dSDimitry Andric   return !(Role & (ModuleMap::TextualHeader | ModuleMap::ExcludedHeader));
111bdd1243dSDimitry Andric }
112bdd1243dSDimitry Andric 
1130b57cec5SDimitry Andric Module::ExportDecl
1140b57cec5SDimitry 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 
1310b57cec5SDimitry 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.
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 
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.
18406c3fb27SDimitry 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 
2385f757f3fSDimitry 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 
2565f757f3fSDimitry Andric /// Determine whether the given file name is the name of a builtin
2575f757f3fSDimitry Andric /// header, supplied by Clang to replace, override, or augment existing system
2585f757f3fSDimitry Andric /// headers.
2595f757f3fSDimitry Andric static bool isBuiltinHeaderName(StringRef FileName) {
2605f757f3fSDimitry Andric   return llvm::StringSwitch<bool>(FileName)
2615f757f3fSDimitry Andric            .Case("float.h", true)
2625f757f3fSDimitry Andric            .Case("iso646.h", true)
2635f757f3fSDimitry Andric            .Case("limits.h", true)
2645f757f3fSDimitry Andric            .Case("stdalign.h", true)
2655f757f3fSDimitry Andric            .Case("stdarg.h", true)
2665f757f3fSDimitry Andric            .Case("stdatomic.h", true)
2675f757f3fSDimitry Andric            .Case("stdbool.h", true)
2685f757f3fSDimitry Andric            .Case("stddef.h", true)
2695f757f3fSDimitry Andric            .Case("stdint.h", true)
2705f757f3fSDimitry Andric            .Case("tgmath.h", true)
2715f757f3fSDimitry Andric            .Case("unwind.h", true)
2725f757f3fSDimitry Andric            .Default(false);
2735f757f3fSDimitry Andric }
2745f757f3fSDimitry Andric 
2755f757f3fSDimitry Andric /// Determine whether the given module name is the name of a builtin
2765f757f3fSDimitry Andric /// module that is cyclic with a system module  on some platforms.
2775f757f3fSDimitry Andric static bool isBuiltInModuleName(StringRef ModuleName) {
2785f757f3fSDimitry Andric   return llvm::StringSwitch<bool>(ModuleName)
2795f757f3fSDimitry Andric            .Case("_Builtin_float", true)
2805f757f3fSDimitry Andric            .Case("_Builtin_inttypes", true)
2815f757f3fSDimitry Andric            .Case("_Builtin_iso646", true)
2825f757f3fSDimitry Andric            .Case("_Builtin_limits", true)
2835f757f3fSDimitry Andric            .Case("_Builtin_stdalign", true)
2845f757f3fSDimitry Andric            .Case("_Builtin_stdarg", true)
2855f757f3fSDimitry Andric            .Case("_Builtin_stdatomic", true)
2865f757f3fSDimitry Andric            .Case("_Builtin_stdbool", true)
2875f757f3fSDimitry Andric            .Case("_Builtin_stddef", true)
2885f757f3fSDimitry Andric            .Case("_Builtin_stdint", true)
2895f757f3fSDimitry Andric            .Case("_Builtin_stdnoreturn", true)
2905f757f3fSDimitry Andric            .Case("_Builtin_tgmath", true)
2915f757f3fSDimitry Andric            .Case("_Builtin_unwind", true)
2925f757f3fSDimitry Andric            .Default(false);
2935f757f3fSDimitry Andric }
2945f757f3fSDimitry Andric 
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.
30806c3fb27SDimitry Andric         setUmbrellaHeaderAsWritten(Mod, *File, Header.FileName,
30906c3fb27SDimitry Andric                                    RelativePathName.str());
3100b57cec5SDimitry Andric     } else {
3117a6dacacSDimitry 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 
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 ||
3395f757f3fSDimitry 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 
3515f757f3fSDimitry 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 
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 
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 
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.
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 
4155f757f3fSDimitry Andric bool ModuleMap::isBuiltinHeader(FileEntryRef File) {
4165f757f3fSDimitry Andric   return File.getDir() == BuiltinIncludeDir && LangOpts.BuiltinHeadersInSystemModules &&
4175f757f3fSDimitry Andric          isBuiltinHeaderName(llvm::sys::path::filename(File.getName()));
4180b57cec5SDimitry Andric }
4190b57cec5SDimitry Andric 
4205f757f3fSDimitry Andric bool ModuleMap::shouldImportRelativeToBuiltinIncludeDir(StringRef FileName,
4215f757f3fSDimitry Andric                                                         Module *Module) const {
4225f757f3fSDimitry Andric   return LangOpts.BuiltinHeadersInSystemModules && BuiltinIncludeDir &&
4235f757f3fSDimitry Andric          Module->IsSystem && !Module->isPartOfFramework() &&
4245f757f3fSDimitry Andric          isBuiltinHeaderName(FileName);
4255ffd83dbSDimitry Andric }
4265ffd83dbSDimitry Andric 
4275f757f3fSDimitry 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 
43806c3fb27SDimitry Andric ModuleMap::KnownHeader ModuleMap::findHeaderInUmbrellaDirs(
43906c3fb27SDimitry Andric     FileEntryRef File, SmallVectorImpl<DirectoryEntryRef> &IntermediateDirs) {
4400b57cec5SDimitry Andric   if (UmbrellaDirs.empty())
4410b57cec5SDimitry Andric     return {};
4420b57cec5SDimitry Andric 
44306c3fb27SDimitry 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.
44906c3fb27SDimitry 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 {
45406c3fb27SDimitry Andric     auto KnownDir = UmbrellaDirs.find(*Dir);
4550b57cec5SDimitry Andric     if (KnownDir != UmbrellaDirs.end())
4560b57cec5SDimitry Andric       return KnownHeader(KnownDir->second, NormalHeader);
4570b57cec5SDimitry Andric 
45806c3fb27SDimitry 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.
46606c3fb27SDimitry Andric     Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
4670b57cec5SDimitry Andric   } while (Dir);
4680b57cec5SDimitry Andric   return {};
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric 
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 
4920b57cec5SDimitry Andric static Module *getTopLevelOrNull(Module *M) {
4930b57cec5SDimitry Andric   return M ? M->getTopLevelModule() : nullptr;
4940b57cec5SDimitry Andric }
4950b57cec5SDimitry Andric 
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) {
55306c3fb27SDimitry Andric     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module_indirect)
55406c3fb27SDimitry Andric         << RequestingModule->getTopLevelModule()->Name << Filename
55506c3fb27SDimitry 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 
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 
60606c3fb27SDimitry 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
63606c3fb27SDimitry Andric ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(FileEntryRef File) {
6370b57cec5SDimitry Andric   assert(!Headers.count(File) && "already have a module for this header");
6380b57cec5SDimitry Andric 
63906c3fb27SDimitry 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;
64706c3fb27SDimitry Andric     while (!UmbrellaModule->getEffectiveUmbrellaDir() && UmbrellaModule->Parent)
6480b57cec5SDimitry Andric       UmbrellaModule = UmbrellaModule->Parent;
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric     if (UmbrellaModule->InferSubmodules) {
651*0fca6ea1SDimitry Andric       FileID UmbrellaModuleMap = getModuleMapFileIDForUniquing(UmbrellaModule);
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric       // Infer submodules for each of the directories we found between
6540b57cec5SDimitry Andric       // the directory of the umbrella header and the directory where
6550b57cec5SDimitry Andric       // the actual header is located.
6560b57cec5SDimitry Andric       bool Explicit = UmbrellaModule->InferExplicitSubmodules;
6570b57cec5SDimitry Andric 
65806c3fb27SDimitry Andric       for (DirectoryEntryRef SkippedDir : llvm::reverse(SkippedDirs)) {
6590b57cec5SDimitry Andric         // Find or create the module that corresponds to this directory name.
6600b57cec5SDimitry Andric         SmallString<32> NameBuf;
6610b57cec5SDimitry Andric         StringRef Name = sanitizeFilenameAsIdentifier(
66206c3fb27SDimitry Andric             llvm::sys::path::stem(SkippedDir.getName()), NameBuf);
6630b57cec5SDimitry Andric         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6640b57cec5SDimitry Andric                                     Explicit).first;
6650b57cec5SDimitry Andric         InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
6660b57cec5SDimitry Andric         Result->IsInferred = true;
6670b57cec5SDimitry Andric 
6680b57cec5SDimitry Andric         // Associate the module and the directory.
669349cc55cSDimitry Andric         UmbrellaDirs[SkippedDir] = Result;
6700b57cec5SDimitry Andric 
6710b57cec5SDimitry Andric         // If inferred submodules export everything they import, add a
6720b57cec5SDimitry Andric         // wildcard to the set of exports.
6730b57cec5SDimitry Andric         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
6740b57cec5SDimitry Andric           Result->Exports.push_back(Module::ExportDecl(nullptr, true));
6750b57cec5SDimitry Andric       }
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric       // Infer a submodule with the same name as this header file.
6780b57cec5SDimitry Andric       SmallString<32> NameBuf;
6790b57cec5SDimitry Andric       StringRef Name = sanitizeFilenameAsIdentifier(
68006c3fb27SDimitry Andric                          llvm::sys::path::stem(File.getName()), NameBuf);
6810b57cec5SDimitry Andric       Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6820b57cec5SDimitry Andric                                   Explicit).first;
6830b57cec5SDimitry Andric       InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
6840b57cec5SDimitry Andric       Result->IsInferred = true;
6850b57cec5SDimitry Andric       Result->addTopHeader(File);
6860b57cec5SDimitry Andric 
6870b57cec5SDimitry Andric       // If inferred submodules export everything they import, add a
6880b57cec5SDimitry Andric       // wildcard to the set of exports.
6890b57cec5SDimitry Andric       if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
6900b57cec5SDimitry Andric         Result->Exports.push_back(Module::ExportDecl(nullptr, true));
6910b57cec5SDimitry Andric     } else {
6920b57cec5SDimitry Andric       // Record each of the directories we stepped through as being part of
6930b57cec5SDimitry Andric       // the module we found, since the umbrella header covers them all.
6940b57cec5SDimitry Andric       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
6950b57cec5SDimitry Andric         UmbrellaDirs[SkippedDirs[I]] = Result;
6960b57cec5SDimitry Andric     }
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric     KnownHeader Header(Result, NormalHeader);
6990b57cec5SDimitry Andric     Headers[File].push_back(Header);
7000b57cec5SDimitry Andric     return Header;
7010b57cec5SDimitry Andric   }
7020b57cec5SDimitry Andric 
7030b57cec5SDimitry Andric   return {};
7040b57cec5SDimitry Andric }
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric ArrayRef<ModuleMap::KnownHeader>
70706c3fb27SDimitry Andric ModuleMap::findAllModulesForHeader(FileEntryRef File) {
7085ffd83dbSDimitry Andric   HeadersMap::iterator Known = findKnownHeader(File);
7095ffd83dbSDimitry Andric   if (Known != Headers.end())
7105ffd83dbSDimitry Andric     return Known->second;
7115ffd83dbSDimitry Andric 
7125ffd83dbSDimitry Andric   if (findOrCreateModuleForHeaderInUmbrellaDir(File))
7135ffd83dbSDimitry Andric     return Headers.find(File)->second;
7145ffd83dbSDimitry Andric 
715bdd1243dSDimitry Andric   return std::nullopt;
7165ffd83dbSDimitry Andric }
7175ffd83dbSDimitry Andric 
7185ffd83dbSDimitry Andric ArrayRef<ModuleMap::KnownHeader>
7195f757f3fSDimitry Andric ModuleMap::findResolvedModulesForHeader(FileEntryRef File) const {
7205ffd83dbSDimitry Andric   // FIXME: Is this necessary?
7210b57cec5SDimitry Andric   resolveHeaderDirectives(File);
7220b57cec5SDimitry Andric   auto It = Headers.find(File);
7230b57cec5SDimitry Andric   if (It == Headers.end())
724bdd1243dSDimitry Andric     return std::nullopt;
7250b57cec5SDimitry Andric   return It->second;
7260b57cec5SDimitry Andric }
7270b57cec5SDimitry Andric 
72806c3fb27SDimitry Andric bool ModuleMap::isHeaderInUnavailableModule(FileEntryRef Header) const {
7290b57cec5SDimitry Andric   return isHeaderUnavailableInModule(Header, nullptr);
7300b57cec5SDimitry Andric }
7310b57cec5SDimitry Andric 
73206c3fb27SDimitry Andric bool ModuleMap::isHeaderUnavailableInModule(
73306c3fb27SDimitry Andric     FileEntryRef Header, const Module *RequestingModule) const {
7340b57cec5SDimitry Andric   resolveHeaderDirectives(Header);
7350b57cec5SDimitry Andric   HeadersMap::const_iterator Known = Headers.find(Header);
7360b57cec5SDimitry Andric   if (Known != Headers.end()) {
7370b57cec5SDimitry Andric     for (SmallVectorImpl<KnownHeader>::const_iterator
7380b57cec5SDimitry Andric              I = Known->second.begin(),
7390b57cec5SDimitry Andric              E = Known->second.end();
7400b57cec5SDimitry Andric          I != E; ++I) {
7410b57cec5SDimitry Andric 
742bdd1243dSDimitry Andric       if (I->getRole() == ModuleMap::ExcludedHeader)
743bdd1243dSDimitry Andric         continue;
744bdd1243dSDimitry Andric 
7450b57cec5SDimitry Andric       if (I->isAvailable() &&
7460b57cec5SDimitry Andric           (!RequestingModule ||
7470b57cec5SDimitry Andric            I->getModule()->isSubModuleOf(RequestingModule))) {
7480b57cec5SDimitry Andric         // When no requesting module is available, the caller is looking if a
7490b57cec5SDimitry Andric         // header is part a module by only looking into the module map. This is
7500b57cec5SDimitry Andric         // done by warn_uncovered_module_header checks; don't consider textual
7510b57cec5SDimitry Andric         // headers part of it in this mode, otherwise we get misleading warnings
7520b57cec5SDimitry Andric         // that a umbrella header is not including a textual header.
7530b57cec5SDimitry Andric         if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
7540b57cec5SDimitry Andric           continue;
7550b57cec5SDimitry Andric         return false;
7560b57cec5SDimitry Andric       }
7570b57cec5SDimitry Andric     }
7580b57cec5SDimitry Andric     return true;
7590b57cec5SDimitry Andric   }
7600b57cec5SDimitry Andric 
76106c3fb27SDimitry Andric   OptionalDirectoryEntryRef Dir = Header.getDir();
76206c3fb27SDimitry Andric   SmallVector<DirectoryEntryRef, 2> SkippedDirs;
7630b57cec5SDimitry Andric   StringRef DirName = Dir->getName();
7640b57cec5SDimitry Andric 
7650b57cec5SDimitry Andric   auto IsUnavailable = [&](const Module *M) {
7660b57cec5SDimitry Andric     return !M->isAvailable() && (!RequestingModule ||
7670b57cec5SDimitry Andric                                  M->isSubModuleOf(RequestingModule));
7680b57cec5SDimitry Andric   };
7690b57cec5SDimitry Andric 
7700b57cec5SDimitry Andric   // Keep walking up the directory hierarchy, looking for a directory with
7710b57cec5SDimitry Andric   // an umbrella header.
7720b57cec5SDimitry Andric   do {
77306c3fb27SDimitry Andric     auto KnownDir = UmbrellaDirs.find(*Dir);
7740b57cec5SDimitry Andric     if (KnownDir != UmbrellaDirs.end()) {
7750b57cec5SDimitry Andric       Module *Found = KnownDir->second;
7760b57cec5SDimitry Andric       if (IsUnavailable(Found))
7770b57cec5SDimitry Andric         return true;
7780b57cec5SDimitry Andric 
7790b57cec5SDimitry Andric       // Search up the module stack until we find a module with an umbrella
7800b57cec5SDimitry Andric       // directory.
7810b57cec5SDimitry Andric       Module *UmbrellaModule = Found;
78206c3fb27SDimitry Andric       while (!UmbrellaModule->getEffectiveUmbrellaDir() &&
78306c3fb27SDimitry Andric              UmbrellaModule->Parent)
7840b57cec5SDimitry Andric         UmbrellaModule = UmbrellaModule->Parent;
7850b57cec5SDimitry Andric 
7860b57cec5SDimitry Andric       if (UmbrellaModule->InferSubmodules) {
78706c3fb27SDimitry Andric         for (DirectoryEntryRef SkippedDir : llvm::reverse(SkippedDirs)) {
7880b57cec5SDimitry Andric           // Find or create the module that corresponds to this directory name.
7890b57cec5SDimitry Andric           SmallString<32> NameBuf;
7900b57cec5SDimitry Andric           StringRef Name = sanitizeFilenameAsIdentifier(
79106c3fb27SDimitry Andric               llvm::sys::path::stem(SkippedDir.getName()), NameBuf);
7920b57cec5SDimitry Andric           Found = lookupModuleQualified(Name, Found);
7930b57cec5SDimitry Andric           if (!Found)
7940b57cec5SDimitry Andric             return false;
7950b57cec5SDimitry Andric           if (IsUnavailable(Found))
7960b57cec5SDimitry Andric             return true;
7970b57cec5SDimitry Andric         }
7980b57cec5SDimitry Andric 
7990b57cec5SDimitry Andric         // Infer a submodule with the same name as this header file.
8000b57cec5SDimitry Andric         SmallString<32> NameBuf;
8010b57cec5SDimitry Andric         StringRef Name = sanitizeFilenameAsIdentifier(
80206c3fb27SDimitry Andric                            llvm::sys::path::stem(Header.getName()),
8030b57cec5SDimitry Andric                            NameBuf);
8040b57cec5SDimitry Andric         Found = lookupModuleQualified(Name, Found);
8050b57cec5SDimitry Andric         if (!Found)
8060b57cec5SDimitry Andric           return false;
8070b57cec5SDimitry Andric       }
8080b57cec5SDimitry Andric 
8090b57cec5SDimitry Andric       return IsUnavailable(Found);
8100b57cec5SDimitry Andric     }
8110b57cec5SDimitry Andric 
81206c3fb27SDimitry Andric     SkippedDirs.push_back(*Dir);
8130b57cec5SDimitry Andric 
8140b57cec5SDimitry Andric     // Retrieve our parent path.
8150b57cec5SDimitry Andric     DirName = llvm::sys::path::parent_path(DirName);
8160b57cec5SDimitry Andric     if (DirName.empty())
8170b57cec5SDimitry Andric       break;
8180b57cec5SDimitry Andric 
8190b57cec5SDimitry Andric     // Resolve the parent path to a directory entry.
82006c3fb27SDimitry Andric     Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
8210b57cec5SDimitry Andric   } while (Dir);
8220b57cec5SDimitry Andric 
8230b57cec5SDimitry Andric   return false;
8240b57cec5SDimitry Andric }
8250b57cec5SDimitry Andric 
8260b57cec5SDimitry Andric Module *ModuleMap::findModule(StringRef Name) const {
8270b57cec5SDimitry Andric   llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
8280b57cec5SDimitry Andric   if (Known != Modules.end())
8290b57cec5SDimitry Andric     return Known->getValue();
8300b57cec5SDimitry Andric 
8310b57cec5SDimitry Andric   return nullptr;
8320b57cec5SDimitry Andric }
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
8350b57cec5SDimitry Andric                                            Module *Context) const {
8360b57cec5SDimitry Andric   for(; Context; Context = Context->Parent) {
8370b57cec5SDimitry Andric     if (Module *Sub = lookupModuleQualified(Name, Context))
8380b57cec5SDimitry Andric       return Sub;
8390b57cec5SDimitry Andric   }
8400b57cec5SDimitry Andric 
8410b57cec5SDimitry Andric   return findModule(Name);
8420b57cec5SDimitry Andric }
8430b57cec5SDimitry Andric 
8440b57cec5SDimitry Andric Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
8450b57cec5SDimitry Andric   if (!Context)
8460b57cec5SDimitry Andric     return findModule(Name);
8470b57cec5SDimitry Andric 
8480b57cec5SDimitry Andric   return Context->findSubmodule(Name);
8490b57cec5SDimitry Andric }
8500b57cec5SDimitry Andric 
8510b57cec5SDimitry Andric std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
8520b57cec5SDimitry Andric                                                         Module *Parent,
8530b57cec5SDimitry Andric                                                         bool IsFramework,
8540b57cec5SDimitry Andric                                                         bool IsExplicit) {
8550b57cec5SDimitry Andric   // Try to find an existing module with this name.
8560b57cec5SDimitry Andric   if (Module *Sub = lookupModuleQualified(Name, Parent))
8570b57cec5SDimitry Andric     return std::make_pair(Sub, false);
8580b57cec5SDimitry Andric 
8590b57cec5SDimitry Andric   // Create a new module with this name.
8600b57cec5SDimitry Andric   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
8610b57cec5SDimitry Andric                               IsExplicit, NumCreatedModules++);
8620b57cec5SDimitry Andric   if (!Parent) {
8630b57cec5SDimitry Andric     if (LangOpts.CurrentModule == Name)
8640b57cec5SDimitry Andric       SourceModule = Result;
8650b57cec5SDimitry Andric     Modules[Name] = Result;
8660b57cec5SDimitry Andric     ModuleScopeIDs[Result] = CurrentModuleScopeID;
8670b57cec5SDimitry Andric   }
8680b57cec5SDimitry Andric   return std::make_pair(Result, true);
8690b57cec5SDimitry Andric }
8700b57cec5SDimitry Andric 
8710eae32dcSDimitry Andric Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
8720eae32dcSDimitry Andric                                                            Module *Parent) {
8730eae32dcSDimitry Andric   auto *Result = new Module("<global>", Loc, Parent, /*IsFramework*/ false,
8740eae32dcSDimitry Andric                             /*IsExplicit*/ true, NumCreatedModules++);
87506c3fb27SDimitry Andric   Result->Kind = Module::ExplicitGlobalModuleFragment;
8760eae32dcSDimitry Andric   // If the created module isn't owned by a parent, send it to PendingSubmodules
8770eae32dcSDimitry Andric   // to wait for its parent.
8780eae32dcSDimitry Andric   if (!Result->Parent)
8790eae32dcSDimitry Andric     PendingSubmodules.emplace_back(Result);
8800eae32dcSDimitry Andric   return Result;
8810b57cec5SDimitry Andric }
8820b57cec5SDimitry Andric 
8835f757f3fSDimitry Andric Module *
8845f757f3fSDimitry Andric ModuleMap::createImplicitGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
8855f757f3fSDimitry Andric                                                            Module *Parent) {
88606c3fb27SDimitry Andric   assert(Parent && "We should only create an implicit global module fragment "
88706c3fb27SDimitry Andric                    "in a module purview");
88806c3fb27SDimitry Andric   // Note: Here the `IsExplicit` parameter refers to the semantics in clang
88906c3fb27SDimitry Andric   // modules. All the non-explicit submodules in clang modules will be exported
89006c3fb27SDimitry Andric   // too. Here we simplify the implementation by using the concept.
8915f757f3fSDimitry Andric   auto *Result =
8925f757f3fSDimitry Andric       new Module("<implicit global>", Loc, Parent, /*IsFramework=*/false,
8935f757f3fSDimitry Andric                  /*IsExplicit=*/false, NumCreatedModules++);
89406c3fb27SDimitry Andric   Result->Kind = Module::ImplicitGlobalModuleFragment;
89506c3fb27SDimitry Andric   return Result;
89606c3fb27SDimitry Andric }
89706c3fb27SDimitry Andric 
8980b57cec5SDimitry Andric Module *
8990b57cec5SDimitry Andric ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
9000b57cec5SDimitry Andric                                                        SourceLocation Loc) {
9010b57cec5SDimitry Andric   auto *Result =
9020b57cec5SDimitry Andric       new Module("<private>", Loc, Parent, /*IsFramework*/ false,
9030b57cec5SDimitry Andric                  /*IsExplicit*/ true, NumCreatedModules++);
9040b57cec5SDimitry Andric   Result->Kind = Module::PrivateModuleFragment;
9050b57cec5SDimitry Andric   return Result;
9060b57cec5SDimitry Andric }
9070b57cec5SDimitry Andric 
90806c3fb27SDimitry Andric Module *ModuleMap::createModuleUnitWithKind(SourceLocation Loc, StringRef Name,
90906c3fb27SDimitry Andric                                             Module::ModuleKind Kind) {
91006c3fb27SDimitry Andric   auto *Result =
91106c3fb27SDimitry Andric       new Module(Name, Loc, nullptr, /*IsFramework*/ false,
91206c3fb27SDimitry Andric                  /*IsExplicit*/ false, NumCreatedModules++);
91306c3fb27SDimitry Andric   Result->Kind = Kind;
91406c3fb27SDimitry Andric 
91506c3fb27SDimitry Andric   // Reparent any current global module fragment as a submodule of this module.
91606c3fb27SDimitry Andric   for (auto &Submodule : PendingSubmodules) {
91706c3fb27SDimitry Andric     Submodule->setParent(Result);
91806c3fb27SDimitry Andric     Submodule.release(); // now owned by parent
91906c3fb27SDimitry Andric   }
92006c3fb27SDimitry Andric   PendingSubmodules.clear();
92106c3fb27SDimitry Andric   return Result;
92206c3fb27SDimitry Andric }
92306c3fb27SDimitry Andric 
9240b57cec5SDimitry Andric Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
925bdd1243dSDimitry Andric                                                 StringRef Name) {
9260b57cec5SDimitry Andric   assert(LangOpts.CurrentModule == Name && "module name mismatch");
9270b57cec5SDimitry Andric   assert(!Modules[Name] && "redefining existing module");
9280b57cec5SDimitry Andric 
9290b57cec5SDimitry Andric   auto *Result =
93006c3fb27SDimitry Andric       createModuleUnitWithKind(Loc, Name, Module::ModuleInterfaceUnit);
9310b57cec5SDimitry Andric   Modules[Name] = SourceModule = Result;
9320b57cec5SDimitry Andric 
9330b57cec5SDimitry Andric   // Mark the main source file as being within the newly-created module so that
9340b57cec5SDimitry Andric   // declarations and macros are properly visibility-restricted to it.
9355f757f3fSDimitry Andric   auto MainFile = SourceMgr.getFileEntryRefForID(SourceMgr.getMainFileID());
9360b57cec5SDimitry Andric   assert(MainFile && "no input file for module interface");
9375f757f3fSDimitry Andric   Headers[*MainFile].push_back(KnownHeader(Result, PrivateHeader));
9380b57cec5SDimitry Andric 
9390b57cec5SDimitry Andric   return Result;
9400b57cec5SDimitry Andric }
9410b57cec5SDimitry Andric 
94206c3fb27SDimitry Andric Module *ModuleMap::createModuleForImplementationUnit(SourceLocation Loc,
94306c3fb27SDimitry Andric                                                      StringRef Name) {
94406c3fb27SDimitry Andric   assert(LangOpts.CurrentModule == Name && "module name mismatch");
94506c3fb27SDimitry Andric   // The interface for this implementation must exist and be loaded.
94606c3fb27SDimitry Andric   assert(Modules[Name] && Modules[Name]->Kind == Module::ModuleInterfaceUnit &&
94706c3fb27SDimitry Andric          "creating implementation module without an interface");
94806c3fb27SDimitry Andric 
94906c3fb27SDimitry Andric   // Create an entry in the modules map to own the implementation unit module.
95006c3fb27SDimitry Andric   // User module names must not start with a period (so that this cannot clash
95106c3fb27SDimitry Andric   // with any legal user-defined module name).
95206c3fb27SDimitry Andric   StringRef IName = ".ImplementationUnit";
95306c3fb27SDimitry Andric   assert(!Modules[IName] && "multiple implementation units?");
95406c3fb27SDimitry Andric 
95506c3fb27SDimitry Andric   auto *Result =
95606c3fb27SDimitry Andric       createModuleUnitWithKind(Loc, Name, Module::ModuleImplementationUnit);
95706c3fb27SDimitry Andric   Modules[IName] = SourceModule = Result;
95806c3fb27SDimitry Andric 
95906c3fb27SDimitry Andric   // Check that the main file is present.
96006c3fb27SDimitry Andric   assert(SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()) &&
96106c3fb27SDimitry Andric          "no input file for module implementation");
96206c3fb27SDimitry Andric 
96306c3fb27SDimitry Andric   return Result;
96406c3fb27SDimitry Andric }
96506c3fb27SDimitry Andric 
96681ad6265SDimitry Andric Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name,
96781ad6265SDimitry Andric                                     Module::Header H) {
96881ad6265SDimitry Andric   assert(LangOpts.CurrentModule == Name && "module name mismatch");
96981ad6265SDimitry Andric   assert(!Modules[Name] && "redefining existing module");
97081ad6265SDimitry Andric 
97181ad6265SDimitry Andric   auto *Result = new Module(Name, Loc, nullptr, /*IsFramework*/ false,
97281ad6265SDimitry Andric                             /*IsExplicit*/ false, NumCreatedModules++);
97381ad6265SDimitry Andric   Result->Kind = Module::ModuleHeaderUnit;
97481ad6265SDimitry Andric   Modules[Name] = SourceModule = Result;
97581ad6265SDimitry Andric   addHeader(Result, H, NormalHeader);
97681ad6265SDimitry Andric   return Result;
97781ad6265SDimitry Andric }
97881ad6265SDimitry Andric 
9790b57cec5SDimitry Andric /// For a framework module, infer the framework against which we
9800b57cec5SDimitry Andric /// should link.
98106c3fb27SDimitry Andric static void inferFrameworkLink(Module *Mod) {
9820b57cec5SDimitry Andric   assert(Mod->IsFramework && "Can only infer linking for framework modules");
9830b57cec5SDimitry Andric   assert(!Mod->isSubFramework() &&
9840b57cec5SDimitry Andric          "Can only infer linking for top-level frameworks");
9850b57cec5SDimitry Andric 
9861db9f3b2SDimitry Andric   StringRef FrameworkName(Mod->Name);
9871db9f3b2SDimitry Andric   FrameworkName.consume_back("_Private");
9881db9f3b2SDimitry Andric   Mod->LinkLibraries.push_back(Module::LinkLibrary(FrameworkName.str(),
9890b57cec5SDimitry Andric                                                    /*IsFramework=*/true));
9900b57cec5SDimitry Andric }
9910b57cec5SDimitry Andric 
99206c3fb27SDimitry Andric Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
9930b57cec5SDimitry Andric                                         bool IsSystem, Module *Parent) {
9940b57cec5SDimitry Andric   Attributes Attrs;
9950b57cec5SDimitry Andric   Attrs.IsSystem = IsSystem;
9960b57cec5SDimitry Andric   return inferFrameworkModule(FrameworkDir, Attrs, Parent);
9970b57cec5SDimitry Andric }
9980b57cec5SDimitry Andric 
99906c3fb27SDimitry Andric Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
10000b57cec5SDimitry Andric                                         Attributes Attrs, Module *Parent) {
10010b57cec5SDimitry Andric   // Note: as an egregious but useful hack we use the real path here, because
10020b57cec5SDimitry Andric   // we might be looking at an embedded framework that symlinks out to a
10030b57cec5SDimitry Andric   // top-level framework, and we need to infer as if we were naming the
10040b57cec5SDimitry Andric   // top-level framework.
10050b57cec5SDimitry Andric   StringRef FrameworkDirName =
10060b57cec5SDimitry Andric       SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
10070b57cec5SDimitry Andric 
10080b57cec5SDimitry Andric   // In case this is a case-insensitive filesystem, use the canonical
10090b57cec5SDimitry Andric   // directory name as the ModuleName, since modules are case-sensitive.
10100b57cec5SDimitry Andric   // FIXME: we should be able to give a fix-it hint for the correct spelling.
10110b57cec5SDimitry Andric   SmallString<32> ModuleNameStorage;
10120b57cec5SDimitry Andric   StringRef ModuleName = sanitizeFilenameAsIdentifier(
10130b57cec5SDimitry Andric       llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
10140b57cec5SDimitry Andric 
10150b57cec5SDimitry Andric   // Check whether we've already found this module.
10160b57cec5SDimitry Andric   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
10170b57cec5SDimitry Andric     return Mod;
10180b57cec5SDimitry Andric 
10190b57cec5SDimitry Andric   FileManager &FileMgr = SourceMgr.getFileManager();
10200b57cec5SDimitry Andric 
10210b57cec5SDimitry Andric   // If the framework has a parent path from which we're allowed to infer
10220b57cec5SDimitry Andric   // a framework module, do so.
1023*0fca6ea1SDimitry Andric   FileID ModuleMapFID;
10240b57cec5SDimitry Andric   if (!Parent) {
10250b57cec5SDimitry Andric     // Determine whether we're allowed to infer a module map.
10260b57cec5SDimitry Andric     bool canInfer = false;
10270b57cec5SDimitry Andric     if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
10280b57cec5SDimitry Andric       // Figure out the parent path.
10290b57cec5SDimitry Andric       StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
103006c3fb27SDimitry Andric       if (auto ParentDir = FileMgr.getOptionalDirectoryRef(Parent)) {
10310b57cec5SDimitry Andric         // Check whether we have already looked into the parent directory
10320b57cec5SDimitry Andric         // for a module map.
10330b57cec5SDimitry Andric         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
1034a7dea167SDimitry Andric           inferred = InferredDirectories.find(*ParentDir);
10350b57cec5SDimitry Andric         if (inferred == InferredDirectories.end()) {
10360b57cec5SDimitry Andric           // We haven't looked here before. Load a module map, if there is
10370b57cec5SDimitry Andric           // one.
10385f757f3fSDimitry Andric           bool IsFrameworkDir = Parent.ends_with(".framework");
103906c3fb27SDimitry Andric           if (OptionalFileEntryRef ModMapFile =
1040a7dea167SDimitry Andric                   HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) {
104106c3fb27SDimitry Andric             parseModuleMapFile(*ModMapFile, Attrs.IsSystem, *ParentDir);
1042a7dea167SDimitry Andric             inferred = InferredDirectories.find(*ParentDir);
10430b57cec5SDimitry Andric           }
10440b57cec5SDimitry Andric 
10450b57cec5SDimitry Andric           if (inferred == InferredDirectories.end())
10460b57cec5SDimitry Andric             inferred = InferredDirectories.insert(
1047a7dea167SDimitry Andric                          std::make_pair(*ParentDir, InferredDirectory())).first;
10480b57cec5SDimitry Andric         }
10490b57cec5SDimitry Andric 
10500b57cec5SDimitry Andric         if (inferred->second.InferModules) {
10510b57cec5SDimitry Andric           // We're allowed to infer for this directory, but make sure it's okay
10520b57cec5SDimitry Andric           // to infer this particular module.
10530b57cec5SDimitry Andric           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
1054349cc55cSDimitry Andric           canInfer =
1055349cc55cSDimitry Andric               !llvm::is_contained(inferred->second.ExcludedModules, Name);
10560b57cec5SDimitry Andric 
10570b57cec5SDimitry Andric           Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
10580b57cec5SDimitry Andric           Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
10590b57cec5SDimitry Andric           Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
10600b57cec5SDimitry Andric           Attrs.NoUndeclaredIncludes |=
10610b57cec5SDimitry Andric               inferred->second.Attrs.NoUndeclaredIncludes;
1062*0fca6ea1SDimitry Andric           ModuleMapFID = inferred->second.ModuleMapFID;
10630b57cec5SDimitry Andric         }
10640b57cec5SDimitry Andric       }
10650b57cec5SDimitry Andric     }
10660b57cec5SDimitry Andric 
10670b57cec5SDimitry Andric     // If we're not allowed to infer a framework module, don't.
10680b57cec5SDimitry Andric     if (!canInfer)
10690b57cec5SDimitry Andric       return nullptr;
1070bdd1243dSDimitry Andric   } else {
1071*0fca6ea1SDimitry Andric     ModuleMapFID = getModuleMapFileIDForUniquing(Parent);
1072bdd1243dSDimitry Andric   }
10730b57cec5SDimitry Andric 
10740b57cec5SDimitry Andric   // Look for an umbrella header.
107506c3fb27SDimitry Andric   SmallString<128> UmbrellaName = FrameworkDir.getName();
10760b57cec5SDimitry Andric   llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
1077bdd1243dSDimitry Andric   auto UmbrellaHeader = FileMgr.getOptionalFileRef(UmbrellaName);
10780b57cec5SDimitry Andric 
10790b57cec5SDimitry Andric   // FIXME: If there's no umbrella header, we could probably scan the
10800b57cec5SDimitry Andric   // framework to load *everything*. But, it's not clear that this is a good
10810b57cec5SDimitry Andric   // idea.
10820b57cec5SDimitry Andric   if (!UmbrellaHeader)
10830b57cec5SDimitry Andric     return nullptr;
10840b57cec5SDimitry Andric 
10850b57cec5SDimitry Andric   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
10860b57cec5SDimitry Andric                               /*IsFramework=*/true, /*IsExplicit=*/false,
10870b57cec5SDimitry Andric                               NumCreatedModules++);
1088*0fca6ea1SDimitry Andric   InferredModuleAllowedBy[Result] = ModuleMapFID;
10890b57cec5SDimitry Andric   Result->IsInferred = true;
10900b57cec5SDimitry Andric   if (!Parent) {
10910b57cec5SDimitry Andric     if (LangOpts.CurrentModule == ModuleName)
10920b57cec5SDimitry Andric       SourceModule = Result;
10930b57cec5SDimitry Andric     Modules[ModuleName] = Result;
10940b57cec5SDimitry Andric     ModuleScopeIDs[Result] = CurrentModuleScopeID;
10950b57cec5SDimitry Andric   }
10960b57cec5SDimitry Andric 
10970b57cec5SDimitry Andric   Result->IsSystem |= Attrs.IsSystem;
10980b57cec5SDimitry Andric   Result->IsExternC |= Attrs.IsExternC;
10990b57cec5SDimitry Andric   Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
11000b57cec5SDimitry Andric   Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
11010b57cec5SDimitry Andric   Result->Directory = FrameworkDir;
11020b57cec5SDimitry Andric 
1103fe6060f1SDimitry Andric   // Chop off the first framework bit, as that is implied.
1104fe6060f1SDimitry Andric   StringRef RelativePath = UmbrellaName.str().substr(
1105fe6060f1SDimitry Andric       Result->getTopLevelModule()->Directory->getName().size());
1106fe6060f1SDimitry Andric   RelativePath = llvm::sys::path::relative_path(RelativePath);
1107fe6060f1SDimitry Andric 
11080b57cec5SDimitry Andric   // umbrella header "umbrella-header-name"
110906c3fb27SDimitry Andric   setUmbrellaHeaderAsWritten(Result, *UmbrellaHeader, ModuleName + ".h",
111006c3fb27SDimitry Andric                              RelativePath);
11110b57cec5SDimitry Andric 
11120b57cec5SDimitry Andric   // export *
11130b57cec5SDimitry Andric   Result->Exports.push_back(Module::ExportDecl(nullptr, true));
11140b57cec5SDimitry Andric 
11150b57cec5SDimitry Andric   // module * { export * }
11160b57cec5SDimitry Andric   Result->InferSubmodules = true;
11170b57cec5SDimitry Andric   Result->InferExportWildcard = true;
11180b57cec5SDimitry Andric 
11190b57cec5SDimitry Andric   // Look for subframeworks.
11200b57cec5SDimitry Andric   std::error_code EC;
112106c3fb27SDimitry Andric   SmallString<128> SubframeworksDirName = FrameworkDir.getName();
11220b57cec5SDimitry Andric   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
11230b57cec5SDimitry Andric   llvm::sys::path::native(SubframeworksDirName);
11240b57cec5SDimitry Andric   llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
11250b57cec5SDimitry Andric   for (llvm::vfs::directory_iterator
11260b57cec5SDimitry Andric            Dir = FS.dir_begin(SubframeworksDirName, EC),
11270b57cec5SDimitry Andric            DirEnd;
11280b57cec5SDimitry Andric        Dir != DirEnd && !EC; Dir.increment(EC)) {
11295f757f3fSDimitry Andric     if (!StringRef(Dir->path()).ends_with(".framework"))
11300b57cec5SDimitry Andric       continue;
11310b57cec5SDimitry Andric 
113206c3fb27SDimitry Andric     if (auto SubframeworkDir = FileMgr.getOptionalDirectoryRef(Dir->path())) {
11330b57cec5SDimitry Andric       // Note: as an egregious but useful hack, we use the real path here and
11340b57cec5SDimitry Andric       // check whether it is actually a subdirectory of the parent directory.
11350b57cec5SDimitry Andric       // This will not be the case if the 'subframework' is actually a symlink
11360b57cec5SDimitry Andric       // out to a top-level framework.
1137a7dea167SDimitry Andric       StringRef SubframeworkDirName =
1138a7dea167SDimitry Andric           FileMgr.getCanonicalName(*SubframeworkDir);
11390b57cec5SDimitry Andric       bool FoundParent = false;
11400b57cec5SDimitry Andric       do {
11410b57cec5SDimitry Andric         // Get the parent directory name.
11420b57cec5SDimitry Andric         SubframeworkDirName
11430b57cec5SDimitry Andric           = llvm::sys::path::parent_path(SubframeworkDirName);
11440b57cec5SDimitry Andric         if (SubframeworkDirName.empty())
11450b57cec5SDimitry Andric           break;
11460b57cec5SDimitry Andric 
1147a7dea167SDimitry Andric         if (auto SubDir = FileMgr.getDirectory(SubframeworkDirName)) {
1148a7dea167SDimitry Andric           if (*SubDir == FrameworkDir) {
11490b57cec5SDimitry Andric             FoundParent = true;
11500b57cec5SDimitry Andric             break;
11510b57cec5SDimitry Andric           }
1152a7dea167SDimitry Andric         }
11530b57cec5SDimitry Andric       } while (true);
11540b57cec5SDimitry Andric 
11550b57cec5SDimitry Andric       if (!FoundParent)
11560b57cec5SDimitry Andric         continue;
11570b57cec5SDimitry Andric 
11580b57cec5SDimitry Andric       // FIXME: Do we want to warn about subframeworks without umbrella headers?
1159a7dea167SDimitry Andric       inferFrameworkModule(*SubframeworkDir, Attrs, Result);
11600b57cec5SDimitry Andric     }
11610b57cec5SDimitry Andric   }
11620b57cec5SDimitry Andric 
11630b57cec5SDimitry Andric   // If the module is a top-level framework, automatically link against the
11640b57cec5SDimitry Andric   // framework.
116506c3fb27SDimitry Andric   if (!Result->isSubFramework())
116606c3fb27SDimitry Andric     inferFrameworkLink(Result);
11670b57cec5SDimitry Andric 
11680b57cec5SDimitry Andric   return Result;
11690b57cec5SDimitry Andric }
11700b57cec5SDimitry Andric 
11710b57cec5SDimitry Andric Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
11720b57cec5SDimitry Andric                                         Module *ShadowingModule) {
11730b57cec5SDimitry Andric 
11740b57cec5SDimitry Andric   // Create a new module with this name.
11750b57cec5SDimitry Andric   Module *Result =
11760b57cec5SDimitry Andric       new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
11770b57cec5SDimitry Andric                  /*IsExplicit=*/false, NumCreatedModules++);
11780b57cec5SDimitry Andric   Result->ShadowingModule = ShadowingModule;
11795ffd83dbSDimitry Andric   Result->markUnavailable(/*Unimportable*/true);
11800b57cec5SDimitry Andric   ModuleScopeIDs[Result] = CurrentModuleScopeID;
11810b57cec5SDimitry Andric   ShadowModules.push_back(Result);
11820b57cec5SDimitry Andric 
11830b57cec5SDimitry Andric   return Result;
11840b57cec5SDimitry Andric }
11850b57cec5SDimitry Andric 
118606c3fb27SDimitry Andric void ModuleMap::setUmbrellaHeaderAsWritten(
1187bdd1243dSDimitry Andric     Module *Mod, FileEntryRef UmbrellaHeader, const Twine &NameAsWritten,
1188fe6060f1SDimitry Andric     const Twine &PathRelativeToRootModuleDirectory) {
11890b57cec5SDimitry Andric   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
119006c3fb27SDimitry Andric   Mod->Umbrella = UmbrellaHeader;
11910b57cec5SDimitry Andric   Mod->UmbrellaAsWritten = NameAsWritten.str();
1192fe6060f1SDimitry Andric   Mod->UmbrellaRelativeToRootModuleDirectory =
1193fe6060f1SDimitry Andric       PathRelativeToRootModuleDirectory.str();
1194bdd1243dSDimitry Andric   UmbrellaDirs[UmbrellaHeader.getDir()] = Mod;
11950b57cec5SDimitry Andric 
11960b57cec5SDimitry Andric   // Notify callbacks that we just added a new header.
11970b57cec5SDimitry Andric   for (const auto &Cb : Callbacks)
119806c3fb27SDimitry Andric     Cb->moduleMapAddUmbrellaHeader(UmbrellaHeader);
11990b57cec5SDimitry Andric }
12000b57cec5SDimitry Andric 
120106c3fb27SDimitry Andric void ModuleMap::setUmbrellaDirAsWritten(
120206c3fb27SDimitry Andric     Module *Mod, DirectoryEntryRef UmbrellaDir, const Twine &NameAsWritten,
1203fe6060f1SDimitry Andric     const Twine &PathRelativeToRootModuleDirectory) {
1204fe6060f1SDimitry Andric   Mod->Umbrella = UmbrellaDir;
12050b57cec5SDimitry Andric   Mod->UmbrellaAsWritten = NameAsWritten.str();
1206fe6060f1SDimitry Andric   Mod->UmbrellaRelativeToRootModuleDirectory =
1207fe6060f1SDimitry Andric       PathRelativeToRootModuleDirectory.str();
12080b57cec5SDimitry Andric   UmbrellaDirs[UmbrellaDir] = Mod;
12090b57cec5SDimitry Andric }
12100b57cec5SDimitry Andric 
12110b57cec5SDimitry Andric void ModuleMap::addUnresolvedHeader(Module *Mod,
12120b57cec5SDimitry Andric                                     Module::UnresolvedHeaderDirective Header,
12130b57cec5SDimitry Andric                                     bool &NeedsFramework) {
12140b57cec5SDimitry Andric   // If there is a builtin counterpart to this file, add it now so it can
12150b57cec5SDimitry Andric   // wrap the system header.
12160b57cec5SDimitry Andric   if (resolveAsBuiltinHeader(Mod, Header)) {
12170b57cec5SDimitry Andric     // If we have both a builtin and system version of the file, the
12180b57cec5SDimitry Andric     // builtin version may want to inject macros into the system header, so
12190b57cec5SDimitry Andric     // force the system header to be treated as a textual header in this
12200b57cec5SDimitry Andric     // case.
12210b57cec5SDimitry Andric     Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
12220b57cec5SDimitry Andric         headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
12230b57cec5SDimitry Andric     Header.HasBuiltinHeader = true;
12240b57cec5SDimitry Andric   }
12250b57cec5SDimitry Andric 
12260b57cec5SDimitry Andric   // If possible, don't stat the header until we need to. This requires the
12270b57cec5SDimitry Andric   // user to have provided us with some stat information about the file.
12280b57cec5SDimitry Andric   // FIXME: Add support for lazily stat'ing umbrella headers and excluded
12290b57cec5SDimitry Andric   // headers.
12300b57cec5SDimitry Andric   if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
12310b57cec5SDimitry Andric       Header.Kind != Module::HK_Excluded) {
12320b57cec5SDimitry Andric     // We expect more variation in mtime than size, so if we're given both,
12330b57cec5SDimitry Andric     // use the mtime as the key.
12340b57cec5SDimitry Andric     if (Header.ModTime)
12350b57cec5SDimitry Andric       LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
12360b57cec5SDimitry Andric     else
12370b57cec5SDimitry Andric       LazyHeadersBySize[*Header.Size].push_back(Mod);
12380b57cec5SDimitry Andric     Mod->UnresolvedHeaders.push_back(Header);
12390b57cec5SDimitry Andric     return;
12400b57cec5SDimitry Andric   }
12410b57cec5SDimitry Andric 
12420b57cec5SDimitry Andric   // We don't have stat information or can't defer looking this file up.
12430b57cec5SDimitry Andric   // Perform the lookup now.
12440b57cec5SDimitry Andric   resolveHeader(Mod, Header, NeedsFramework);
12450b57cec5SDimitry Andric }
12460b57cec5SDimitry Andric 
12470b57cec5SDimitry Andric void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
12480b57cec5SDimitry Andric   auto BySize = LazyHeadersBySize.find(File->getSize());
12490b57cec5SDimitry Andric   if (BySize != LazyHeadersBySize.end()) {
12500b57cec5SDimitry Andric     for (auto *M : BySize->second)
125181ad6265SDimitry Andric       resolveHeaderDirectives(M, File);
12520b57cec5SDimitry Andric     LazyHeadersBySize.erase(BySize);
12530b57cec5SDimitry Andric   }
12540b57cec5SDimitry Andric 
12550b57cec5SDimitry Andric   auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
12560b57cec5SDimitry Andric   if (ByModTime != LazyHeadersByModTime.end()) {
12570b57cec5SDimitry Andric     for (auto *M : ByModTime->second)
125881ad6265SDimitry Andric       resolveHeaderDirectives(M, File);
12590b57cec5SDimitry Andric     LazyHeadersByModTime.erase(ByModTime);
12600b57cec5SDimitry Andric   }
12610b57cec5SDimitry Andric }
12620b57cec5SDimitry Andric 
126381ad6265SDimitry Andric void ModuleMap::resolveHeaderDirectives(
1264bdd1243dSDimitry Andric     Module *Mod, std::optional<const FileEntry *> File) const {
12650b57cec5SDimitry Andric   bool NeedsFramework = false;
126681ad6265SDimitry Andric   SmallVector<Module::UnresolvedHeaderDirective, 1> NewHeaders;
1267bdd1243dSDimitry Andric   const auto Size = File ? (*File)->getSize() : 0;
1268bdd1243dSDimitry Andric   const auto ModTime = File ? (*File)->getModificationTime() : 0;
126981ad6265SDimitry Andric 
127081ad6265SDimitry Andric   for (auto &Header : Mod->UnresolvedHeaders) {
127181ad6265SDimitry Andric     if (File && ((Header.ModTime && Header.ModTime != ModTime) ||
127281ad6265SDimitry Andric                  (Header.Size && Header.Size != Size)))
127381ad6265SDimitry Andric       NewHeaders.push_back(Header);
127481ad6265SDimitry Andric     else
12750b57cec5SDimitry Andric       // This operation is logically const; we're just changing how we represent
12760b57cec5SDimitry Andric       // the header information for this file.
12770b57cec5SDimitry Andric       const_cast<ModuleMap *>(this)->resolveHeader(Mod, Header, NeedsFramework);
127881ad6265SDimitry Andric   }
127981ad6265SDimitry Andric   Mod->UnresolvedHeaders.swap(NewHeaders);
12800b57cec5SDimitry Andric }
12810b57cec5SDimitry Andric 
12820b57cec5SDimitry Andric void ModuleMap::addHeader(Module *Mod, Module::Header Header,
12830b57cec5SDimitry Andric                           ModuleHeaderRole Role, bool Imported) {
12840b57cec5SDimitry Andric   KnownHeader KH(Mod, Role);
12850b57cec5SDimitry Andric 
12860b57cec5SDimitry Andric   // Only add each header to the headers list once.
12870b57cec5SDimitry Andric   // FIXME: Should we diagnose if a header is listed twice in the
12880b57cec5SDimitry Andric   // same module definition?
12890b57cec5SDimitry Andric   auto &HeaderList = Headers[Header.Entry];
1290349cc55cSDimitry Andric   if (llvm::is_contained(HeaderList, KH))
12910b57cec5SDimitry Andric     return;
12920b57cec5SDimitry Andric 
12930b57cec5SDimitry Andric   HeaderList.push_back(KH);
12940b57cec5SDimitry Andric   Mod->Headers[headerRoleToKind(Role)].push_back(Header);
12950b57cec5SDimitry Andric 
12965f757f3fSDimitry Andric   bool isCompilingModuleHeader = Mod->isForBuilding(LangOpts);
12970b57cec5SDimitry Andric   if (!Imported || isCompilingModuleHeader) {
12980b57cec5SDimitry Andric     // When we import HeaderFileInfo, the external source is expected to
12990b57cec5SDimitry Andric     // set the isModuleHeader flag itself.
13000b57cec5SDimitry Andric     HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
13010b57cec5SDimitry Andric                                     isCompilingModuleHeader);
13020b57cec5SDimitry Andric   }
13030b57cec5SDimitry Andric 
13040b57cec5SDimitry Andric   // Notify callbacks that we just added a new header.
13050b57cec5SDimitry Andric   for (const auto &Cb : Callbacks)
130606c3fb27SDimitry Andric     Cb->moduleMapAddHeader(Header.Entry.getName());
13070b57cec5SDimitry Andric }
13080b57cec5SDimitry Andric 
1309*0fca6ea1SDimitry Andric FileID ModuleMap::getContainingModuleMapFileID(const Module *Module) const {
13100b57cec5SDimitry Andric   if (Module->DefinitionLoc.isInvalid())
1311*0fca6ea1SDimitry Andric     return {};
13120b57cec5SDimitry Andric 
1313*0fca6ea1SDimitry Andric   return SourceMgr.getFileID(Module->DefinitionLoc);
13140b57cec5SDimitry Andric }
13150b57cec5SDimitry Andric 
1316bdd1243dSDimitry Andric OptionalFileEntryRef
1317*0fca6ea1SDimitry Andric ModuleMap::getContainingModuleMapFile(const Module *Module) const {
1318*0fca6ea1SDimitry Andric   return SourceMgr.getFileEntryRefForID(getContainingModuleMapFileID(Module));
1319*0fca6ea1SDimitry Andric }
1320*0fca6ea1SDimitry Andric 
1321*0fca6ea1SDimitry Andric FileID ModuleMap::getModuleMapFileIDForUniquing(const Module *M) const {
13220b57cec5SDimitry Andric   if (M->IsInferred) {
13230b57cec5SDimitry Andric     assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
13245f757f3fSDimitry Andric     return InferredModuleAllowedBy.find(M)->second;
13250b57cec5SDimitry Andric   }
1326*0fca6ea1SDimitry Andric   return getContainingModuleMapFileID(M);
13270b57cec5SDimitry Andric }
13280b57cec5SDimitry Andric 
1329*0fca6ea1SDimitry Andric OptionalFileEntryRef
1330*0fca6ea1SDimitry Andric ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
1331*0fca6ea1SDimitry Andric   return SourceMgr.getFileEntryRefForID(getModuleMapFileIDForUniquing(M));
1332*0fca6ea1SDimitry Andric }
1333*0fca6ea1SDimitry Andric 
1334*0fca6ea1SDimitry Andric void ModuleMap::setInferredModuleAllowedBy(Module *M, FileID ModMapFID) {
13350b57cec5SDimitry Andric   assert(M->IsInferred && "module not inferred");
1336*0fca6ea1SDimitry Andric   InferredModuleAllowedBy[M] = ModMapFID;
13370b57cec5SDimitry Andric }
13380b57cec5SDimitry Andric 
1339bdd1243dSDimitry Andric std::error_code
1340bdd1243dSDimitry Andric ModuleMap::canonicalizeModuleMapPath(SmallVectorImpl<char> &Path) {
1341bdd1243dSDimitry Andric   StringRef Dir = llvm::sys::path::parent_path({Path.data(), Path.size()});
1342bdd1243dSDimitry Andric 
1343bdd1243dSDimitry Andric   // Do not canonicalize within the framework; the module map parser expects
1344bdd1243dSDimitry Andric   // Modules/ not Versions/A/Modules.
1345bdd1243dSDimitry Andric   if (llvm::sys::path::filename(Dir) == "Modules") {
1346bdd1243dSDimitry Andric     StringRef Parent = llvm::sys::path::parent_path(Dir);
13475f757f3fSDimitry Andric     if (Parent.ends_with(".framework"))
1348bdd1243dSDimitry Andric       Dir = Parent;
1349bdd1243dSDimitry Andric   }
1350bdd1243dSDimitry Andric 
1351bdd1243dSDimitry Andric   FileManager &FM = SourceMgr.getFileManager();
135206c3fb27SDimitry Andric   auto DirEntry = FM.getDirectoryRef(Dir.empty() ? "." : Dir);
1353bdd1243dSDimitry Andric   if (!DirEntry)
135406c3fb27SDimitry Andric     return llvm::errorToErrorCode(DirEntry.takeError());
1355bdd1243dSDimitry Andric 
1356bdd1243dSDimitry Andric   // Canonicalize the directory.
1357bdd1243dSDimitry Andric   StringRef CanonicalDir = FM.getCanonicalName(*DirEntry);
135806c3fb27SDimitry Andric   if (CanonicalDir != Dir)
135906c3fb27SDimitry Andric     llvm::sys::path::replace_path_prefix(Path, Dir, CanonicalDir);
1360bdd1243dSDimitry Andric 
1361bdd1243dSDimitry Andric   // In theory, the filename component should also be canonicalized if it
1362bdd1243dSDimitry Andric   // on a case-insensitive filesystem. However, the extra canonicalization is
1363bdd1243dSDimitry Andric   // expensive and if clang looked up the filename it will always be lowercase.
1364bdd1243dSDimitry Andric 
1365bdd1243dSDimitry Andric   // Remove ., remove redundant separators, and switch to native separators.
1366bdd1243dSDimitry Andric   // This is needed for separators between CanonicalDir and the filename.
1367bdd1243dSDimitry Andric   llvm::sys::path::remove_dots(Path);
1368bdd1243dSDimitry Andric 
1369bdd1243dSDimitry Andric   return std::error_code();
1370bdd1243dSDimitry Andric }
1371bdd1243dSDimitry Andric 
13725ffd83dbSDimitry Andric void ModuleMap::addAdditionalModuleMapFile(const Module *M,
13735f757f3fSDimitry Andric                                            FileEntryRef ModuleMap) {
13745ffd83dbSDimitry Andric   AdditionalModMaps[M].insert(ModuleMap);
13755ffd83dbSDimitry Andric }
13765ffd83dbSDimitry Andric 
13770b57cec5SDimitry Andric LLVM_DUMP_METHOD void ModuleMap::dump() {
13780b57cec5SDimitry Andric   llvm::errs() << "Modules:";
13790b57cec5SDimitry Andric   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
13800b57cec5SDimitry Andric                                         MEnd = Modules.end();
13810b57cec5SDimitry Andric        M != MEnd; ++M)
13820b57cec5SDimitry Andric     M->getValue()->print(llvm::errs(), 2);
13830b57cec5SDimitry Andric 
13840b57cec5SDimitry Andric   llvm::errs() << "Headers:";
13850b57cec5SDimitry Andric   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
13860b57cec5SDimitry Andric        H != HEnd; ++H) {
13875f757f3fSDimitry Andric     llvm::errs() << "  \"" << H->first.getName() << "\" -> ";
13880b57cec5SDimitry Andric     for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
13890b57cec5SDimitry Andric                                                       E = H->second.end();
13900b57cec5SDimitry Andric          I != E; ++I) {
13910b57cec5SDimitry Andric       if (I != H->second.begin())
13920b57cec5SDimitry Andric         llvm::errs() << ",";
13930b57cec5SDimitry Andric       llvm::errs() << I->getModule()->getFullModuleName();
13940b57cec5SDimitry Andric     }
13950b57cec5SDimitry Andric     llvm::errs() << "\n";
13960b57cec5SDimitry Andric   }
13970b57cec5SDimitry Andric }
13980b57cec5SDimitry Andric 
13990b57cec5SDimitry Andric bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
14000b57cec5SDimitry Andric   auto Unresolved = std::move(Mod->UnresolvedExports);
14010b57cec5SDimitry Andric   Mod->UnresolvedExports.clear();
14020b57cec5SDimitry Andric   for (auto &UE : Unresolved) {
14030b57cec5SDimitry Andric     Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
14040b57cec5SDimitry Andric     if (Export.getPointer() || Export.getInt())
14050b57cec5SDimitry Andric       Mod->Exports.push_back(Export);
14060b57cec5SDimitry Andric     else
14070b57cec5SDimitry Andric       Mod->UnresolvedExports.push_back(UE);
14080b57cec5SDimitry Andric   }
14090b57cec5SDimitry Andric   return !Mod->UnresolvedExports.empty();
14100b57cec5SDimitry Andric }
14110b57cec5SDimitry Andric 
14120b57cec5SDimitry Andric bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
14135f757f3fSDimitry Andric   auto *Top = Mod->getTopLevelModule();
14145f757f3fSDimitry Andric   auto Unresolved = std::move(Top->UnresolvedDirectUses);
14155f757f3fSDimitry Andric   Top->UnresolvedDirectUses.clear();
14160b57cec5SDimitry Andric   for (auto &UDU : Unresolved) {
14175f757f3fSDimitry Andric     Module *DirectUse = resolveModuleId(UDU, Top, Complain);
14180b57cec5SDimitry Andric     if (DirectUse)
14195f757f3fSDimitry Andric       Top->DirectUses.push_back(DirectUse);
14200b57cec5SDimitry Andric     else
14215f757f3fSDimitry Andric       Top->UnresolvedDirectUses.push_back(UDU);
14220b57cec5SDimitry Andric   }
14235f757f3fSDimitry Andric   return !Top->UnresolvedDirectUses.empty();
14240b57cec5SDimitry Andric }
14250b57cec5SDimitry Andric 
14260b57cec5SDimitry Andric bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
14270b57cec5SDimitry Andric   auto Unresolved = std::move(Mod->UnresolvedConflicts);
14280b57cec5SDimitry Andric   Mod->UnresolvedConflicts.clear();
14290b57cec5SDimitry Andric   for (auto &UC : Unresolved) {
14300b57cec5SDimitry Andric     if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
14310b57cec5SDimitry Andric       Module::Conflict Conflict;
14320b57cec5SDimitry Andric       Conflict.Other = OtherMod;
14330b57cec5SDimitry Andric       Conflict.Message = UC.Message;
14340b57cec5SDimitry Andric       Mod->Conflicts.push_back(Conflict);
14350b57cec5SDimitry Andric     } else
14360b57cec5SDimitry Andric       Mod->UnresolvedConflicts.push_back(UC);
14370b57cec5SDimitry Andric   }
14380b57cec5SDimitry Andric   return !Mod->UnresolvedConflicts.empty();
14390b57cec5SDimitry Andric }
14400b57cec5SDimitry Andric 
14410b57cec5SDimitry Andric //----------------------------------------------------------------------------//
14420b57cec5SDimitry Andric // Module map file parser
14430b57cec5SDimitry Andric //----------------------------------------------------------------------------//
14440b57cec5SDimitry Andric 
14450b57cec5SDimitry Andric namespace clang {
14460b57cec5SDimitry Andric 
14470b57cec5SDimitry Andric   /// A token in a module map file.
14480b57cec5SDimitry Andric   struct MMToken {
14490b57cec5SDimitry Andric     enum TokenKind {
14500b57cec5SDimitry Andric       Comma,
14510b57cec5SDimitry Andric       ConfigMacros,
14520b57cec5SDimitry Andric       Conflict,
14530b57cec5SDimitry Andric       EndOfFile,
14540b57cec5SDimitry Andric       HeaderKeyword,
14550b57cec5SDimitry Andric       Identifier,
14560b57cec5SDimitry Andric       Exclaim,
14570b57cec5SDimitry Andric       ExcludeKeyword,
14580b57cec5SDimitry Andric       ExplicitKeyword,
14590b57cec5SDimitry Andric       ExportKeyword,
14600b57cec5SDimitry Andric       ExportAsKeyword,
14610b57cec5SDimitry Andric       ExternKeyword,
14620b57cec5SDimitry Andric       FrameworkKeyword,
14630b57cec5SDimitry Andric       LinkKeyword,
14640b57cec5SDimitry Andric       ModuleKeyword,
14650b57cec5SDimitry Andric       Period,
14660b57cec5SDimitry Andric       PrivateKeyword,
14670b57cec5SDimitry Andric       UmbrellaKeyword,
14680b57cec5SDimitry Andric       UseKeyword,
14690b57cec5SDimitry Andric       RequiresKeyword,
14700b57cec5SDimitry Andric       Star,
14710b57cec5SDimitry Andric       StringLiteral,
14720b57cec5SDimitry Andric       IntegerLiteral,
14730b57cec5SDimitry Andric       TextualKeyword,
14740b57cec5SDimitry Andric       LBrace,
14750b57cec5SDimitry Andric       RBrace,
14760b57cec5SDimitry Andric       LSquare,
14770b57cec5SDimitry Andric       RSquare
14780b57cec5SDimitry Andric     } Kind;
14790b57cec5SDimitry Andric 
1480fe6060f1SDimitry Andric     SourceLocation::UIntTy Location;
14810b57cec5SDimitry Andric     unsigned StringLength;
14820b57cec5SDimitry Andric     union {
14830b57cec5SDimitry Andric       // If Kind != IntegerLiteral.
14840b57cec5SDimitry Andric       const char *StringData;
14850b57cec5SDimitry Andric 
14860b57cec5SDimitry Andric       // If Kind == IntegerLiteral.
14870b57cec5SDimitry Andric       uint64_t IntegerValue;
14880b57cec5SDimitry Andric     };
14890b57cec5SDimitry Andric 
14900b57cec5SDimitry Andric     void clear() {
14910b57cec5SDimitry Andric       Kind = EndOfFile;
14920b57cec5SDimitry Andric       Location = 0;
14930b57cec5SDimitry Andric       StringLength = 0;
14940b57cec5SDimitry Andric       StringData = nullptr;
14950b57cec5SDimitry Andric     }
14960b57cec5SDimitry Andric 
14970b57cec5SDimitry Andric     bool is(TokenKind K) const { return Kind == K; }
14980b57cec5SDimitry Andric 
14990b57cec5SDimitry Andric     SourceLocation getLocation() const {
15000b57cec5SDimitry Andric       return SourceLocation::getFromRawEncoding(Location);
15010b57cec5SDimitry Andric     }
15020b57cec5SDimitry Andric 
15030b57cec5SDimitry Andric     uint64_t getInteger() const {
15040b57cec5SDimitry Andric       return Kind == IntegerLiteral ? IntegerValue : 0;
15050b57cec5SDimitry Andric     }
15060b57cec5SDimitry Andric 
15070b57cec5SDimitry Andric     StringRef getString() const {
15080b57cec5SDimitry Andric       return Kind == IntegerLiteral ? StringRef()
15090b57cec5SDimitry Andric                                     : StringRef(StringData, StringLength);
15100b57cec5SDimitry Andric     }
15110b57cec5SDimitry Andric   };
15120b57cec5SDimitry Andric 
15130b57cec5SDimitry Andric   class ModuleMapParser {
15140b57cec5SDimitry Andric     Lexer &L;
15150b57cec5SDimitry Andric     SourceManager &SourceMgr;
15160b57cec5SDimitry Andric 
15170b57cec5SDimitry Andric     /// Default target information, used only for string literal
15180b57cec5SDimitry Andric     /// parsing.
15190b57cec5SDimitry Andric     const TargetInfo *Target;
15200b57cec5SDimitry Andric 
15210b57cec5SDimitry Andric     DiagnosticsEngine &Diags;
15220b57cec5SDimitry Andric     ModuleMap &Map;
15230b57cec5SDimitry Andric 
15240b57cec5SDimitry Andric     /// The current module map file.
1525*0fca6ea1SDimitry Andric     FileID ModuleMapFID;
15260b57cec5SDimitry Andric 
15270b57cec5SDimitry Andric     /// Source location of most recent parsed module declaration
15280b57cec5SDimitry Andric     SourceLocation CurrModuleDeclLoc;
15290b57cec5SDimitry Andric 
15300b57cec5SDimitry Andric     /// The directory that file names in this module map file should
15310b57cec5SDimitry Andric     /// be resolved relative to.
153206c3fb27SDimitry Andric     DirectoryEntryRef Directory;
15330b57cec5SDimitry Andric 
15340b57cec5SDimitry Andric     /// Whether this module map is in a system header directory.
15350b57cec5SDimitry Andric     bool IsSystem;
15360b57cec5SDimitry Andric 
15370b57cec5SDimitry Andric     /// Whether an error occurred.
15380b57cec5SDimitry Andric     bool HadError = false;
15390b57cec5SDimitry Andric 
15400b57cec5SDimitry Andric     /// Stores string data for the various string literals referenced
15410b57cec5SDimitry Andric     /// during parsing.
15420b57cec5SDimitry Andric     llvm::BumpPtrAllocator StringData;
15430b57cec5SDimitry Andric 
15440b57cec5SDimitry Andric     /// The current token.
15450b57cec5SDimitry Andric     MMToken Tok;
15460b57cec5SDimitry Andric 
15470b57cec5SDimitry Andric     /// The active module.
15480b57cec5SDimitry Andric     Module *ActiveModule = nullptr;
15490b57cec5SDimitry Andric 
15500b57cec5SDimitry Andric     /// Whether a module uses the 'requires excluded' hack to mark its
15510b57cec5SDimitry Andric     /// contents as 'textual'.
15520b57cec5SDimitry Andric     ///
15530b57cec5SDimitry Andric     /// On older Darwin SDK versions, 'requires excluded' is used to mark the
15540b57cec5SDimitry Andric     /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
15550b57cec5SDimitry Andric     /// non-modular headers.  For backwards compatibility, we continue to
15560b57cec5SDimitry Andric     /// support this idiom for just these modules, and map the headers to
15570b57cec5SDimitry Andric     /// 'textual' to match the original intent.
15580b57cec5SDimitry Andric     llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
15590b57cec5SDimitry Andric 
15600b57cec5SDimitry Andric     /// Consume the current token and return its location.
15610b57cec5SDimitry Andric     SourceLocation consumeToken();
15620b57cec5SDimitry Andric 
15630b57cec5SDimitry Andric     /// Skip tokens until we reach the a token with the given kind
15640b57cec5SDimitry Andric     /// (or the end of the file).
15650b57cec5SDimitry Andric     void skipUntil(MMToken::TokenKind K);
15660b57cec5SDimitry Andric 
15670b57cec5SDimitry Andric     bool parseModuleId(ModuleId &Id);
15680b57cec5SDimitry Andric     void parseModuleDecl();
15690b57cec5SDimitry Andric     void parseExternModuleDecl();
15700b57cec5SDimitry Andric     void parseRequiresDecl();
15710b57cec5SDimitry Andric     void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
15720b57cec5SDimitry Andric     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
15730b57cec5SDimitry Andric     void parseExportDecl();
15740b57cec5SDimitry Andric     void parseExportAsDecl();
15750b57cec5SDimitry Andric     void parseUseDecl();
15760b57cec5SDimitry Andric     void parseLinkDecl();
15770b57cec5SDimitry Andric     void parseConfigMacros();
15780b57cec5SDimitry Andric     void parseConflict();
15790b57cec5SDimitry Andric     void parseInferredModuleDecl(bool Framework, bool Explicit);
15800b57cec5SDimitry Andric 
15810b57cec5SDimitry Andric     /// Private modules are canonicalized as Foo_Private. Clang provides extra
15820b57cec5SDimitry Andric     /// module map search logic to find the appropriate private module when PCH
15830b57cec5SDimitry Andric     /// is used with implicit module maps. Warn when private modules are written
15840b57cec5SDimitry Andric     /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
15850b57cec5SDimitry Andric     void diagnosePrivateModules(SourceLocation ExplicitLoc,
15860b57cec5SDimitry Andric                                 SourceLocation FrameworkLoc);
15870b57cec5SDimitry Andric 
15880b57cec5SDimitry Andric     using Attributes = ModuleMap::Attributes;
15890b57cec5SDimitry Andric 
15900b57cec5SDimitry Andric     bool parseOptionalAttributes(Attributes &Attrs);
15910b57cec5SDimitry Andric 
15920b57cec5SDimitry Andric   public:
1593*0fca6ea1SDimitry Andric     ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
15940b57cec5SDimitry Andric                     const TargetInfo *Target, DiagnosticsEngine &Diags,
1595*0fca6ea1SDimitry Andric                     ModuleMap &Map, FileID ModuleMapFID,
159606c3fb27SDimitry Andric                     DirectoryEntryRef Directory, bool IsSystem)
15970b57cec5SDimitry Andric         : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
1598*0fca6ea1SDimitry Andric           ModuleMapFID(ModuleMapFID), Directory(Directory), IsSystem(IsSystem) {
15990b57cec5SDimitry Andric       Tok.clear();
16000b57cec5SDimitry Andric       consumeToken();
16010b57cec5SDimitry Andric     }
16020b57cec5SDimitry Andric 
16030b57cec5SDimitry Andric     bool parseModuleMapFile();
16040b57cec5SDimitry Andric 
16050b57cec5SDimitry Andric     bool terminatedByDirective() { return false; }
16060b57cec5SDimitry Andric     SourceLocation getLocation() { return Tok.getLocation(); }
16070b57cec5SDimitry Andric   };
16080b57cec5SDimitry Andric 
16090b57cec5SDimitry Andric } // namespace clang
16100b57cec5SDimitry Andric 
16110b57cec5SDimitry Andric SourceLocation ModuleMapParser::consumeToken() {
16120b57cec5SDimitry Andric   SourceLocation Result = Tok.getLocation();
16130b57cec5SDimitry Andric 
16140b57cec5SDimitry Andric retry:
16150b57cec5SDimitry Andric   Tok.clear();
16160b57cec5SDimitry Andric   Token LToken;
16170b57cec5SDimitry Andric   L.LexFromRawLexer(LToken);
16180b57cec5SDimitry Andric   Tok.Location = LToken.getLocation().getRawEncoding();
16190b57cec5SDimitry Andric   switch (LToken.getKind()) {
16200b57cec5SDimitry Andric   case tok::raw_identifier: {
16210b57cec5SDimitry Andric     StringRef RI = LToken.getRawIdentifier();
16220b57cec5SDimitry Andric     Tok.StringData = RI.data();
16230b57cec5SDimitry Andric     Tok.StringLength = RI.size();
16240b57cec5SDimitry Andric     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
16250b57cec5SDimitry Andric                  .Case("config_macros", MMToken::ConfigMacros)
16260b57cec5SDimitry Andric                  .Case("conflict", MMToken::Conflict)
16270b57cec5SDimitry Andric                  .Case("exclude", MMToken::ExcludeKeyword)
16280b57cec5SDimitry Andric                  .Case("explicit", MMToken::ExplicitKeyword)
16290b57cec5SDimitry Andric                  .Case("export", MMToken::ExportKeyword)
16300b57cec5SDimitry Andric                  .Case("export_as", MMToken::ExportAsKeyword)
16310b57cec5SDimitry Andric                  .Case("extern", MMToken::ExternKeyword)
16320b57cec5SDimitry Andric                  .Case("framework", MMToken::FrameworkKeyword)
16330b57cec5SDimitry Andric                  .Case("header", MMToken::HeaderKeyword)
16340b57cec5SDimitry Andric                  .Case("link", MMToken::LinkKeyword)
16350b57cec5SDimitry Andric                  .Case("module", MMToken::ModuleKeyword)
16360b57cec5SDimitry Andric                  .Case("private", MMToken::PrivateKeyword)
16370b57cec5SDimitry Andric                  .Case("requires", MMToken::RequiresKeyword)
16380b57cec5SDimitry Andric                  .Case("textual", MMToken::TextualKeyword)
16390b57cec5SDimitry Andric                  .Case("umbrella", MMToken::UmbrellaKeyword)
16400b57cec5SDimitry Andric                  .Case("use", MMToken::UseKeyword)
16410b57cec5SDimitry Andric                  .Default(MMToken::Identifier);
16420b57cec5SDimitry Andric     break;
16430b57cec5SDimitry Andric   }
16440b57cec5SDimitry Andric 
16450b57cec5SDimitry Andric   case tok::comma:
16460b57cec5SDimitry Andric     Tok.Kind = MMToken::Comma;
16470b57cec5SDimitry Andric     break;
16480b57cec5SDimitry Andric 
16490b57cec5SDimitry Andric   case tok::eof:
16500b57cec5SDimitry Andric     Tok.Kind = MMToken::EndOfFile;
16510b57cec5SDimitry Andric     break;
16520b57cec5SDimitry Andric 
16530b57cec5SDimitry Andric   case tok::l_brace:
16540b57cec5SDimitry Andric     Tok.Kind = MMToken::LBrace;
16550b57cec5SDimitry Andric     break;
16560b57cec5SDimitry Andric 
16570b57cec5SDimitry Andric   case tok::l_square:
16580b57cec5SDimitry Andric     Tok.Kind = MMToken::LSquare;
16590b57cec5SDimitry Andric     break;
16600b57cec5SDimitry Andric 
16610b57cec5SDimitry Andric   case tok::period:
16620b57cec5SDimitry Andric     Tok.Kind = MMToken::Period;
16630b57cec5SDimitry Andric     break;
16640b57cec5SDimitry Andric 
16650b57cec5SDimitry Andric   case tok::r_brace:
16660b57cec5SDimitry Andric     Tok.Kind = MMToken::RBrace;
16670b57cec5SDimitry Andric     break;
16680b57cec5SDimitry Andric 
16690b57cec5SDimitry Andric   case tok::r_square:
16700b57cec5SDimitry Andric     Tok.Kind = MMToken::RSquare;
16710b57cec5SDimitry Andric     break;
16720b57cec5SDimitry Andric 
16730b57cec5SDimitry Andric   case tok::star:
16740b57cec5SDimitry Andric     Tok.Kind = MMToken::Star;
16750b57cec5SDimitry Andric     break;
16760b57cec5SDimitry Andric 
16770b57cec5SDimitry Andric   case tok::exclaim:
16780b57cec5SDimitry Andric     Tok.Kind = MMToken::Exclaim;
16790b57cec5SDimitry Andric     break;
16800b57cec5SDimitry Andric 
16810b57cec5SDimitry Andric   case tok::string_literal: {
16820b57cec5SDimitry Andric     if (LToken.hasUDSuffix()) {
16830b57cec5SDimitry Andric       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
16840b57cec5SDimitry Andric       HadError = true;
16850b57cec5SDimitry Andric       goto retry;
16860b57cec5SDimitry Andric     }
16870b57cec5SDimitry Andric 
16880b57cec5SDimitry Andric     // Parse the string literal.
16890b57cec5SDimitry Andric     LangOptions LangOpts;
16900b57cec5SDimitry Andric     StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
16910b57cec5SDimitry Andric     if (StringLiteral.hadError)
16920b57cec5SDimitry Andric       goto retry;
16930b57cec5SDimitry Andric 
16940b57cec5SDimitry Andric     // Copy the string literal into our string data allocator.
16950b57cec5SDimitry Andric     unsigned Length = StringLiteral.GetStringLength();
16960b57cec5SDimitry Andric     char *Saved = StringData.Allocate<char>(Length + 1);
16970b57cec5SDimitry Andric     memcpy(Saved, StringLiteral.GetString().data(), Length);
16980b57cec5SDimitry Andric     Saved[Length] = 0;
16990b57cec5SDimitry Andric 
17000b57cec5SDimitry Andric     // Form the token.
17010b57cec5SDimitry Andric     Tok.Kind = MMToken::StringLiteral;
17020b57cec5SDimitry Andric     Tok.StringData = Saved;
17030b57cec5SDimitry Andric     Tok.StringLength = Length;
17040b57cec5SDimitry Andric     break;
17050b57cec5SDimitry Andric   }
17060b57cec5SDimitry Andric 
17070b57cec5SDimitry Andric   case tok::numeric_constant: {
17080b57cec5SDimitry Andric     // We don't support any suffixes or other complications.
17090b57cec5SDimitry Andric     SmallString<32> SpellingBuffer;
17100b57cec5SDimitry Andric     SpellingBuffer.resize(LToken.getLength() + 1);
17110b57cec5SDimitry Andric     const char *Start = SpellingBuffer.data();
17120b57cec5SDimitry Andric     unsigned Length =
171381ad6265SDimitry Andric         Lexer::getSpelling(LToken, Start, SourceMgr, Map.LangOpts);
17140b57cec5SDimitry Andric     uint64_t Value;
17150b57cec5SDimitry Andric     if (StringRef(Start, Length).getAsInteger(0, Value)) {
17160b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
17170b57cec5SDimitry Andric       HadError = true;
17180b57cec5SDimitry Andric       goto retry;
17190b57cec5SDimitry Andric     }
17200b57cec5SDimitry Andric 
17210b57cec5SDimitry Andric     Tok.Kind = MMToken::IntegerLiteral;
17220b57cec5SDimitry Andric     Tok.IntegerValue = Value;
17230b57cec5SDimitry Andric     break;
17240b57cec5SDimitry Andric   }
17250b57cec5SDimitry Andric 
17260b57cec5SDimitry Andric   case tok::comment:
17270b57cec5SDimitry Andric     goto retry;
17280b57cec5SDimitry Andric 
17290b57cec5SDimitry Andric   case tok::hash:
17300b57cec5SDimitry Andric     // A module map can be terminated prematurely by
17310b57cec5SDimitry Andric     //   #pragma clang module contents
17320b57cec5SDimitry Andric     // When building the module, we'll treat the rest of the file as the
17330b57cec5SDimitry Andric     // contents of the module.
17340b57cec5SDimitry Andric     {
17350b57cec5SDimitry Andric       auto NextIsIdent = [&](StringRef Str) -> bool {
17360b57cec5SDimitry Andric         L.LexFromRawLexer(LToken);
17370b57cec5SDimitry Andric         return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
17380b57cec5SDimitry Andric                LToken.getRawIdentifier() == Str;
17390b57cec5SDimitry Andric       };
17400b57cec5SDimitry Andric       if (NextIsIdent("pragma") && NextIsIdent("clang") &&
17410b57cec5SDimitry Andric           NextIsIdent("module") && NextIsIdent("contents")) {
17420b57cec5SDimitry Andric         Tok.Kind = MMToken::EndOfFile;
17430b57cec5SDimitry Andric         break;
17440b57cec5SDimitry Andric       }
17450b57cec5SDimitry Andric     }
1746bdd1243dSDimitry Andric     [[fallthrough]];
17470b57cec5SDimitry Andric 
17480b57cec5SDimitry Andric   default:
17490b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
17500b57cec5SDimitry Andric     HadError = true;
17510b57cec5SDimitry Andric     goto retry;
17520b57cec5SDimitry Andric   }
17530b57cec5SDimitry Andric 
17540b57cec5SDimitry Andric   return Result;
17550b57cec5SDimitry Andric }
17560b57cec5SDimitry Andric 
17570b57cec5SDimitry Andric void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
17580b57cec5SDimitry Andric   unsigned braceDepth = 0;
17590b57cec5SDimitry Andric   unsigned squareDepth = 0;
17600b57cec5SDimitry Andric   do {
17610b57cec5SDimitry Andric     switch (Tok.Kind) {
17620b57cec5SDimitry Andric     case MMToken::EndOfFile:
17630b57cec5SDimitry Andric       return;
17640b57cec5SDimitry Andric 
17650b57cec5SDimitry Andric     case MMToken::LBrace:
17660b57cec5SDimitry Andric       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
17670b57cec5SDimitry Andric         return;
17680b57cec5SDimitry Andric 
17690b57cec5SDimitry Andric       ++braceDepth;
17700b57cec5SDimitry Andric       break;
17710b57cec5SDimitry Andric 
17720b57cec5SDimitry Andric     case MMToken::LSquare:
17730b57cec5SDimitry Andric       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
17740b57cec5SDimitry Andric         return;
17750b57cec5SDimitry Andric 
17760b57cec5SDimitry Andric       ++squareDepth;
17770b57cec5SDimitry Andric       break;
17780b57cec5SDimitry Andric 
17790b57cec5SDimitry Andric     case MMToken::RBrace:
17800b57cec5SDimitry Andric       if (braceDepth > 0)
17810b57cec5SDimitry Andric         --braceDepth;
17820b57cec5SDimitry Andric       else if (Tok.is(K))
17830b57cec5SDimitry Andric         return;
17840b57cec5SDimitry Andric       break;
17850b57cec5SDimitry Andric 
17860b57cec5SDimitry Andric     case MMToken::RSquare:
17870b57cec5SDimitry Andric       if (squareDepth > 0)
17880b57cec5SDimitry Andric         --squareDepth;
17890b57cec5SDimitry Andric       else if (Tok.is(K))
17900b57cec5SDimitry Andric         return;
17910b57cec5SDimitry Andric       break;
17920b57cec5SDimitry Andric 
17930b57cec5SDimitry Andric     default:
17940b57cec5SDimitry Andric       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
17950b57cec5SDimitry Andric         return;
17960b57cec5SDimitry Andric       break;
17970b57cec5SDimitry Andric     }
17980b57cec5SDimitry Andric 
17990b57cec5SDimitry Andric    consumeToken();
18000b57cec5SDimitry Andric   } while (true);
18010b57cec5SDimitry Andric }
18020b57cec5SDimitry Andric 
18030b57cec5SDimitry Andric /// Parse a module-id.
18040b57cec5SDimitry Andric ///
18050b57cec5SDimitry Andric ///   module-id:
18060b57cec5SDimitry Andric ///     identifier
18070b57cec5SDimitry Andric ///     identifier '.' module-id
18080b57cec5SDimitry Andric ///
18090b57cec5SDimitry Andric /// \returns true if an error occurred, false otherwise.
18100b57cec5SDimitry Andric bool ModuleMapParser::parseModuleId(ModuleId &Id) {
18110b57cec5SDimitry Andric   Id.clear();
18120b57cec5SDimitry Andric   do {
18130b57cec5SDimitry Andric     if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
18145ffd83dbSDimitry Andric       Id.push_back(
18155ffd83dbSDimitry Andric           std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
18160b57cec5SDimitry Andric       consumeToken();
18170b57cec5SDimitry Andric     } else {
18180b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
18190b57cec5SDimitry Andric       return true;
18200b57cec5SDimitry Andric     }
18210b57cec5SDimitry Andric 
18220b57cec5SDimitry Andric     if (!Tok.is(MMToken::Period))
18230b57cec5SDimitry Andric       break;
18240b57cec5SDimitry Andric 
18250b57cec5SDimitry Andric     consumeToken();
18260b57cec5SDimitry Andric   } while (true);
18270b57cec5SDimitry Andric 
18280b57cec5SDimitry Andric   return false;
18290b57cec5SDimitry Andric }
18300b57cec5SDimitry Andric 
18310b57cec5SDimitry Andric namespace {
18320b57cec5SDimitry Andric 
18330b57cec5SDimitry Andric   /// Enumerates the known attributes.
18340b57cec5SDimitry Andric   enum AttributeKind {
18350b57cec5SDimitry Andric     /// An unknown attribute.
18360b57cec5SDimitry Andric     AT_unknown,
18370b57cec5SDimitry Andric 
18380b57cec5SDimitry Andric     /// The 'system' attribute.
18390b57cec5SDimitry Andric     AT_system,
18400b57cec5SDimitry Andric 
18410b57cec5SDimitry Andric     /// The 'extern_c' attribute.
18420b57cec5SDimitry Andric     AT_extern_c,
18430b57cec5SDimitry Andric 
18440b57cec5SDimitry Andric     /// The 'exhaustive' attribute.
18450b57cec5SDimitry Andric     AT_exhaustive,
18460b57cec5SDimitry Andric 
18470b57cec5SDimitry Andric     /// The 'no_undeclared_includes' attribute.
18480b57cec5SDimitry Andric     AT_no_undeclared_includes
18490b57cec5SDimitry Andric   };
18500b57cec5SDimitry Andric 
18510b57cec5SDimitry Andric } // namespace
18520b57cec5SDimitry Andric 
18530b57cec5SDimitry Andric /// Private modules are canonicalized as Foo_Private. Clang provides extra
18540b57cec5SDimitry Andric /// module map search logic to find the appropriate private module when PCH
18550b57cec5SDimitry Andric /// is used with implicit module maps. Warn when private modules are written
18560b57cec5SDimitry Andric /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
18570b57cec5SDimitry Andric void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
18580b57cec5SDimitry Andric                                              SourceLocation FrameworkLoc) {
18590b57cec5SDimitry Andric   auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
18600b57cec5SDimitry Andric                              const Module *M, SourceRange ReplLoc) {
18610b57cec5SDimitry Andric     auto D = Diags.Report(ActiveModule->DefinitionLoc,
18620b57cec5SDimitry Andric                           diag::note_mmap_rename_top_level_private_module);
18630b57cec5SDimitry Andric     D << BadName << M->Name;
18640b57cec5SDimitry Andric     D << FixItHint::CreateReplacement(ReplLoc, Canonical);
18650b57cec5SDimitry Andric   };
18660b57cec5SDimitry Andric 
18670b57cec5SDimitry Andric   for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
18680b57cec5SDimitry Andric     auto const *M = E->getValue();
18690b57cec5SDimitry Andric     if (M->Directory != ActiveModule->Directory)
18700b57cec5SDimitry Andric       continue;
18710b57cec5SDimitry Andric 
18720b57cec5SDimitry Andric     SmallString<128> FullName(ActiveModule->getFullModuleName());
18735f757f3fSDimitry Andric     if (!FullName.starts_with(M->Name) && !FullName.ends_with("Private"))
18740b57cec5SDimitry Andric       continue;
18750b57cec5SDimitry Andric     SmallString<128> FixedPrivModDecl;
18760b57cec5SDimitry Andric     SmallString<128> Canonical(M->Name);
18770b57cec5SDimitry Andric     Canonical.append("_Private");
18780b57cec5SDimitry Andric 
18790b57cec5SDimitry Andric     // Foo.Private -> Foo_Private
18800b57cec5SDimitry Andric     if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
18810b57cec5SDimitry Andric         M->Name == ActiveModule->Parent->Name) {
18820b57cec5SDimitry Andric       Diags.Report(ActiveModule->DefinitionLoc,
18830b57cec5SDimitry Andric                    diag::warn_mmap_mismatched_private_submodule)
18840b57cec5SDimitry Andric           << FullName;
18850b57cec5SDimitry Andric 
18860b57cec5SDimitry Andric       SourceLocation FixItInitBegin = CurrModuleDeclLoc;
18870b57cec5SDimitry Andric       if (FrameworkLoc.isValid())
18880b57cec5SDimitry Andric         FixItInitBegin = FrameworkLoc;
18890b57cec5SDimitry Andric       if (ExplicitLoc.isValid())
18900b57cec5SDimitry Andric         FixItInitBegin = ExplicitLoc;
18910b57cec5SDimitry Andric 
18920b57cec5SDimitry Andric       if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
18930b57cec5SDimitry Andric         FixedPrivModDecl.append("framework ");
18940b57cec5SDimitry Andric       FixedPrivModDecl.append("module ");
18950b57cec5SDimitry Andric       FixedPrivModDecl.append(Canonical);
18960b57cec5SDimitry Andric 
18970b57cec5SDimitry Andric       GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
18980b57cec5SDimitry Andric                       SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
18990b57cec5SDimitry Andric       continue;
19000b57cec5SDimitry Andric     }
19010b57cec5SDimitry Andric 
19020b57cec5SDimitry Andric     // FooPrivate and whatnots -> Foo_Private
19030b57cec5SDimitry Andric     if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
19040b57cec5SDimitry Andric         ActiveModule->Name != Canonical) {
19050b57cec5SDimitry Andric       Diags.Report(ActiveModule->DefinitionLoc,
19060b57cec5SDimitry Andric                    diag::warn_mmap_mismatched_private_module_name)
19070b57cec5SDimitry Andric           << ActiveModule->Name;
19080b57cec5SDimitry Andric       GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
19090b57cec5SDimitry Andric                       SourceRange(ActiveModule->DefinitionLoc));
19100b57cec5SDimitry Andric     }
19110b57cec5SDimitry Andric   }
19120b57cec5SDimitry Andric }
19130b57cec5SDimitry Andric 
19140b57cec5SDimitry Andric /// Parse a module declaration.
19150b57cec5SDimitry Andric ///
19160b57cec5SDimitry Andric ///   module-declaration:
19170b57cec5SDimitry Andric ///     'extern' 'module' module-id string-literal
19180b57cec5SDimitry Andric ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
19190b57cec5SDimitry Andric ///       { module-member* }
19200b57cec5SDimitry Andric ///
19210b57cec5SDimitry Andric ///   module-member:
19220b57cec5SDimitry Andric ///     requires-declaration
19230b57cec5SDimitry Andric ///     header-declaration
19240b57cec5SDimitry Andric ///     submodule-declaration
19250b57cec5SDimitry Andric ///     export-declaration
19260b57cec5SDimitry Andric ///     export-as-declaration
19270b57cec5SDimitry Andric ///     link-declaration
19280b57cec5SDimitry Andric ///
19290b57cec5SDimitry Andric ///   submodule-declaration:
19300b57cec5SDimitry Andric ///     module-declaration
19310b57cec5SDimitry Andric ///     inferred-submodule-declaration
19320b57cec5SDimitry Andric void ModuleMapParser::parseModuleDecl() {
19330b57cec5SDimitry Andric   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
19340b57cec5SDimitry Andric          Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
19350b57cec5SDimitry Andric   if (Tok.is(MMToken::ExternKeyword)) {
19360b57cec5SDimitry Andric     parseExternModuleDecl();
19370b57cec5SDimitry Andric     return;
19380b57cec5SDimitry Andric   }
19390b57cec5SDimitry Andric 
19400b57cec5SDimitry Andric   // Parse 'explicit' or 'framework' keyword, if present.
19410b57cec5SDimitry Andric   SourceLocation ExplicitLoc;
19420b57cec5SDimitry Andric   SourceLocation FrameworkLoc;
19430b57cec5SDimitry Andric   bool Explicit = false;
19440b57cec5SDimitry Andric   bool Framework = false;
19450b57cec5SDimitry Andric 
19460b57cec5SDimitry Andric   // Parse 'explicit' keyword, if present.
19470b57cec5SDimitry Andric   if (Tok.is(MMToken::ExplicitKeyword)) {
19480b57cec5SDimitry Andric     ExplicitLoc = consumeToken();
19490b57cec5SDimitry Andric     Explicit = true;
19500b57cec5SDimitry Andric   }
19510b57cec5SDimitry Andric 
19520b57cec5SDimitry Andric   // Parse 'framework' keyword, if present.
19530b57cec5SDimitry Andric   if (Tok.is(MMToken::FrameworkKeyword)) {
19540b57cec5SDimitry Andric     FrameworkLoc = consumeToken();
19550b57cec5SDimitry Andric     Framework = true;
19560b57cec5SDimitry Andric   }
19570b57cec5SDimitry Andric 
19580b57cec5SDimitry Andric   // Parse 'module' keyword.
19590b57cec5SDimitry Andric   if (!Tok.is(MMToken::ModuleKeyword)) {
19600b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
19610b57cec5SDimitry Andric     consumeToken();
19620b57cec5SDimitry Andric     HadError = true;
19630b57cec5SDimitry Andric     return;
19640b57cec5SDimitry Andric   }
19650b57cec5SDimitry Andric   CurrModuleDeclLoc = consumeToken(); // 'module' keyword
19660b57cec5SDimitry Andric 
19670b57cec5SDimitry Andric   // If we have a wildcard for the module name, this is an inferred submodule.
19680b57cec5SDimitry Andric   // Parse it.
19690b57cec5SDimitry Andric   if (Tok.is(MMToken::Star))
19700b57cec5SDimitry Andric     return parseInferredModuleDecl(Framework, Explicit);
19710b57cec5SDimitry Andric 
19720b57cec5SDimitry Andric   // Parse the module name.
19730b57cec5SDimitry Andric   ModuleId Id;
19740b57cec5SDimitry Andric   if (parseModuleId(Id)) {
19750b57cec5SDimitry Andric     HadError = true;
19760b57cec5SDimitry Andric     return;
19770b57cec5SDimitry Andric   }
19780b57cec5SDimitry Andric 
19790b57cec5SDimitry Andric   if (ActiveModule) {
19800b57cec5SDimitry Andric     if (Id.size() > 1) {
19810b57cec5SDimitry Andric       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
19820b57cec5SDimitry Andric         << SourceRange(Id.front().second, Id.back().second);
19830b57cec5SDimitry Andric 
19840b57cec5SDimitry Andric       HadError = true;
19850b57cec5SDimitry Andric       return;
19860b57cec5SDimitry Andric     }
19870b57cec5SDimitry Andric   } else if (Id.size() == 1 && Explicit) {
19880b57cec5SDimitry Andric     // Top-level modules can't be explicit.
19890b57cec5SDimitry Andric     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
19900b57cec5SDimitry Andric     Explicit = false;
19910b57cec5SDimitry Andric     ExplicitLoc = SourceLocation();
19920b57cec5SDimitry Andric     HadError = true;
19930b57cec5SDimitry Andric   }
19940b57cec5SDimitry Andric 
19950b57cec5SDimitry Andric   Module *PreviousActiveModule = ActiveModule;
19960b57cec5SDimitry Andric   if (Id.size() > 1) {
19970b57cec5SDimitry Andric     // This module map defines a submodule. Go find the module of which it
19980b57cec5SDimitry Andric     // is a submodule.
19990b57cec5SDimitry Andric     ActiveModule = nullptr;
20000b57cec5SDimitry Andric     const Module *TopLevelModule = nullptr;
20010b57cec5SDimitry Andric     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
20020b57cec5SDimitry Andric       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
20030b57cec5SDimitry Andric         if (I == 0)
20040b57cec5SDimitry Andric           TopLevelModule = Next;
20050b57cec5SDimitry Andric         ActiveModule = Next;
20060b57cec5SDimitry Andric         continue;
20070b57cec5SDimitry Andric       }
20080b57cec5SDimitry Andric 
2009e8d8bef9SDimitry Andric       Diags.Report(Id[I].second, diag::err_mmap_missing_parent_module)
2010e8d8bef9SDimitry Andric           << Id[I].first << (ActiveModule != nullptr)
2011e8d8bef9SDimitry Andric           << (ActiveModule
2012e8d8bef9SDimitry Andric                   ? ActiveModule->getTopLevelModule()->getFullModuleName()
2013e8d8bef9SDimitry Andric                   : "");
20140b57cec5SDimitry Andric       HadError = true;
20150b57cec5SDimitry Andric     }
20160b57cec5SDimitry Andric 
2017e8d8bef9SDimitry Andric     if (TopLevelModule &&
2018*0fca6ea1SDimitry Andric         ModuleMapFID != Map.getContainingModuleMapFileID(TopLevelModule)) {
2019*0fca6ea1SDimitry Andric       assert(ModuleMapFID !=
2020*0fca6ea1SDimitry Andric                  Map.getModuleMapFileIDForUniquing(TopLevelModule) &&
20210b57cec5SDimitry Andric              "submodule defined in same file as 'module *' that allowed its "
20220b57cec5SDimitry Andric              "top-level module");
2023*0fca6ea1SDimitry Andric       Map.addAdditionalModuleMapFile(
2024*0fca6ea1SDimitry Andric           TopLevelModule, *SourceMgr.getFileEntryRefForID(ModuleMapFID));
20250b57cec5SDimitry Andric     }
20260b57cec5SDimitry Andric   }
20270b57cec5SDimitry Andric 
20280b57cec5SDimitry Andric   StringRef ModuleName = Id.back().first;
20290b57cec5SDimitry Andric   SourceLocation ModuleNameLoc = Id.back().second;
20300b57cec5SDimitry Andric 
20310b57cec5SDimitry Andric   // Parse the optional attribute list.
20320b57cec5SDimitry Andric   Attributes Attrs;
20330b57cec5SDimitry Andric   if (parseOptionalAttributes(Attrs))
20340b57cec5SDimitry Andric     return;
20350b57cec5SDimitry Andric 
20360b57cec5SDimitry Andric   // Parse the opening brace.
20370b57cec5SDimitry Andric   if (!Tok.is(MMToken::LBrace)) {
20380b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
20390b57cec5SDimitry Andric       << ModuleName;
20400b57cec5SDimitry Andric     HadError = true;
20410b57cec5SDimitry Andric     return;
20420b57cec5SDimitry Andric   }
20430b57cec5SDimitry Andric   SourceLocation LBraceLoc = consumeToken();
20440b57cec5SDimitry Andric 
20450b57cec5SDimitry Andric   // Determine whether this (sub)module has already been defined.
20460b57cec5SDimitry Andric   Module *ShadowingModule = nullptr;
20470b57cec5SDimitry Andric   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
20480b57cec5SDimitry Andric     // We might see a (re)definition of a module that we already have a
204906c3fb27SDimitry Andric     // definition for in four cases:
20500b57cec5SDimitry Andric     //  - If we loaded one definition from an AST file and we've just found a
20510b57cec5SDimitry Andric     //    corresponding definition in a module map file, or
205206c3fb27SDimitry Andric     bool LoadedFromASTFile = Existing->IsFromModuleFile;
205306c3fb27SDimitry Andric     //  - If we previously inferred this module from different module map file.
205406c3fb27SDimitry Andric     bool Inferred = Existing->IsInferred;
205506c3fb27SDimitry Andric     //  - If we're building a framework that vends a module map, we might've
205606c3fb27SDimitry Andric     //    previously seen the one in intermediate products and now the system
205706c3fb27SDimitry Andric     //    one.
205806c3fb27SDimitry Andric     // FIXME: If we're parsing module map file that looks like this:
205906c3fb27SDimitry Andric     //          framework module FW { ... }
206006c3fb27SDimitry Andric     //          module FW.Sub { ... }
206106c3fb27SDimitry Andric     //        We can't check the framework qualifier, since it's not attached to
206206c3fb27SDimitry Andric     //        the definition of Sub. Checking that qualifier on \c Existing is
206306c3fb27SDimitry Andric     //        not correct either, since we might've previously seen:
206406c3fb27SDimitry Andric     //          module FW { ... }
206506c3fb27SDimitry Andric     //          module FW.Sub { ... }
206606c3fb27SDimitry Andric     //        We should enforce consistency of redefinitions so that we can rely
206706c3fb27SDimitry Andric     //        that \c Existing is part of a framework iff the redefinition of FW
206806c3fb27SDimitry Andric     //        we have just skipped had it too. Once we do that, stop checking
206906c3fb27SDimitry Andric     //        the local framework qualifier and only rely on \c Existing.
207006c3fb27SDimitry Andric     bool PartOfFramework = Framework || Existing->isPartOfFramework();
20710b57cec5SDimitry Andric     //  - If we're building a (preprocessed) module and we've just loaded the
20720b57cec5SDimitry Andric     //    module map file from which it was created.
20730b57cec5SDimitry Andric     bool ParsedAsMainInput =
20740b57cec5SDimitry Andric         Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
20750b57cec5SDimitry Andric         Map.LangOpts.CurrentModule == ModuleName &&
20760b57cec5SDimitry Andric         SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
20770b57cec5SDimitry Andric             SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
207806c3fb27SDimitry Andric     if (LoadedFromASTFile || Inferred || PartOfFramework || ParsedAsMainInput) {
207906c3fb27SDimitry Andric       ActiveModule = PreviousActiveModule;
20800b57cec5SDimitry Andric       // Skip the module definition.
20810b57cec5SDimitry Andric       skipUntil(MMToken::RBrace);
20820b57cec5SDimitry Andric       if (Tok.is(MMToken::RBrace))
20830b57cec5SDimitry Andric         consumeToken();
20840b57cec5SDimitry Andric       else {
20850b57cec5SDimitry Andric         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
20860b57cec5SDimitry Andric         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
20870b57cec5SDimitry Andric         HadError = true;
20880b57cec5SDimitry Andric       }
20890b57cec5SDimitry Andric       return;
20900b57cec5SDimitry Andric     }
20910b57cec5SDimitry Andric 
20920b57cec5SDimitry Andric     if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
20930b57cec5SDimitry Andric       ShadowingModule = Existing;
20940b57cec5SDimitry Andric     } else {
20950b57cec5SDimitry Andric       // This is not a shawdowed module decl, it is an illegal redefinition.
20960b57cec5SDimitry Andric       Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
20970b57cec5SDimitry Andric           << ModuleName;
20980b57cec5SDimitry Andric       Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
20990b57cec5SDimitry Andric 
21000b57cec5SDimitry Andric       // Skip the module definition.
21010b57cec5SDimitry Andric       skipUntil(MMToken::RBrace);
21020b57cec5SDimitry Andric       if (Tok.is(MMToken::RBrace))
21030b57cec5SDimitry Andric         consumeToken();
21040b57cec5SDimitry Andric 
21050b57cec5SDimitry Andric       HadError = true;
21060b57cec5SDimitry Andric       return;
21070b57cec5SDimitry Andric     }
21080b57cec5SDimitry Andric   }
21090b57cec5SDimitry Andric 
21100b57cec5SDimitry Andric   // Start defining this module.
21110b57cec5SDimitry Andric   if (ShadowingModule) {
21120b57cec5SDimitry Andric     ActiveModule =
21130b57cec5SDimitry Andric         Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
21140b57cec5SDimitry Andric   } else {
21150b57cec5SDimitry Andric     ActiveModule =
21160b57cec5SDimitry Andric         Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
21170b57cec5SDimitry Andric             .first;
21180b57cec5SDimitry Andric   }
21190b57cec5SDimitry Andric 
21200b57cec5SDimitry Andric   ActiveModule->DefinitionLoc = ModuleNameLoc;
21210b57cec5SDimitry Andric   if (Attrs.IsSystem || IsSystem)
21220b57cec5SDimitry Andric     ActiveModule->IsSystem = true;
21230b57cec5SDimitry Andric   if (Attrs.IsExternC)
21240b57cec5SDimitry Andric     ActiveModule->IsExternC = true;
2125bdd1243dSDimitry Andric   if (Attrs.NoUndeclaredIncludes)
21260b57cec5SDimitry Andric     ActiveModule->NoUndeclaredIncludes = true;
21270b57cec5SDimitry Andric   ActiveModule->Directory = Directory;
21280b57cec5SDimitry Andric 
2129*0fca6ea1SDimitry Andric   StringRef MapFileName(
2130*0fca6ea1SDimitry Andric       SourceMgr.getFileEntryRefForID(ModuleMapFID)->getName());
21315f757f3fSDimitry Andric   if (MapFileName.ends_with("module.private.modulemap") ||
21325f757f3fSDimitry Andric       MapFileName.ends_with("module_private.map")) {
21330b57cec5SDimitry Andric     ActiveModule->ModuleMapIsPrivate = true;
21340b57cec5SDimitry Andric   }
21350b57cec5SDimitry Andric 
21360b57cec5SDimitry Andric   // Private modules named as FooPrivate, Foo.Private or similar are likely a
21370b57cec5SDimitry Andric   // user error; provide warnings, notes and fixits to direct users to use
21380b57cec5SDimitry Andric   // Foo_Private instead.
21390b57cec5SDimitry Andric   SourceLocation StartLoc =
21400b57cec5SDimitry Andric       SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
21410b57cec5SDimitry Andric   if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
21420b57cec5SDimitry Andric       !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
21430b57cec5SDimitry Andric                        StartLoc) &&
21440b57cec5SDimitry Andric       !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
21450b57cec5SDimitry Andric                        StartLoc) &&
21460b57cec5SDimitry Andric       ActiveModule->ModuleMapIsPrivate)
21470b57cec5SDimitry Andric     diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
21480b57cec5SDimitry Andric 
21490b57cec5SDimitry Andric   bool Done = false;
21500b57cec5SDimitry Andric   do {
21510b57cec5SDimitry Andric     switch (Tok.Kind) {
21520b57cec5SDimitry Andric     case MMToken::EndOfFile:
21530b57cec5SDimitry Andric     case MMToken::RBrace:
21540b57cec5SDimitry Andric       Done = true;
21550b57cec5SDimitry Andric       break;
21560b57cec5SDimitry Andric 
21570b57cec5SDimitry Andric     case MMToken::ConfigMacros:
21580b57cec5SDimitry Andric       parseConfigMacros();
21590b57cec5SDimitry Andric       break;
21600b57cec5SDimitry Andric 
21610b57cec5SDimitry Andric     case MMToken::Conflict:
21620b57cec5SDimitry Andric       parseConflict();
21630b57cec5SDimitry Andric       break;
21640b57cec5SDimitry Andric 
21650b57cec5SDimitry Andric     case MMToken::ExplicitKeyword:
21660b57cec5SDimitry Andric     case MMToken::ExternKeyword:
21670b57cec5SDimitry Andric     case MMToken::FrameworkKeyword:
21680b57cec5SDimitry Andric     case MMToken::ModuleKeyword:
21690b57cec5SDimitry Andric       parseModuleDecl();
21700b57cec5SDimitry Andric       break;
21710b57cec5SDimitry Andric 
21720b57cec5SDimitry Andric     case MMToken::ExportKeyword:
21730b57cec5SDimitry Andric       parseExportDecl();
21740b57cec5SDimitry Andric       break;
21750b57cec5SDimitry Andric 
21760b57cec5SDimitry Andric     case MMToken::ExportAsKeyword:
21770b57cec5SDimitry Andric       parseExportAsDecl();
21780b57cec5SDimitry Andric       break;
21790b57cec5SDimitry Andric 
21800b57cec5SDimitry Andric     case MMToken::UseKeyword:
21810b57cec5SDimitry Andric       parseUseDecl();
21820b57cec5SDimitry Andric       break;
21830b57cec5SDimitry Andric 
21840b57cec5SDimitry Andric     case MMToken::RequiresKeyword:
21850b57cec5SDimitry Andric       parseRequiresDecl();
21860b57cec5SDimitry Andric       break;
21870b57cec5SDimitry Andric 
21880b57cec5SDimitry Andric     case MMToken::TextualKeyword:
21890b57cec5SDimitry Andric       parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
21900b57cec5SDimitry Andric       break;
21910b57cec5SDimitry Andric 
21920b57cec5SDimitry Andric     case MMToken::UmbrellaKeyword: {
21930b57cec5SDimitry Andric       SourceLocation UmbrellaLoc = consumeToken();
21940b57cec5SDimitry Andric       if (Tok.is(MMToken::HeaderKeyword))
21950b57cec5SDimitry Andric         parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
21960b57cec5SDimitry Andric       else
21970b57cec5SDimitry Andric         parseUmbrellaDirDecl(UmbrellaLoc);
21980b57cec5SDimitry Andric       break;
21990b57cec5SDimitry Andric     }
22000b57cec5SDimitry Andric 
22010b57cec5SDimitry Andric     case MMToken::ExcludeKeyword:
22020b57cec5SDimitry Andric       parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
22030b57cec5SDimitry Andric       break;
22040b57cec5SDimitry Andric 
22050b57cec5SDimitry Andric     case MMToken::PrivateKeyword:
22060b57cec5SDimitry Andric       parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
22070b57cec5SDimitry Andric       break;
22080b57cec5SDimitry Andric 
22090b57cec5SDimitry Andric     case MMToken::HeaderKeyword:
22100b57cec5SDimitry Andric       parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
22110b57cec5SDimitry Andric       break;
22120b57cec5SDimitry Andric 
22130b57cec5SDimitry Andric     case MMToken::LinkKeyword:
22140b57cec5SDimitry Andric       parseLinkDecl();
22150b57cec5SDimitry Andric       break;
22160b57cec5SDimitry Andric 
22170b57cec5SDimitry Andric     default:
22180b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
22190b57cec5SDimitry Andric       consumeToken();
22200b57cec5SDimitry Andric       break;
22210b57cec5SDimitry Andric     }
22220b57cec5SDimitry Andric   } while (!Done);
22230b57cec5SDimitry Andric 
22240b57cec5SDimitry Andric   if (Tok.is(MMToken::RBrace))
22250b57cec5SDimitry Andric     consumeToken();
22260b57cec5SDimitry Andric   else {
22270b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
22280b57cec5SDimitry Andric     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
22290b57cec5SDimitry Andric     HadError = true;
22300b57cec5SDimitry Andric   }
22310b57cec5SDimitry Andric 
22320b57cec5SDimitry Andric   // If the active module is a top-level framework, and there are no link
22330b57cec5SDimitry Andric   // libraries, automatically link against the framework.
22340b57cec5SDimitry Andric   if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
223506c3fb27SDimitry Andric       ActiveModule->LinkLibraries.empty())
223606c3fb27SDimitry Andric     inferFrameworkLink(ActiveModule);
22370b57cec5SDimitry Andric 
22380b57cec5SDimitry Andric   // If the module meets all requirements but is still unavailable, mark the
22390b57cec5SDimitry Andric   // whole tree as unavailable to prevent it from building.
22405ffd83dbSDimitry Andric   if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
22410b57cec5SDimitry Andric       ActiveModule->Parent) {
22425ffd83dbSDimitry Andric     ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false);
22430b57cec5SDimitry Andric     ActiveModule->getTopLevelModule()->MissingHeaders.append(
22440b57cec5SDimitry Andric       ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
22450b57cec5SDimitry Andric   }
22460b57cec5SDimitry Andric 
22470b57cec5SDimitry Andric   // We're done parsing this module. Pop back to the previous module.
22480b57cec5SDimitry Andric   ActiveModule = PreviousActiveModule;
22490b57cec5SDimitry Andric }
22500b57cec5SDimitry Andric 
22510b57cec5SDimitry Andric /// Parse an extern module declaration.
22520b57cec5SDimitry Andric ///
22530b57cec5SDimitry Andric ///   extern module-declaration:
22540b57cec5SDimitry Andric ///     'extern' 'module' module-id string-literal
22550b57cec5SDimitry Andric void ModuleMapParser::parseExternModuleDecl() {
22560b57cec5SDimitry Andric   assert(Tok.is(MMToken::ExternKeyword));
22570b57cec5SDimitry Andric   SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
22580b57cec5SDimitry Andric 
22590b57cec5SDimitry Andric   // Parse 'module' keyword.
22600b57cec5SDimitry Andric   if (!Tok.is(MMToken::ModuleKeyword)) {
22610b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
22620b57cec5SDimitry Andric     consumeToken();
22630b57cec5SDimitry Andric     HadError = true;
22640b57cec5SDimitry Andric     return;
22650b57cec5SDimitry Andric   }
22660b57cec5SDimitry Andric   consumeToken(); // 'module' keyword
22670b57cec5SDimitry Andric 
22680b57cec5SDimitry Andric   // Parse the module name.
22690b57cec5SDimitry Andric   ModuleId Id;
22700b57cec5SDimitry Andric   if (parseModuleId(Id)) {
22710b57cec5SDimitry Andric     HadError = true;
22720b57cec5SDimitry Andric     return;
22730b57cec5SDimitry Andric   }
22740b57cec5SDimitry Andric 
22750b57cec5SDimitry Andric   // Parse the referenced module map file name.
22760b57cec5SDimitry Andric   if (!Tok.is(MMToken::StringLiteral)) {
22770b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
22780b57cec5SDimitry Andric     HadError = true;
22790b57cec5SDimitry Andric     return;
22800b57cec5SDimitry Andric   }
22815ffd83dbSDimitry Andric   std::string FileName = std::string(Tok.getString());
22820b57cec5SDimitry Andric   consumeToken(); // filename
22830b57cec5SDimitry Andric 
22840b57cec5SDimitry Andric   StringRef FileNameRef = FileName;
22850b57cec5SDimitry Andric   SmallString<128> ModuleMapFileName;
22860b57cec5SDimitry Andric   if (llvm::sys::path::is_relative(FileNameRef)) {
228706c3fb27SDimitry Andric     ModuleMapFileName += Directory.getName();
22880b57cec5SDimitry Andric     llvm::sys::path::append(ModuleMapFileName, FileName);
22890b57cec5SDimitry Andric     FileNameRef = ModuleMapFileName;
22900b57cec5SDimitry Andric   }
229106c3fb27SDimitry Andric   if (auto File = SourceMgr.getFileManager().getOptionalFileRef(FileNameRef))
22920b57cec5SDimitry Andric     Map.parseModuleMapFile(
2293349cc55cSDimitry Andric         *File, IsSystem,
22940b57cec5SDimitry Andric         Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
22950b57cec5SDimitry Andric             ? Directory
229606c3fb27SDimitry Andric             : File->getDir(),
22970b57cec5SDimitry Andric         FileID(), nullptr, ExternLoc);
22980b57cec5SDimitry Andric }
22990b57cec5SDimitry Andric 
23000b57cec5SDimitry Andric /// Whether to add the requirement \p Feature to the module \p M.
23010b57cec5SDimitry Andric ///
23020b57cec5SDimitry Andric /// This preserves backwards compatibility for two hacks in the Darwin system
23030b57cec5SDimitry Andric /// module map files:
23040b57cec5SDimitry Andric ///
23050b57cec5SDimitry Andric /// 1. The use of 'requires excluded' to make headers non-modular, which
23060b57cec5SDimitry Andric ///    should really be mapped to 'textual' now that we have this feature.  We
23070b57cec5SDimitry Andric ///    drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
23080b57cec5SDimitry Andric ///    true.  Later, this bit will be used to map all the headers inside this
23090b57cec5SDimitry Andric ///    module to 'textual'.
23100b57cec5SDimitry Andric ///
23110b57cec5SDimitry Andric ///    This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
23120b57cec5SDimitry Andric ///
23130b57cec5SDimitry Andric /// 2. Removes a bogus cplusplus requirement from IOKit.avc.  This requirement
23140b57cec5SDimitry Andric ///    was never correct and causes issues now that we check it, so drop it.
23150b57cec5SDimitry Andric static bool shouldAddRequirement(Module *M, StringRef Feature,
23160b57cec5SDimitry Andric                                  bool &IsRequiresExcludedHack) {
23170b57cec5SDimitry Andric   if (Feature == "excluded" &&
23180b57cec5SDimitry Andric       (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
23190b57cec5SDimitry Andric        M->fullModuleNameIs({"Tcl", "Private"}))) {
23200b57cec5SDimitry Andric     IsRequiresExcludedHack = true;
23210b57cec5SDimitry Andric     return false;
23220b57cec5SDimitry Andric   } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
23230b57cec5SDimitry Andric     return false;
23240b57cec5SDimitry Andric   }
23250b57cec5SDimitry Andric 
23260b57cec5SDimitry Andric   return true;
23270b57cec5SDimitry Andric }
23280b57cec5SDimitry Andric 
23290b57cec5SDimitry Andric /// Parse a requires declaration.
23300b57cec5SDimitry Andric ///
23310b57cec5SDimitry Andric ///   requires-declaration:
23320b57cec5SDimitry Andric ///     'requires' feature-list
23330b57cec5SDimitry Andric ///
23340b57cec5SDimitry Andric ///   feature-list:
23350b57cec5SDimitry Andric ///     feature ',' feature-list
23360b57cec5SDimitry Andric ///     feature
23370b57cec5SDimitry Andric ///
23380b57cec5SDimitry Andric ///   feature:
23390b57cec5SDimitry Andric ///     '!'[opt] identifier
23400b57cec5SDimitry Andric void ModuleMapParser::parseRequiresDecl() {
23410b57cec5SDimitry Andric   assert(Tok.is(MMToken::RequiresKeyword));
23420b57cec5SDimitry Andric 
23430b57cec5SDimitry Andric   // Parse 'requires' keyword.
23440b57cec5SDimitry Andric   consumeToken();
23450b57cec5SDimitry Andric 
23460b57cec5SDimitry Andric   // Parse the feature-list.
23470b57cec5SDimitry Andric   do {
23480b57cec5SDimitry Andric     bool RequiredState = true;
23490b57cec5SDimitry Andric     if (Tok.is(MMToken::Exclaim)) {
23500b57cec5SDimitry Andric       RequiredState = false;
23510b57cec5SDimitry Andric       consumeToken();
23520b57cec5SDimitry Andric     }
23530b57cec5SDimitry Andric 
23540b57cec5SDimitry Andric     if (!Tok.is(MMToken::Identifier)) {
23550b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
23560b57cec5SDimitry Andric       HadError = true;
23570b57cec5SDimitry Andric       return;
23580b57cec5SDimitry Andric     }
23590b57cec5SDimitry Andric 
23600b57cec5SDimitry Andric     // Consume the feature name.
23615ffd83dbSDimitry Andric     std::string Feature = std::string(Tok.getString());
23620b57cec5SDimitry Andric     consumeToken();
23630b57cec5SDimitry Andric 
23640b57cec5SDimitry Andric     bool IsRequiresExcludedHack = false;
23650b57cec5SDimitry Andric     bool ShouldAddRequirement =
23660b57cec5SDimitry Andric         shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
23670b57cec5SDimitry Andric 
23680b57cec5SDimitry Andric     if (IsRequiresExcludedHack)
23690b57cec5SDimitry Andric       UsesRequiresExcludedHack.insert(ActiveModule);
23700b57cec5SDimitry Andric 
23710b57cec5SDimitry Andric     if (ShouldAddRequirement) {
23720b57cec5SDimitry Andric       // Add this feature.
23730b57cec5SDimitry Andric       ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
23740b57cec5SDimitry Andric                                    *Map.Target);
23750b57cec5SDimitry Andric     }
23760b57cec5SDimitry Andric 
23770b57cec5SDimitry Andric     if (!Tok.is(MMToken::Comma))
23780b57cec5SDimitry Andric       break;
23790b57cec5SDimitry Andric 
23800b57cec5SDimitry Andric     // Consume the comma.
23810b57cec5SDimitry Andric     consumeToken();
23820b57cec5SDimitry Andric   } while (true);
23830b57cec5SDimitry Andric }
23840b57cec5SDimitry Andric 
23850b57cec5SDimitry Andric /// Parse a header declaration.
23860b57cec5SDimitry Andric ///
23870b57cec5SDimitry Andric ///   header-declaration:
23880b57cec5SDimitry Andric ///     'textual'[opt] 'header' string-literal
23890b57cec5SDimitry Andric ///     'private' 'textual'[opt] 'header' string-literal
23900b57cec5SDimitry Andric ///     'exclude' 'header' string-literal
23910b57cec5SDimitry Andric ///     'umbrella' 'header' string-literal
23920b57cec5SDimitry Andric ///
23930b57cec5SDimitry Andric /// FIXME: Support 'private textual header'.
23940b57cec5SDimitry Andric void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
23950b57cec5SDimitry Andric                                       SourceLocation LeadingLoc) {
23960b57cec5SDimitry Andric   // We've already consumed the first token.
23970b57cec5SDimitry Andric   ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
2398bdd1243dSDimitry Andric 
23990b57cec5SDimitry Andric   if (LeadingToken == MMToken::PrivateKeyword) {
24000b57cec5SDimitry Andric     Role = ModuleMap::PrivateHeader;
24010b57cec5SDimitry Andric     // 'private' may optionally be followed by 'textual'.
24020b57cec5SDimitry Andric     if (Tok.is(MMToken::TextualKeyword)) {
24030b57cec5SDimitry Andric       LeadingToken = Tok.Kind;
24040b57cec5SDimitry Andric       consumeToken();
24050b57cec5SDimitry Andric     }
2406bdd1243dSDimitry Andric   } else if (LeadingToken == MMToken::ExcludeKeyword) {
2407bdd1243dSDimitry Andric     Role = ModuleMap::ExcludedHeader;
24080b57cec5SDimitry Andric   }
24090b57cec5SDimitry Andric 
24100b57cec5SDimitry Andric   if (LeadingToken == MMToken::TextualKeyword)
24110b57cec5SDimitry Andric     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
24120b57cec5SDimitry Andric 
24130b57cec5SDimitry Andric   if (UsesRequiresExcludedHack.count(ActiveModule)) {
24140b57cec5SDimitry Andric     // Mark this header 'textual' (see doc comment for
24150b57cec5SDimitry Andric     // Module::UsesRequiresExcludedHack).
24160b57cec5SDimitry Andric     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
24170b57cec5SDimitry Andric   }
24180b57cec5SDimitry Andric 
24190b57cec5SDimitry Andric   if (LeadingToken != MMToken::HeaderKeyword) {
24200b57cec5SDimitry Andric     if (!Tok.is(MMToken::HeaderKeyword)) {
24210b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
24220b57cec5SDimitry Andric           << (LeadingToken == MMToken::PrivateKeyword ? "private" :
24230b57cec5SDimitry Andric               LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
24240b57cec5SDimitry Andric               LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
24250b57cec5SDimitry Andric       return;
24260b57cec5SDimitry Andric     }
24270b57cec5SDimitry Andric     consumeToken();
24280b57cec5SDimitry Andric   }
24290b57cec5SDimitry Andric 
24300b57cec5SDimitry Andric   // Parse the header name.
24310b57cec5SDimitry Andric   if (!Tok.is(MMToken::StringLiteral)) {
24320b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
24330b57cec5SDimitry Andric       << "header";
24340b57cec5SDimitry Andric     HadError = true;
24350b57cec5SDimitry Andric     return;
24360b57cec5SDimitry Andric   }
24370b57cec5SDimitry Andric   Module::UnresolvedHeaderDirective Header;
24385ffd83dbSDimitry Andric   Header.FileName = std::string(Tok.getString());
24390b57cec5SDimitry Andric   Header.FileNameLoc = consumeToken();
24400b57cec5SDimitry Andric   Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
2441bdd1243dSDimitry Andric   Header.Kind = Map.headerRoleToKind(Role);
24420b57cec5SDimitry Andric 
24430b57cec5SDimitry Andric   // Check whether we already have an umbrella.
24445f757f3fSDimitry Andric   if (Header.IsUmbrella &&
24455f757f3fSDimitry Andric       !std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
24460b57cec5SDimitry Andric     Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
24470b57cec5SDimitry Andric       << ActiveModule->getFullModuleName();
24480b57cec5SDimitry Andric     HadError = true;
24490b57cec5SDimitry Andric     return;
24500b57cec5SDimitry Andric   }
24510b57cec5SDimitry Andric 
24520b57cec5SDimitry Andric   // If we were given stat information, parse it so we can skip looking for
24530b57cec5SDimitry Andric   // the file.
24540b57cec5SDimitry Andric   if (Tok.is(MMToken::LBrace)) {
24550b57cec5SDimitry Andric     SourceLocation LBraceLoc = consumeToken();
24560b57cec5SDimitry Andric 
24570b57cec5SDimitry Andric     while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
24580b57cec5SDimitry Andric       enum Attribute { Size, ModTime, Unknown };
24590b57cec5SDimitry Andric       StringRef Str = Tok.getString();
24600b57cec5SDimitry Andric       SourceLocation Loc = consumeToken();
24610b57cec5SDimitry Andric       switch (llvm::StringSwitch<Attribute>(Str)
24620b57cec5SDimitry Andric                   .Case("size", Size)
24630b57cec5SDimitry Andric                   .Case("mtime", ModTime)
24640b57cec5SDimitry Andric                   .Default(Unknown)) {
24650b57cec5SDimitry Andric       case Size:
24660b57cec5SDimitry Andric         if (Header.Size)
24670b57cec5SDimitry Andric           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
24680b57cec5SDimitry Andric         if (!Tok.is(MMToken::IntegerLiteral)) {
24690b57cec5SDimitry Andric           Diags.Report(Tok.getLocation(),
24700b57cec5SDimitry Andric                        diag::err_mmap_invalid_header_attribute_value) << Str;
24710b57cec5SDimitry Andric           skipUntil(MMToken::RBrace);
24720b57cec5SDimitry Andric           break;
24730b57cec5SDimitry Andric         }
24740b57cec5SDimitry Andric         Header.Size = Tok.getInteger();
24750b57cec5SDimitry Andric         consumeToken();
24760b57cec5SDimitry Andric         break;
24770b57cec5SDimitry Andric 
24780b57cec5SDimitry Andric       case ModTime:
24790b57cec5SDimitry Andric         if (Header.ModTime)
24800b57cec5SDimitry Andric           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
24810b57cec5SDimitry Andric         if (!Tok.is(MMToken::IntegerLiteral)) {
24820b57cec5SDimitry Andric           Diags.Report(Tok.getLocation(),
24830b57cec5SDimitry Andric                        diag::err_mmap_invalid_header_attribute_value) << Str;
24840b57cec5SDimitry Andric           skipUntil(MMToken::RBrace);
24850b57cec5SDimitry Andric           break;
24860b57cec5SDimitry Andric         }
24870b57cec5SDimitry Andric         Header.ModTime = Tok.getInteger();
24880b57cec5SDimitry Andric         consumeToken();
24890b57cec5SDimitry Andric         break;
24900b57cec5SDimitry Andric 
24910b57cec5SDimitry Andric       case Unknown:
24920b57cec5SDimitry Andric         Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
24930b57cec5SDimitry Andric         skipUntil(MMToken::RBrace);
24940b57cec5SDimitry Andric         break;
24950b57cec5SDimitry Andric       }
24960b57cec5SDimitry Andric     }
24970b57cec5SDimitry Andric 
24980b57cec5SDimitry Andric     if (Tok.is(MMToken::RBrace))
24990b57cec5SDimitry Andric       consumeToken();
25000b57cec5SDimitry Andric     else {
25010b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
25020b57cec5SDimitry Andric       Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
25030b57cec5SDimitry Andric       HadError = true;
25040b57cec5SDimitry Andric     }
25050b57cec5SDimitry Andric   }
25060b57cec5SDimitry Andric 
25070b57cec5SDimitry Andric   bool NeedsFramework = false;
2508439352acSDimitry Andric   // Don't add headers to the builtin modules if the builtin headers belong to
2509439352acSDimitry Andric   // the system modules, with the exception of __stddef_max_align_t.h which
2510439352acSDimitry Andric   // always had its own module.
2511439352acSDimitry Andric   if (!Map.LangOpts.BuiltinHeadersInSystemModules ||
2512439352acSDimitry Andric       !isBuiltInModuleName(ActiveModule->getTopLevelModuleName()) ||
2513439352acSDimitry Andric       ActiveModule->fullModuleNameIs({"_Builtin_stddef", "max_align_t"}))
25140b57cec5SDimitry Andric     Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
25150b57cec5SDimitry Andric 
251606c3fb27SDimitry Andric   if (NeedsFramework)
25170b57cec5SDimitry Andric     Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
25180b57cec5SDimitry Andric       << ActiveModule->getFullModuleName()
25190b57cec5SDimitry Andric       << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
25200b57cec5SDimitry Andric }
25210b57cec5SDimitry Andric 
25225c16e71dSDimitry Andric static bool compareModuleHeaders(const Module::Header &A,
25235c16e71dSDimitry Andric                                  const Module::Header &B) {
25245c16e71dSDimitry Andric   return A.NameAsWritten < B.NameAsWritten;
25250b57cec5SDimitry Andric }
25260b57cec5SDimitry Andric 
25270b57cec5SDimitry Andric /// Parse an umbrella directory declaration.
25280b57cec5SDimitry Andric ///
25290b57cec5SDimitry Andric ///   umbrella-dir-declaration:
25300b57cec5SDimitry Andric ///     umbrella string-literal
25310b57cec5SDimitry Andric void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
25320b57cec5SDimitry Andric   // Parse the directory name.
25330b57cec5SDimitry Andric   if (!Tok.is(MMToken::StringLiteral)) {
25340b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
25350b57cec5SDimitry Andric       << "umbrella";
25360b57cec5SDimitry Andric     HadError = true;
25370b57cec5SDimitry Andric     return;
25380b57cec5SDimitry Andric   }
25390b57cec5SDimitry Andric 
25405ffd83dbSDimitry Andric   std::string DirName = std::string(Tok.getString());
2541fe6060f1SDimitry Andric   std::string DirNameAsWritten = DirName;
25420b57cec5SDimitry Andric   SourceLocation DirNameLoc = consumeToken();
25430b57cec5SDimitry Andric 
25440b57cec5SDimitry Andric   // Check whether we already have an umbrella.
25455f757f3fSDimitry Andric   if (!std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
25460b57cec5SDimitry Andric     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
25470b57cec5SDimitry Andric       << ActiveModule->getFullModuleName();
25480b57cec5SDimitry Andric     HadError = true;
25490b57cec5SDimitry Andric     return;
25500b57cec5SDimitry Andric   }
25510b57cec5SDimitry Andric 
25520b57cec5SDimitry Andric   // Look for this file.
255306c3fb27SDimitry Andric   OptionalDirectoryEntryRef Dir;
2554a7dea167SDimitry Andric   if (llvm::sys::path::is_absolute(DirName)) {
255506c3fb27SDimitry Andric     Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
2556a7dea167SDimitry Andric   } else {
25570b57cec5SDimitry Andric     SmallString<128> PathName;
255806c3fb27SDimitry Andric     PathName = Directory.getName();
25590b57cec5SDimitry Andric     llvm::sys::path::append(PathName, DirName);
256006c3fb27SDimitry Andric     Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(PathName);
25610b57cec5SDimitry Andric   }
25620b57cec5SDimitry Andric 
25630b57cec5SDimitry Andric   if (!Dir) {
25640b57cec5SDimitry Andric     Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
25650b57cec5SDimitry Andric       << DirName;
25660b57cec5SDimitry Andric     return;
25670b57cec5SDimitry Andric   }
25680b57cec5SDimitry Andric 
25690b57cec5SDimitry Andric   if (UsesRequiresExcludedHack.count(ActiveModule)) {
25700b57cec5SDimitry Andric     // Mark this header 'textual' (see doc comment for
25710b57cec5SDimitry Andric     // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
25720b57cec5SDimitry Andric     // directory is relatively expensive, in practice this only applies to the
25730b57cec5SDimitry Andric     // uncommonly used Tcl module on Darwin platforms.
25740b57cec5SDimitry Andric     std::error_code EC;
25750b57cec5SDimitry Andric     SmallVector<Module::Header, 6> Headers;
25760b57cec5SDimitry Andric     llvm::vfs::FileSystem &FS =
25770b57cec5SDimitry Andric         SourceMgr.getFileManager().getVirtualFileSystem();
25780b57cec5SDimitry Andric     for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
25790b57cec5SDimitry Andric          I != E && !EC; I.increment(EC)) {
2580bdd1243dSDimitry Andric       if (auto FE = SourceMgr.getFileManager().getOptionalFileRef(I->path())) {
258106c3fb27SDimitry Andric         Module::Header Header = {"", std::string(I->path()), *FE};
25820b57cec5SDimitry Andric         Headers.push_back(std::move(Header));
25830b57cec5SDimitry Andric       }
25840b57cec5SDimitry Andric     }
25850b57cec5SDimitry Andric 
25860b57cec5SDimitry Andric     // Sort header paths so that the pcm doesn't depend on iteration order.
25875c16e71dSDimitry Andric     std::stable_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
25880b57cec5SDimitry Andric 
25890b57cec5SDimitry Andric     for (auto &Header : Headers)
25900b57cec5SDimitry Andric       Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
25910b57cec5SDimitry Andric     return;
25920b57cec5SDimitry Andric   }
25930b57cec5SDimitry Andric 
259406c3fb27SDimitry Andric   if (Module *OwningModule = Map.UmbrellaDirs[*Dir]) {
25950b57cec5SDimitry Andric     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
25960b57cec5SDimitry Andric       << OwningModule->getFullModuleName();
25970b57cec5SDimitry Andric     HadError = true;
25980b57cec5SDimitry Andric     return;
25990b57cec5SDimitry Andric   }
26000b57cec5SDimitry Andric 
26010b57cec5SDimitry Andric   // Record this umbrella directory.
260206c3fb27SDimitry Andric   Map.setUmbrellaDirAsWritten(ActiveModule, *Dir, DirNameAsWritten, DirName);
26030b57cec5SDimitry Andric }
26040b57cec5SDimitry Andric 
26050b57cec5SDimitry Andric /// Parse a module export declaration.
26060b57cec5SDimitry Andric ///
26070b57cec5SDimitry Andric ///   export-declaration:
26080b57cec5SDimitry Andric ///     'export' wildcard-module-id
26090b57cec5SDimitry Andric ///
26100b57cec5SDimitry Andric ///   wildcard-module-id:
26110b57cec5SDimitry Andric ///     identifier
26120b57cec5SDimitry Andric ///     '*'
26130b57cec5SDimitry Andric ///     identifier '.' wildcard-module-id
26140b57cec5SDimitry Andric void ModuleMapParser::parseExportDecl() {
26150b57cec5SDimitry Andric   assert(Tok.is(MMToken::ExportKeyword));
26160b57cec5SDimitry Andric   SourceLocation ExportLoc = consumeToken();
26170b57cec5SDimitry Andric 
26180b57cec5SDimitry Andric   // Parse the module-id with an optional wildcard at the end.
26190b57cec5SDimitry Andric   ModuleId ParsedModuleId;
26200b57cec5SDimitry Andric   bool Wildcard = false;
26210b57cec5SDimitry Andric   do {
26220b57cec5SDimitry Andric     // FIXME: Support string-literal module names here.
26230b57cec5SDimitry Andric     if (Tok.is(MMToken::Identifier)) {
26245ffd83dbSDimitry Andric       ParsedModuleId.push_back(
26255ffd83dbSDimitry Andric           std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
26260b57cec5SDimitry Andric       consumeToken();
26270b57cec5SDimitry Andric 
26280b57cec5SDimitry Andric       if (Tok.is(MMToken::Period)) {
26290b57cec5SDimitry Andric         consumeToken();
26300b57cec5SDimitry Andric         continue;
26310b57cec5SDimitry Andric       }
26320b57cec5SDimitry Andric 
26330b57cec5SDimitry Andric       break;
26340b57cec5SDimitry Andric     }
26350b57cec5SDimitry Andric 
26360b57cec5SDimitry Andric     if(Tok.is(MMToken::Star)) {
26370b57cec5SDimitry Andric       Wildcard = true;
26380b57cec5SDimitry Andric       consumeToken();
26390b57cec5SDimitry Andric       break;
26400b57cec5SDimitry Andric     }
26410b57cec5SDimitry Andric 
26420b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
26430b57cec5SDimitry Andric     HadError = true;
26440b57cec5SDimitry Andric     return;
26450b57cec5SDimitry Andric   } while (true);
26460b57cec5SDimitry Andric 
26470b57cec5SDimitry Andric   Module::UnresolvedExportDecl Unresolved = {
26480b57cec5SDimitry Andric     ExportLoc, ParsedModuleId, Wildcard
26490b57cec5SDimitry Andric   };
26500b57cec5SDimitry Andric   ActiveModule->UnresolvedExports.push_back(Unresolved);
26510b57cec5SDimitry Andric }
26520b57cec5SDimitry Andric 
26530b57cec5SDimitry Andric /// Parse a module export_as declaration.
26540b57cec5SDimitry Andric ///
26550b57cec5SDimitry Andric ///   export-as-declaration:
26560b57cec5SDimitry Andric ///     'export_as' identifier
26570b57cec5SDimitry Andric void ModuleMapParser::parseExportAsDecl() {
26580b57cec5SDimitry Andric   assert(Tok.is(MMToken::ExportAsKeyword));
26590b57cec5SDimitry Andric   consumeToken();
26600b57cec5SDimitry Andric 
26610b57cec5SDimitry Andric   if (!Tok.is(MMToken::Identifier)) {
26620b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
26630b57cec5SDimitry Andric     HadError = true;
26640b57cec5SDimitry Andric     return;
26650b57cec5SDimitry Andric   }
26660b57cec5SDimitry Andric 
26670b57cec5SDimitry Andric   if (ActiveModule->Parent) {
26680b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
26690b57cec5SDimitry Andric     consumeToken();
26700b57cec5SDimitry Andric     return;
26710b57cec5SDimitry Andric   }
26720b57cec5SDimitry Andric 
26730b57cec5SDimitry Andric   if (!ActiveModule->ExportAsModule.empty()) {
26740b57cec5SDimitry Andric     if (ActiveModule->ExportAsModule == Tok.getString()) {
26750b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
26760b57cec5SDimitry Andric         << ActiveModule->Name << Tok.getString();
26770b57cec5SDimitry Andric     } else {
26780b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
26790b57cec5SDimitry Andric         << ActiveModule->Name << ActiveModule->ExportAsModule
26800b57cec5SDimitry Andric         << Tok.getString();
26810b57cec5SDimitry Andric     }
26820b57cec5SDimitry Andric   }
26830b57cec5SDimitry Andric 
26845ffd83dbSDimitry Andric   ActiveModule->ExportAsModule = std::string(Tok.getString());
26850b57cec5SDimitry Andric   Map.addLinkAsDependency(ActiveModule);
26860b57cec5SDimitry Andric 
26870b57cec5SDimitry Andric   consumeToken();
26880b57cec5SDimitry Andric }
26890b57cec5SDimitry Andric 
26900b57cec5SDimitry Andric /// Parse a module use declaration.
26910b57cec5SDimitry Andric ///
26920b57cec5SDimitry Andric ///   use-declaration:
26930b57cec5SDimitry Andric ///     'use' wildcard-module-id
26940b57cec5SDimitry Andric void ModuleMapParser::parseUseDecl() {
26950b57cec5SDimitry Andric   assert(Tok.is(MMToken::UseKeyword));
26960b57cec5SDimitry Andric   auto KWLoc = consumeToken();
26970b57cec5SDimitry Andric   // Parse the module-id.
26980b57cec5SDimitry Andric   ModuleId ParsedModuleId;
26990b57cec5SDimitry Andric   parseModuleId(ParsedModuleId);
27000b57cec5SDimitry Andric 
27010b57cec5SDimitry Andric   if (ActiveModule->Parent)
27020b57cec5SDimitry Andric     Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
27030b57cec5SDimitry Andric   else
27040b57cec5SDimitry Andric     ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
27050b57cec5SDimitry Andric }
27060b57cec5SDimitry Andric 
27070b57cec5SDimitry Andric /// Parse a link declaration.
27080b57cec5SDimitry Andric ///
27090b57cec5SDimitry Andric ///   module-declaration:
27100b57cec5SDimitry Andric ///     'link' 'framework'[opt] string-literal
27110b57cec5SDimitry Andric void ModuleMapParser::parseLinkDecl() {
27120b57cec5SDimitry Andric   assert(Tok.is(MMToken::LinkKeyword));
27130b57cec5SDimitry Andric   SourceLocation LinkLoc = consumeToken();
27140b57cec5SDimitry Andric 
27150b57cec5SDimitry Andric   // Parse the optional 'framework' keyword.
27160b57cec5SDimitry Andric   bool IsFramework = false;
27170b57cec5SDimitry Andric   if (Tok.is(MMToken::FrameworkKeyword)) {
27180b57cec5SDimitry Andric     consumeToken();
27190b57cec5SDimitry Andric     IsFramework = true;
27200b57cec5SDimitry Andric   }
27210b57cec5SDimitry Andric 
27220b57cec5SDimitry Andric   // Parse the library name
27230b57cec5SDimitry Andric   if (!Tok.is(MMToken::StringLiteral)) {
27240b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
27250b57cec5SDimitry Andric       << IsFramework << SourceRange(LinkLoc);
27260b57cec5SDimitry Andric     HadError = true;
27270b57cec5SDimitry Andric     return;
27280b57cec5SDimitry Andric   }
27290b57cec5SDimitry Andric 
27305ffd83dbSDimitry Andric   std::string LibraryName = std::string(Tok.getString());
27310b57cec5SDimitry Andric   consumeToken();
27320b57cec5SDimitry Andric   ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
27330b57cec5SDimitry Andric                                                             IsFramework));
27340b57cec5SDimitry Andric }
27350b57cec5SDimitry Andric 
27360b57cec5SDimitry Andric /// Parse a configuration macro declaration.
27370b57cec5SDimitry Andric ///
27380b57cec5SDimitry Andric ///   module-declaration:
27390b57cec5SDimitry Andric ///     'config_macros' attributes[opt] config-macro-list?
27400b57cec5SDimitry Andric ///
27410b57cec5SDimitry Andric ///   config-macro-list:
27420b57cec5SDimitry Andric ///     identifier (',' identifier)?
27430b57cec5SDimitry Andric void ModuleMapParser::parseConfigMacros() {
27440b57cec5SDimitry Andric   assert(Tok.is(MMToken::ConfigMacros));
27450b57cec5SDimitry Andric   SourceLocation ConfigMacrosLoc = consumeToken();
27460b57cec5SDimitry Andric 
27470b57cec5SDimitry Andric   // Only top-level modules can have configuration macros.
27480b57cec5SDimitry Andric   if (ActiveModule->Parent) {
27490b57cec5SDimitry Andric     Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
27500b57cec5SDimitry Andric   }
27510b57cec5SDimitry Andric 
27520b57cec5SDimitry Andric   // Parse the optional attributes.
27530b57cec5SDimitry Andric   Attributes Attrs;
27540b57cec5SDimitry Andric   if (parseOptionalAttributes(Attrs))
27550b57cec5SDimitry Andric     return;
27560b57cec5SDimitry Andric 
27570b57cec5SDimitry Andric   if (Attrs.IsExhaustive && !ActiveModule->Parent) {
27580b57cec5SDimitry Andric     ActiveModule->ConfigMacrosExhaustive = true;
27590b57cec5SDimitry Andric   }
27600b57cec5SDimitry Andric 
27610b57cec5SDimitry Andric   // If we don't have an identifier, we're done.
27620b57cec5SDimitry Andric   // FIXME: Support macros with the same name as a keyword here.
27630b57cec5SDimitry Andric   if (!Tok.is(MMToken::Identifier))
27640b57cec5SDimitry Andric     return;
27650b57cec5SDimitry Andric 
27660b57cec5SDimitry Andric   // Consume the first identifier.
27670b57cec5SDimitry Andric   if (!ActiveModule->Parent) {
27680b57cec5SDimitry Andric     ActiveModule->ConfigMacros.push_back(Tok.getString().str());
27690b57cec5SDimitry Andric   }
27700b57cec5SDimitry Andric   consumeToken();
27710b57cec5SDimitry Andric 
27720b57cec5SDimitry Andric   do {
27730b57cec5SDimitry Andric     // If there's a comma, consume it.
27740b57cec5SDimitry Andric     if (!Tok.is(MMToken::Comma))
27750b57cec5SDimitry Andric       break;
27760b57cec5SDimitry Andric     consumeToken();
27770b57cec5SDimitry Andric 
27780b57cec5SDimitry Andric     // We expect to see a macro name here.
27790b57cec5SDimitry Andric     // FIXME: Support macros with the same name as a keyword here.
27800b57cec5SDimitry Andric     if (!Tok.is(MMToken::Identifier)) {
27810b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
27820b57cec5SDimitry Andric       break;
27830b57cec5SDimitry Andric     }
27840b57cec5SDimitry Andric 
27850b57cec5SDimitry Andric     // Consume the macro name.
27860b57cec5SDimitry Andric     if (!ActiveModule->Parent) {
27870b57cec5SDimitry Andric       ActiveModule->ConfigMacros.push_back(Tok.getString().str());
27880b57cec5SDimitry Andric     }
27890b57cec5SDimitry Andric     consumeToken();
27900b57cec5SDimitry Andric   } while (true);
27910b57cec5SDimitry Andric }
27920b57cec5SDimitry Andric 
27930b57cec5SDimitry Andric /// Format a module-id into a string.
27940b57cec5SDimitry Andric static std::string formatModuleId(const ModuleId &Id) {
27950b57cec5SDimitry Andric   std::string result;
27960b57cec5SDimitry Andric   {
27970b57cec5SDimitry Andric     llvm::raw_string_ostream OS(result);
27980b57cec5SDimitry Andric 
27990b57cec5SDimitry Andric     for (unsigned I = 0, N = Id.size(); I != N; ++I) {
28000b57cec5SDimitry Andric       if (I)
28010b57cec5SDimitry Andric         OS << ".";
28020b57cec5SDimitry Andric       OS << Id[I].first;
28030b57cec5SDimitry Andric     }
28040b57cec5SDimitry Andric   }
28050b57cec5SDimitry Andric 
28060b57cec5SDimitry Andric   return result;
28070b57cec5SDimitry Andric }
28080b57cec5SDimitry Andric 
28090b57cec5SDimitry Andric /// Parse a conflict declaration.
28100b57cec5SDimitry Andric ///
28110b57cec5SDimitry Andric ///   module-declaration:
28120b57cec5SDimitry Andric ///     'conflict' module-id ',' string-literal
28130b57cec5SDimitry Andric void ModuleMapParser::parseConflict() {
28140b57cec5SDimitry Andric   assert(Tok.is(MMToken::Conflict));
28150b57cec5SDimitry Andric   SourceLocation ConflictLoc = consumeToken();
28160b57cec5SDimitry Andric   Module::UnresolvedConflict Conflict;
28170b57cec5SDimitry Andric 
28180b57cec5SDimitry Andric   // Parse the module-id.
28190b57cec5SDimitry Andric   if (parseModuleId(Conflict.Id))
28200b57cec5SDimitry Andric     return;
28210b57cec5SDimitry Andric 
28220b57cec5SDimitry Andric   // Parse the ','.
28230b57cec5SDimitry Andric   if (!Tok.is(MMToken::Comma)) {
28240b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
28250b57cec5SDimitry Andric       << SourceRange(ConflictLoc);
28260b57cec5SDimitry Andric     return;
28270b57cec5SDimitry Andric   }
28280b57cec5SDimitry Andric   consumeToken();
28290b57cec5SDimitry Andric 
28300b57cec5SDimitry Andric   // Parse the message.
28310b57cec5SDimitry Andric   if (!Tok.is(MMToken::StringLiteral)) {
28320b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
28330b57cec5SDimitry Andric       << formatModuleId(Conflict.Id);
28340b57cec5SDimitry Andric     return;
28350b57cec5SDimitry Andric   }
28360b57cec5SDimitry Andric   Conflict.Message = Tok.getString().str();
28370b57cec5SDimitry Andric   consumeToken();
28380b57cec5SDimitry Andric 
28390b57cec5SDimitry Andric   // Add this unresolved conflict.
28400b57cec5SDimitry Andric   ActiveModule->UnresolvedConflicts.push_back(Conflict);
28410b57cec5SDimitry Andric }
28420b57cec5SDimitry Andric 
28430b57cec5SDimitry Andric /// Parse an inferred module declaration (wildcard modules).
28440b57cec5SDimitry Andric ///
28450b57cec5SDimitry Andric ///   module-declaration:
28460b57cec5SDimitry Andric ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
28470b57cec5SDimitry Andric ///       { inferred-module-member* }
28480b57cec5SDimitry Andric ///
28490b57cec5SDimitry Andric ///   inferred-module-member:
28500b57cec5SDimitry Andric ///     'export' '*'
28510b57cec5SDimitry Andric ///     'exclude' identifier
28520b57cec5SDimitry Andric void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
28530b57cec5SDimitry Andric   assert(Tok.is(MMToken::Star));
28540b57cec5SDimitry Andric   SourceLocation StarLoc = consumeToken();
28550b57cec5SDimitry Andric   bool Failed = false;
28560b57cec5SDimitry Andric 
28570b57cec5SDimitry Andric   // Inferred modules must be submodules.
28580b57cec5SDimitry Andric   if (!ActiveModule && !Framework) {
28590b57cec5SDimitry Andric     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
28600b57cec5SDimitry Andric     Failed = true;
28610b57cec5SDimitry Andric   }
28620b57cec5SDimitry Andric 
28630b57cec5SDimitry Andric   if (ActiveModule) {
28640b57cec5SDimitry Andric     // Inferred modules must have umbrella directories.
28650b57cec5SDimitry Andric     if (!Failed && ActiveModule->IsAvailable &&
286606c3fb27SDimitry Andric         !ActiveModule->getEffectiveUmbrellaDir()) {
28670b57cec5SDimitry Andric       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
28680b57cec5SDimitry Andric       Failed = true;
28690b57cec5SDimitry Andric     }
28700b57cec5SDimitry Andric 
28710b57cec5SDimitry Andric     // Check for redefinition of an inferred module.
28720b57cec5SDimitry Andric     if (!Failed && ActiveModule->InferSubmodules) {
28730b57cec5SDimitry Andric       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
28740b57cec5SDimitry Andric       if (ActiveModule->InferredSubmoduleLoc.isValid())
28750b57cec5SDimitry Andric         Diags.Report(ActiveModule->InferredSubmoduleLoc,
28760b57cec5SDimitry Andric                      diag::note_mmap_prev_definition);
28770b57cec5SDimitry Andric       Failed = true;
28780b57cec5SDimitry Andric     }
28790b57cec5SDimitry Andric 
28800b57cec5SDimitry Andric     // Check for the 'framework' keyword, which is not permitted here.
28810b57cec5SDimitry Andric     if (Framework) {
28820b57cec5SDimitry Andric       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
28830b57cec5SDimitry Andric       Framework = false;
28840b57cec5SDimitry Andric     }
28850b57cec5SDimitry Andric   } else if (Explicit) {
28860b57cec5SDimitry Andric     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
28870b57cec5SDimitry Andric     Explicit = false;
28880b57cec5SDimitry Andric   }
28890b57cec5SDimitry Andric 
28900b57cec5SDimitry Andric   // If there were any problems with this inferred submodule, skip its body.
28910b57cec5SDimitry Andric   if (Failed) {
28920b57cec5SDimitry Andric     if (Tok.is(MMToken::LBrace)) {
28930b57cec5SDimitry Andric       consumeToken();
28940b57cec5SDimitry Andric       skipUntil(MMToken::RBrace);
28950b57cec5SDimitry Andric       if (Tok.is(MMToken::RBrace))
28960b57cec5SDimitry Andric         consumeToken();
28970b57cec5SDimitry Andric     }
28980b57cec5SDimitry Andric     HadError = true;
28990b57cec5SDimitry Andric     return;
29000b57cec5SDimitry Andric   }
29010b57cec5SDimitry Andric 
29020b57cec5SDimitry Andric   // Parse optional attributes.
29030b57cec5SDimitry Andric   Attributes Attrs;
29040b57cec5SDimitry Andric   if (parseOptionalAttributes(Attrs))
29050b57cec5SDimitry Andric     return;
29060b57cec5SDimitry Andric 
29070b57cec5SDimitry Andric   if (ActiveModule) {
29080b57cec5SDimitry Andric     // Note that we have an inferred submodule.
29090b57cec5SDimitry Andric     ActiveModule->InferSubmodules = true;
29100b57cec5SDimitry Andric     ActiveModule->InferredSubmoduleLoc = StarLoc;
29110b57cec5SDimitry Andric     ActiveModule->InferExplicitSubmodules = Explicit;
29120b57cec5SDimitry Andric   } else {
29130b57cec5SDimitry Andric     // We'll be inferring framework modules for this directory.
29140b57cec5SDimitry Andric     Map.InferredDirectories[Directory].InferModules = true;
29150b57cec5SDimitry Andric     Map.InferredDirectories[Directory].Attrs = Attrs;
2916*0fca6ea1SDimitry Andric     Map.InferredDirectories[Directory].ModuleMapFID = ModuleMapFID;
29170b57cec5SDimitry Andric     // FIXME: Handle the 'framework' keyword.
29180b57cec5SDimitry Andric   }
29190b57cec5SDimitry Andric 
29200b57cec5SDimitry Andric   // Parse the opening brace.
29210b57cec5SDimitry Andric   if (!Tok.is(MMToken::LBrace)) {
29220b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
29230b57cec5SDimitry Andric     HadError = true;
29240b57cec5SDimitry Andric     return;
29250b57cec5SDimitry Andric   }
29260b57cec5SDimitry Andric   SourceLocation LBraceLoc = consumeToken();
29270b57cec5SDimitry Andric 
29280b57cec5SDimitry Andric   // Parse the body of the inferred submodule.
29290b57cec5SDimitry Andric   bool Done = false;
29300b57cec5SDimitry Andric   do {
29310b57cec5SDimitry Andric     switch (Tok.Kind) {
29320b57cec5SDimitry Andric     case MMToken::EndOfFile:
29330b57cec5SDimitry Andric     case MMToken::RBrace:
29340b57cec5SDimitry Andric       Done = true;
29350b57cec5SDimitry Andric       break;
29360b57cec5SDimitry Andric 
29370b57cec5SDimitry Andric     case MMToken::ExcludeKeyword:
29380b57cec5SDimitry Andric       if (ActiveModule) {
29390b57cec5SDimitry Andric         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
29400b57cec5SDimitry Andric           << (ActiveModule != nullptr);
29410b57cec5SDimitry Andric         consumeToken();
29420b57cec5SDimitry Andric         break;
29430b57cec5SDimitry Andric       }
29440b57cec5SDimitry Andric 
29450b57cec5SDimitry Andric       consumeToken();
29460b57cec5SDimitry Andric       // FIXME: Support string-literal module names here.
29470b57cec5SDimitry Andric       if (!Tok.is(MMToken::Identifier)) {
29480b57cec5SDimitry Andric         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
29490b57cec5SDimitry Andric         break;
29500b57cec5SDimitry Andric       }
29510b57cec5SDimitry Andric 
29525ffd83dbSDimitry Andric       Map.InferredDirectories[Directory].ExcludedModules.push_back(
29535ffd83dbSDimitry Andric           std::string(Tok.getString()));
29540b57cec5SDimitry Andric       consumeToken();
29550b57cec5SDimitry Andric       break;
29560b57cec5SDimitry Andric 
29570b57cec5SDimitry Andric     case MMToken::ExportKeyword:
29580b57cec5SDimitry Andric       if (!ActiveModule) {
29590b57cec5SDimitry Andric         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
29600b57cec5SDimitry Andric           << (ActiveModule != nullptr);
29610b57cec5SDimitry Andric         consumeToken();
29620b57cec5SDimitry Andric         break;
29630b57cec5SDimitry Andric       }
29640b57cec5SDimitry Andric 
29650b57cec5SDimitry Andric       consumeToken();
29660b57cec5SDimitry Andric       if (Tok.is(MMToken::Star))
29670b57cec5SDimitry Andric         ActiveModule->InferExportWildcard = true;
29680b57cec5SDimitry Andric       else
29690b57cec5SDimitry Andric         Diags.Report(Tok.getLocation(),
29700b57cec5SDimitry Andric                      diag::err_mmap_expected_export_wildcard);
29710b57cec5SDimitry Andric       consumeToken();
29720b57cec5SDimitry Andric       break;
29730b57cec5SDimitry Andric 
29740b57cec5SDimitry Andric     case MMToken::ExplicitKeyword:
29750b57cec5SDimitry Andric     case MMToken::ModuleKeyword:
29760b57cec5SDimitry Andric     case MMToken::HeaderKeyword:
29770b57cec5SDimitry Andric     case MMToken::PrivateKeyword:
29780b57cec5SDimitry Andric     case MMToken::UmbrellaKeyword:
29790b57cec5SDimitry Andric     default:
29800b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
29810b57cec5SDimitry Andric           << (ActiveModule != nullptr);
29820b57cec5SDimitry Andric       consumeToken();
29830b57cec5SDimitry Andric       break;
29840b57cec5SDimitry Andric     }
29850b57cec5SDimitry Andric   } while (!Done);
29860b57cec5SDimitry Andric 
29870b57cec5SDimitry Andric   if (Tok.is(MMToken::RBrace))
29880b57cec5SDimitry Andric     consumeToken();
29890b57cec5SDimitry Andric   else {
29900b57cec5SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
29910b57cec5SDimitry Andric     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
29920b57cec5SDimitry Andric     HadError = true;
29930b57cec5SDimitry Andric   }
29940b57cec5SDimitry Andric }
29950b57cec5SDimitry Andric 
29960b57cec5SDimitry Andric /// Parse optional attributes.
29970b57cec5SDimitry Andric ///
29980b57cec5SDimitry Andric ///   attributes:
29990b57cec5SDimitry Andric ///     attribute attributes
30000b57cec5SDimitry Andric ///     attribute
30010b57cec5SDimitry Andric ///
30020b57cec5SDimitry Andric ///   attribute:
30030b57cec5SDimitry Andric ///     [ identifier ]
30040b57cec5SDimitry Andric ///
30050b57cec5SDimitry Andric /// \param Attrs Will be filled in with the parsed attributes.
30060b57cec5SDimitry Andric ///
30070b57cec5SDimitry Andric /// \returns true if an error occurred, false otherwise.
30080b57cec5SDimitry Andric bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
30090b57cec5SDimitry Andric   bool HadError = false;
30100b57cec5SDimitry Andric 
30110b57cec5SDimitry Andric   while (Tok.is(MMToken::LSquare)) {
30120b57cec5SDimitry Andric     // Consume the '['.
30130b57cec5SDimitry Andric     SourceLocation LSquareLoc = consumeToken();
30140b57cec5SDimitry Andric 
30150b57cec5SDimitry Andric     // Check whether we have an attribute name here.
30160b57cec5SDimitry Andric     if (!Tok.is(MMToken::Identifier)) {
30170b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
30180b57cec5SDimitry Andric       skipUntil(MMToken::RSquare);
30190b57cec5SDimitry Andric       if (Tok.is(MMToken::RSquare))
30200b57cec5SDimitry Andric         consumeToken();
30210b57cec5SDimitry Andric       HadError = true;
30220b57cec5SDimitry Andric     }
30230b57cec5SDimitry Andric 
30240b57cec5SDimitry Andric     // Decode the attribute name.
30250b57cec5SDimitry Andric     AttributeKind Attribute
30260b57cec5SDimitry Andric       = llvm::StringSwitch<AttributeKind>(Tok.getString())
30270b57cec5SDimitry Andric           .Case("exhaustive", AT_exhaustive)
30280b57cec5SDimitry Andric           .Case("extern_c", AT_extern_c)
30290b57cec5SDimitry Andric           .Case("no_undeclared_includes", AT_no_undeclared_includes)
30300b57cec5SDimitry Andric           .Case("system", AT_system)
30310b57cec5SDimitry Andric           .Default(AT_unknown);
30320b57cec5SDimitry Andric     switch (Attribute) {
30330b57cec5SDimitry Andric     case AT_unknown:
30340b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
30350b57cec5SDimitry Andric         << Tok.getString();
30360b57cec5SDimitry Andric       break;
30370b57cec5SDimitry Andric 
30380b57cec5SDimitry Andric     case AT_system:
30390b57cec5SDimitry Andric       Attrs.IsSystem = true;
30400b57cec5SDimitry Andric       break;
30410b57cec5SDimitry Andric 
30420b57cec5SDimitry Andric     case AT_extern_c:
30430b57cec5SDimitry Andric       Attrs.IsExternC = true;
30440b57cec5SDimitry Andric       break;
30450b57cec5SDimitry Andric 
30460b57cec5SDimitry Andric     case AT_exhaustive:
30470b57cec5SDimitry Andric       Attrs.IsExhaustive = true;
30480b57cec5SDimitry Andric       break;
30490b57cec5SDimitry Andric 
30500b57cec5SDimitry Andric     case AT_no_undeclared_includes:
30510b57cec5SDimitry Andric       Attrs.NoUndeclaredIncludes = true;
30520b57cec5SDimitry Andric       break;
30530b57cec5SDimitry Andric     }
30540b57cec5SDimitry Andric     consumeToken();
30550b57cec5SDimitry Andric 
30560b57cec5SDimitry Andric     // Consume the ']'.
30570b57cec5SDimitry Andric     if (!Tok.is(MMToken::RSquare)) {
30580b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
30590b57cec5SDimitry Andric       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
30600b57cec5SDimitry Andric       skipUntil(MMToken::RSquare);
30610b57cec5SDimitry Andric       HadError = true;
30620b57cec5SDimitry Andric     }
30630b57cec5SDimitry Andric 
30640b57cec5SDimitry Andric     if (Tok.is(MMToken::RSquare))
30650b57cec5SDimitry Andric       consumeToken();
30660b57cec5SDimitry Andric   }
30670b57cec5SDimitry Andric 
30680b57cec5SDimitry Andric   return HadError;
30690b57cec5SDimitry Andric }
30700b57cec5SDimitry Andric 
30710b57cec5SDimitry Andric /// Parse a module map file.
30720b57cec5SDimitry Andric ///
30730b57cec5SDimitry Andric ///   module-map-file:
30740b57cec5SDimitry Andric ///     module-declaration*
30750b57cec5SDimitry Andric bool ModuleMapParser::parseModuleMapFile() {
30760b57cec5SDimitry Andric   do {
30770b57cec5SDimitry Andric     switch (Tok.Kind) {
30780b57cec5SDimitry Andric     case MMToken::EndOfFile:
30790b57cec5SDimitry Andric       return HadError;
30800b57cec5SDimitry Andric 
30810b57cec5SDimitry Andric     case MMToken::ExplicitKeyword:
30820b57cec5SDimitry Andric     case MMToken::ExternKeyword:
30830b57cec5SDimitry Andric     case MMToken::ModuleKeyword:
30840b57cec5SDimitry Andric     case MMToken::FrameworkKeyword:
30850b57cec5SDimitry Andric       parseModuleDecl();
30860b57cec5SDimitry Andric       break;
30870b57cec5SDimitry Andric 
30880b57cec5SDimitry Andric     case MMToken::Comma:
30890b57cec5SDimitry Andric     case MMToken::ConfigMacros:
30900b57cec5SDimitry Andric     case MMToken::Conflict:
30910b57cec5SDimitry Andric     case MMToken::Exclaim:
30920b57cec5SDimitry Andric     case MMToken::ExcludeKeyword:
30930b57cec5SDimitry Andric     case MMToken::ExportKeyword:
30940b57cec5SDimitry Andric     case MMToken::ExportAsKeyword:
30950b57cec5SDimitry Andric     case MMToken::HeaderKeyword:
30960b57cec5SDimitry Andric     case MMToken::Identifier:
30970b57cec5SDimitry Andric     case MMToken::LBrace:
30980b57cec5SDimitry Andric     case MMToken::LinkKeyword:
30990b57cec5SDimitry Andric     case MMToken::LSquare:
31000b57cec5SDimitry Andric     case MMToken::Period:
31010b57cec5SDimitry Andric     case MMToken::PrivateKeyword:
31020b57cec5SDimitry Andric     case MMToken::RBrace:
31030b57cec5SDimitry Andric     case MMToken::RSquare:
31040b57cec5SDimitry Andric     case MMToken::RequiresKeyword:
31050b57cec5SDimitry Andric     case MMToken::Star:
31060b57cec5SDimitry Andric     case MMToken::StringLiteral:
31070b57cec5SDimitry Andric     case MMToken::IntegerLiteral:
31080b57cec5SDimitry Andric     case MMToken::TextualKeyword:
31090b57cec5SDimitry Andric     case MMToken::UmbrellaKeyword:
31100b57cec5SDimitry Andric     case MMToken::UseKeyword:
31110b57cec5SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
31120b57cec5SDimitry Andric       HadError = true;
31130b57cec5SDimitry Andric       consumeToken();
31140b57cec5SDimitry Andric       break;
31150b57cec5SDimitry Andric     }
31160b57cec5SDimitry Andric   } while (true);
31170b57cec5SDimitry Andric }
31180b57cec5SDimitry Andric 
31195f757f3fSDimitry Andric bool ModuleMap::parseModuleMapFile(FileEntryRef File, bool IsSystem,
312006c3fb27SDimitry Andric                                    DirectoryEntryRef Dir, FileID ID,
31210b57cec5SDimitry Andric                                    unsigned *Offset,
31220b57cec5SDimitry Andric                                    SourceLocation ExternModuleLoc) {
31230b57cec5SDimitry Andric   assert(Target && "Missing target information");
31240b57cec5SDimitry Andric   llvm::DenseMap<const FileEntry *, bool>::iterator Known
31250b57cec5SDimitry Andric     = ParsedModuleMap.find(File);
31260b57cec5SDimitry Andric   if (Known != ParsedModuleMap.end())
31270b57cec5SDimitry Andric     return Known->second;
31280b57cec5SDimitry Andric 
31290b57cec5SDimitry Andric   // If the module map file wasn't already entered, do so now.
31300b57cec5SDimitry Andric   if (ID.isInvalid()) {
31310b57cec5SDimitry Andric     auto FileCharacter =
31320b57cec5SDimitry Andric         IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
31330b57cec5SDimitry Andric     ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
31340b57cec5SDimitry Andric   }
31350b57cec5SDimitry Andric 
31360b57cec5SDimitry Andric   assert(Target && "Missing target information");
3137bdd1243dSDimitry Andric   std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
31380b57cec5SDimitry Andric   if (!Buffer)
31390b57cec5SDimitry Andric     return ParsedModuleMap[File] = true;
31400b57cec5SDimitry Andric   assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
31410b57cec5SDimitry Andric          "invalid buffer offset");
31420b57cec5SDimitry Andric 
31430b57cec5SDimitry Andric   // Parse this module map file.
31440b57cec5SDimitry Andric   Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
31450b57cec5SDimitry Andric           Buffer->getBufferStart(),
31460b57cec5SDimitry Andric           Buffer->getBufferStart() + (Offset ? *Offset : 0),
31470b57cec5SDimitry Andric           Buffer->getBufferEnd());
31480b57cec5SDimitry Andric   SourceLocation Start = L.getSourceLocation();
3149*0fca6ea1SDimitry Andric   ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, ID, Dir, IsSystem);
31500b57cec5SDimitry Andric   bool Result = Parser.parseModuleMapFile();
31510b57cec5SDimitry Andric   ParsedModuleMap[File] = Result;
31520b57cec5SDimitry Andric 
31530b57cec5SDimitry Andric   if (Offset) {
31540b57cec5SDimitry Andric     auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
31550b57cec5SDimitry Andric     assert(Loc.first == ID && "stopped in a different file?");
31560b57cec5SDimitry Andric     *Offset = Loc.second;
31570b57cec5SDimitry Andric   }
31580b57cec5SDimitry Andric 
31590b57cec5SDimitry Andric   // Notify callbacks that we parsed it.
31600b57cec5SDimitry Andric   for (const auto &Cb : Callbacks)
31615f757f3fSDimitry Andric     Cb->moduleMapFileRead(Start, File, IsSystem);
31620b57cec5SDimitry Andric 
31630b57cec5SDimitry Andric   return Result;
31640b57cec5SDimitry Andric }
3165