xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/Lex/ModuleMap.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===- ModuleMap.cpp - Describe the layout of modules ---------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This file defines the ModuleMap implementation, which describes the layout
107330f729Sjoerg // of a module as it relates to headers.
117330f729Sjoerg //
127330f729Sjoerg //===----------------------------------------------------------------------===//
137330f729Sjoerg 
147330f729Sjoerg #include "clang/Lex/ModuleMap.h"
157330f729Sjoerg #include "clang/Basic/CharInfo.h"
167330f729Sjoerg #include "clang/Basic/Diagnostic.h"
177330f729Sjoerg #include "clang/Basic/FileManager.h"
187330f729Sjoerg #include "clang/Basic/LLVM.h"
197330f729Sjoerg #include "clang/Basic/LangOptions.h"
207330f729Sjoerg #include "clang/Basic/Module.h"
217330f729Sjoerg #include "clang/Basic/SourceLocation.h"
227330f729Sjoerg #include "clang/Basic/SourceManager.h"
237330f729Sjoerg #include "clang/Basic/TargetInfo.h"
247330f729Sjoerg #include "clang/Lex/HeaderSearch.h"
257330f729Sjoerg #include "clang/Lex/HeaderSearchOptions.h"
267330f729Sjoerg #include "clang/Lex/LexDiagnostic.h"
277330f729Sjoerg #include "clang/Lex/Lexer.h"
287330f729Sjoerg #include "clang/Lex/LiteralSupport.h"
297330f729Sjoerg #include "clang/Lex/Token.h"
307330f729Sjoerg #include "llvm/ADT/DenseMap.h"
317330f729Sjoerg #include "llvm/ADT/None.h"
327330f729Sjoerg #include "llvm/ADT/STLExtras.h"
337330f729Sjoerg #include "llvm/ADT/SmallPtrSet.h"
347330f729Sjoerg #include "llvm/ADT/SmallString.h"
357330f729Sjoerg #include "llvm/ADT/SmallVector.h"
367330f729Sjoerg #include "llvm/ADT/StringMap.h"
377330f729Sjoerg #include "llvm/ADT/StringRef.h"
387330f729Sjoerg #include "llvm/ADT/StringSwitch.h"
397330f729Sjoerg #include "llvm/Support/Allocator.h"
407330f729Sjoerg #include "llvm/Support/Compiler.h"
417330f729Sjoerg #include "llvm/Support/ErrorHandling.h"
427330f729Sjoerg #include "llvm/Support/MemoryBuffer.h"
437330f729Sjoerg #include "llvm/Support/Path.h"
447330f729Sjoerg #include "llvm/Support/VirtualFileSystem.h"
457330f729Sjoerg #include "llvm/Support/raw_ostream.h"
467330f729Sjoerg #include <algorithm>
477330f729Sjoerg #include <cassert>
487330f729Sjoerg #include <cstdint>
497330f729Sjoerg #include <cstring>
507330f729Sjoerg #include <string>
517330f729Sjoerg #include <system_error>
527330f729Sjoerg #include <utility>
537330f729Sjoerg 
547330f729Sjoerg using namespace clang;
557330f729Sjoerg 
anchor()567330f729Sjoerg void ModuleMapCallbacks::anchor() {}
577330f729Sjoerg 
resolveLinkAsDependencies(Module * Mod)587330f729Sjoerg void ModuleMap::resolveLinkAsDependencies(Module *Mod) {
597330f729Sjoerg   auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name);
607330f729Sjoerg   if (PendingLinkAs != PendingLinkAsModule.end()) {
617330f729Sjoerg     for (auto &Name : PendingLinkAs->second) {
627330f729Sjoerg       auto *M = findModule(Name.getKey());
637330f729Sjoerg       if (M)
647330f729Sjoerg         M->UseExportAsModuleLinkName = true;
657330f729Sjoerg     }
667330f729Sjoerg   }
677330f729Sjoerg }
687330f729Sjoerg 
addLinkAsDependency(Module * Mod)697330f729Sjoerg void ModuleMap::addLinkAsDependency(Module *Mod) {
707330f729Sjoerg   if (findModule(Mod->ExportAsModule))
717330f729Sjoerg     Mod->UseExportAsModuleLinkName = true;
727330f729Sjoerg   else
737330f729Sjoerg     PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name);
747330f729Sjoerg }
757330f729Sjoerg 
headerRoleToKind(ModuleHeaderRole Role)767330f729Sjoerg Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
777330f729Sjoerg   switch ((int)Role) {
787330f729Sjoerg   default: llvm_unreachable("unknown header role");
797330f729Sjoerg   case NormalHeader:
807330f729Sjoerg     return Module::HK_Normal;
817330f729Sjoerg   case PrivateHeader:
827330f729Sjoerg     return Module::HK_Private;
837330f729Sjoerg   case TextualHeader:
847330f729Sjoerg     return Module::HK_Textual;
857330f729Sjoerg   case PrivateHeader | TextualHeader:
867330f729Sjoerg     return Module::HK_PrivateTextual;
877330f729Sjoerg   }
887330f729Sjoerg }
897330f729Sjoerg 
907330f729Sjoerg ModuleMap::ModuleHeaderRole
headerKindToRole(Module::HeaderKind Kind)917330f729Sjoerg ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
927330f729Sjoerg   switch ((int)Kind) {
937330f729Sjoerg   case Module::HK_Normal:
947330f729Sjoerg     return NormalHeader;
957330f729Sjoerg   case Module::HK_Private:
967330f729Sjoerg     return PrivateHeader;
977330f729Sjoerg   case Module::HK_Textual:
987330f729Sjoerg     return TextualHeader;
997330f729Sjoerg   case Module::HK_PrivateTextual:
1007330f729Sjoerg     return ModuleHeaderRole(PrivateHeader | TextualHeader);
1017330f729Sjoerg   case Module::HK_Excluded:
1027330f729Sjoerg     llvm_unreachable("unexpected header kind");
1037330f729Sjoerg   }
1047330f729Sjoerg   llvm_unreachable("unknown header kind");
1057330f729Sjoerg }
1067330f729Sjoerg 
1077330f729Sjoerg Module::ExportDecl
resolveExport(Module * Mod,const Module::UnresolvedExportDecl & Unresolved,bool Complain) const1087330f729Sjoerg ModuleMap::resolveExport(Module *Mod,
1097330f729Sjoerg                          const Module::UnresolvedExportDecl &Unresolved,
1107330f729Sjoerg                          bool Complain) const {
1117330f729Sjoerg   // We may have just a wildcard.
1127330f729Sjoerg   if (Unresolved.Id.empty()) {
1137330f729Sjoerg     assert(Unresolved.Wildcard && "Invalid unresolved export");
1147330f729Sjoerg     return Module::ExportDecl(nullptr, true);
1157330f729Sjoerg   }
1167330f729Sjoerg 
1177330f729Sjoerg   // Resolve the module-id.
1187330f729Sjoerg   Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
1197330f729Sjoerg   if (!Context)
1207330f729Sjoerg     return {};
1217330f729Sjoerg 
1227330f729Sjoerg   return Module::ExportDecl(Context, Unresolved.Wildcard);
1237330f729Sjoerg }
1247330f729Sjoerg 
resolveModuleId(const ModuleId & Id,Module * Mod,bool Complain) const1257330f729Sjoerg Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
1267330f729Sjoerg                                    bool Complain) const {
1277330f729Sjoerg   // Find the starting module.
1287330f729Sjoerg   Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
1297330f729Sjoerg   if (!Context) {
1307330f729Sjoerg     if (Complain)
1317330f729Sjoerg       Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
1327330f729Sjoerg       << Id[0].first << Mod->getFullModuleName();
1337330f729Sjoerg 
1347330f729Sjoerg     return nullptr;
1357330f729Sjoerg   }
1367330f729Sjoerg 
1377330f729Sjoerg   // Dig into the module path.
1387330f729Sjoerg   for (unsigned I = 1, N = Id.size(); I != N; ++I) {
1397330f729Sjoerg     Module *Sub = lookupModuleQualified(Id[I].first, Context);
1407330f729Sjoerg     if (!Sub) {
1417330f729Sjoerg       if (Complain)
1427330f729Sjoerg         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
1437330f729Sjoerg         << Id[I].first << Context->getFullModuleName()
1447330f729Sjoerg         << SourceRange(Id[0].second, Id[I-1].second);
1457330f729Sjoerg 
1467330f729Sjoerg       return nullptr;
1477330f729Sjoerg     }
1487330f729Sjoerg 
1497330f729Sjoerg     Context = Sub;
1507330f729Sjoerg   }
1517330f729Sjoerg 
1527330f729Sjoerg   return Context;
1537330f729Sjoerg }
1547330f729Sjoerg 
1557330f729Sjoerg /// Append to \p Paths the set of paths needed to get to the
1567330f729Sjoerg /// subframework in which the given module lives.
appendSubframeworkPaths(Module * Mod,SmallVectorImpl<char> & Path)1577330f729Sjoerg static void appendSubframeworkPaths(Module *Mod,
1587330f729Sjoerg                                     SmallVectorImpl<char> &Path) {
1597330f729Sjoerg   // Collect the framework names from the given module to the top-level module.
1607330f729Sjoerg   SmallVector<StringRef, 2> Paths;
1617330f729Sjoerg   for (; Mod; Mod = Mod->Parent) {
1627330f729Sjoerg     if (Mod->IsFramework)
1637330f729Sjoerg       Paths.push_back(Mod->Name);
1647330f729Sjoerg   }
1657330f729Sjoerg 
1667330f729Sjoerg   if (Paths.empty())
1677330f729Sjoerg     return;
1687330f729Sjoerg 
1697330f729Sjoerg   // Add Frameworks/Name.framework for each subframework.
1707330f729Sjoerg   for (unsigned I = Paths.size() - 1; I != 0; --I)
1717330f729Sjoerg     llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework");
1727330f729Sjoerg }
1737330f729Sjoerg 
findHeader(Module * M,const Module::UnresolvedHeaderDirective & Header,SmallVectorImpl<char> & RelativePathName,bool & NeedsFramework)174*e038c9c4Sjoerg Optional<FileEntryRef> ModuleMap::findHeader(
1757330f729Sjoerg     Module *M, const Module::UnresolvedHeaderDirective &Header,
1767330f729Sjoerg     SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) {
1777330f729Sjoerg   // Search for the header file within the module's home directory.
1787330f729Sjoerg   auto *Directory = M->Directory;
1797330f729Sjoerg   SmallString<128> FullPathName(Directory->getName());
1807330f729Sjoerg 
181*e038c9c4Sjoerg   auto GetFile = [&](StringRef Filename) -> Optional<FileEntryRef> {
182*e038c9c4Sjoerg     auto File =
183*e038c9c4Sjoerg         expectedToOptional(SourceMgr.getFileManager().getFileRef(Filename));
184*e038c9c4Sjoerg     if (!File || (Header.Size && File->getSize() != *Header.Size) ||
185*e038c9c4Sjoerg         (Header.ModTime && File->getModificationTime() != *Header.ModTime))
186*e038c9c4Sjoerg       return None;
1877330f729Sjoerg     return *File;
1887330f729Sjoerg   };
1897330f729Sjoerg 
190*e038c9c4Sjoerg   auto GetFrameworkFile = [&]() -> Optional<FileEntryRef> {
1917330f729Sjoerg     unsigned FullPathLength = FullPathName.size();
1927330f729Sjoerg     appendSubframeworkPaths(M, RelativePathName);
1937330f729Sjoerg     unsigned RelativePathLength = RelativePathName.size();
1947330f729Sjoerg 
1957330f729Sjoerg     // Check whether this file is in the public headers.
1967330f729Sjoerg     llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
1977330f729Sjoerg     llvm::sys::path::append(FullPathName, RelativePathName);
198*e038c9c4Sjoerg     if (auto File = GetFile(FullPathName))
1997330f729Sjoerg       return File;
2007330f729Sjoerg 
2017330f729Sjoerg     // Check whether this file is in the private headers.
2027330f729Sjoerg     // Ideally, private modules in the form 'FrameworkName.Private' should
2037330f729Sjoerg     // be defined as 'module FrameworkName.Private', and not as
2047330f729Sjoerg     // 'framework module FrameworkName.Private', since a 'Private.Framework'
2057330f729Sjoerg     // does not usually exist. However, since both are currently widely used
2067330f729Sjoerg     // for private modules, make sure we find the right path in both cases.
2077330f729Sjoerg     if (M->IsFramework && M->Name == "Private")
2087330f729Sjoerg       RelativePathName.clear();
2097330f729Sjoerg     else
2107330f729Sjoerg       RelativePathName.resize(RelativePathLength);
2117330f729Sjoerg     FullPathName.resize(FullPathLength);
2127330f729Sjoerg     llvm::sys::path::append(RelativePathName, "PrivateHeaders",
2137330f729Sjoerg                             Header.FileName);
2147330f729Sjoerg     llvm::sys::path::append(FullPathName, RelativePathName);
2157330f729Sjoerg     return GetFile(FullPathName);
2167330f729Sjoerg   };
2177330f729Sjoerg 
2187330f729Sjoerg   if (llvm::sys::path::is_absolute(Header.FileName)) {
2197330f729Sjoerg     RelativePathName.clear();
2207330f729Sjoerg     RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
2217330f729Sjoerg     return GetFile(Header.FileName);
2227330f729Sjoerg   }
2237330f729Sjoerg 
2247330f729Sjoerg   if (M->isPartOfFramework())
2257330f729Sjoerg     return GetFrameworkFile();
2267330f729Sjoerg 
2277330f729Sjoerg   // Lookup for normal headers.
2287330f729Sjoerg   llvm::sys::path::append(RelativePathName, Header.FileName);
2297330f729Sjoerg   llvm::sys::path::append(FullPathName, RelativePathName);
230*e038c9c4Sjoerg   auto NormalHdrFile = GetFile(FullPathName);
2317330f729Sjoerg 
232*e038c9c4Sjoerg   if (!NormalHdrFile && Directory->getName().endswith(".framework")) {
2337330f729Sjoerg     // The lack of 'framework' keyword in a module declaration it's a simple
2347330f729Sjoerg     // mistake we can diagnose when the header exists within the proper
2357330f729Sjoerg     // framework style path.
2367330f729Sjoerg     FullPathName.assign(Directory->getName());
2377330f729Sjoerg     RelativePathName.clear();
2387330f729Sjoerg     if (GetFrameworkFile()) {
2397330f729Sjoerg       Diags.Report(Header.FileNameLoc,
2407330f729Sjoerg                    diag::warn_mmap_incomplete_framework_module_declaration)
2417330f729Sjoerg           << Header.FileName << M->getFullModuleName();
2427330f729Sjoerg       NeedsFramework = true;
2437330f729Sjoerg     }
244*e038c9c4Sjoerg     return None;
2457330f729Sjoerg   }
2467330f729Sjoerg 
2477330f729Sjoerg   return NormalHdrFile;
2487330f729Sjoerg }
2497330f729Sjoerg 
resolveHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header,bool & NeedsFramework)2507330f729Sjoerg void ModuleMap::resolveHeader(Module *Mod,
2517330f729Sjoerg                               const Module::UnresolvedHeaderDirective &Header,
2527330f729Sjoerg                               bool &NeedsFramework) {
2537330f729Sjoerg   SmallString<128> RelativePathName;
254*e038c9c4Sjoerg   if (Optional<FileEntryRef> File =
2557330f729Sjoerg           findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
2567330f729Sjoerg     if (Header.IsUmbrella) {
257*e038c9c4Sjoerg       const DirectoryEntry *UmbrellaDir = &File->getDir().getDirEntry();
2587330f729Sjoerg       if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
2597330f729Sjoerg         Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2607330f729Sjoerg           << UmbrellaMod->getFullModuleName();
2617330f729Sjoerg       else
2627330f729Sjoerg         // Record this umbrella header.
263*e038c9c4Sjoerg         setUmbrellaHeader(Mod, *File, Header.FileName, RelativePathName.str());
2647330f729Sjoerg     } else {
265*e038c9c4Sjoerg       Module::Header H = {Header.FileName, std::string(RelativePathName.str()),
266*e038c9c4Sjoerg                           *File};
2677330f729Sjoerg       if (Header.Kind == Module::HK_Excluded)
2687330f729Sjoerg         excludeHeader(Mod, H);
2697330f729Sjoerg       else
2707330f729Sjoerg         addHeader(Mod, H, headerKindToRole(Header.Kind));
2717330f729Sjoerg     }
2727330f729Sjoerg   } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
2737330f729Sjoerg     // There's a builtin header but no corresponding on-disk header. Assume
2747330f729Sjoerg     // this was supposed to modularize the builtin header alone.
2757330f729Sjoerg   } else if (Header.Kind == Module::HK_Excluded) {
2767330f729Sjoerg     // Ignore missing excluded header files. They're optional anyway.
2777330f729Sjoerg   } else {
2787330f729Sjoerg     // If we find a module that has a missing header, we mark this module as
2797330f729Sjoerg     // unavailable and store the header directive for displaying diagnostics.
2807330f729Sjoerg     Mod->MissingHeaders.push_back(Header);
2817330f729Sjoerg     // A missing header with stat information doesn't make the module
2827330f729Sjoerg     // unavailable; this keeps our behavior consistent as headers are lazily
2837330f729Sjoerg     // resolved. (Such a module still can't be built though, except from
2847330f729Sjoerg     // preprocessed source.)
2857330f729Sjoerg     if (!Header.Size && !Header.ModTime)
286*e038c9c4Sjoerg       Mod->markUnavailable(/*Unimportable=*/false);
2877330f729Sjoerg   }
2887330f729Sjoerg }
2897330f729Sjoerg 
resolveAsBuiltinHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header)2907330f729Sjoerg bool ModuleMap::resolveAsBuiltinHeader(
2917330f729Sjoerg     Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
2927330f729Sjoerg   if (Header.Kind == Module::HK_Excluded ||
2937330f729Sjoerg       llvm::sys::path::is_absolute(Header.FileName) ||
2947330f729Sjoerg       Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
2957330f729Sjoerg       !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
2967330f729Sjoerg       !isBuiltinHeader(Header.FileName))
2977330f729Sjoerg     return false;
2987330f729Sjoerg 
2997330f729Sjoerg   // This is a system module with a top-level header. This header
3007330f729Sjoerg   // may have a counterpart (or replacement) in the set of headers
3017330f729Sjoerg   // supplied by Clang. Find that builtin header.
3027330f729Sjoerg   SmallString<128> Path;
3037330f729Sjoerg   llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
3047330f729Sjoerg   auto File = SourceMgr.getFileManager().getFile(Path);
3057330f729Sjoerg   if (!File)
3067330f729Sjoerg     return false;
3077330f729Sjoerg 
3087330f729Sjoerg   auto Role = headerKindToRole(Header.Kind);
309*e038c9c4Sjoerg   Module::Header H = {Header.FileName, std::string(Path.str()), *File};
3107330f729Sjoerg   addHeader(Mod, H, Role);
3117330f729Sjoerg   return true;
3127330f729Sjoerg }
3137330f729Sjoerg 
ModuleMap(SourceManager & SourceMgr,DiagnosticsEngine & Diags,const LangOptions & LangOpts,const TargetInfo * Target,HeaderSearch & HeaderInfo)3147330f729Sjoerg ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
3157330f729Sjoerg                      const LangOptions &LangOpts, const TargetInfo *Target,
3167330f729Sjoerg                      HeaderSearch &HeaderInfo)
3177330f729Sjoerg     : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
3187330f729Sjoerg       HeaderInfo(HeaderInfo) {
3197330f729Sjoerg   MMapLangOpts.LineComment = true;
3207330f729Sjoerg }
3217330f729Sjoerg 
~ModuleMap()3227330f729Sjoerg ModuleMap::~ModuleMap() {
3237330f729Sjoerg   for (auto &M : Modules)
3247330f729Sjoerg     delete M.getValue();
3257330f729Sjoerg   for (auto *M : ShadowModules)
3267330f729Sjoerg     delete M;
3277330f729Sjoerg }
3287330f729Sjoerg 
setTarget(const TargetInfo & Target)3297330f729Sjoerg void ModuleMap::setTarget(const TargetInfo &Target) {
3307330f729Sjoerg   assert((!this->Target || this->Target == &Target) &&
3317330f729Sjoerg          "Improper target override");
3327330f729Sjoerg   this->Target = &Target;
3337330f729Sjoerg }
3347330f729Sjoerg 
3357330f729Sjoerg /// "Sanitize" a filename so that it can be used as an identifier.
sanitizeFilenameAsIdentifier(StringRef Name,SmallVectorImpl<char> & Buffer)3367330f729Sjoerg static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
3377330f729Sjoerg                                               SmallVectorImpl<char> &Buffer) {
3387330f729Sjoerg   if (Name.empty())
3397330f729Sjoerg     return Name;
3407330f729Sjoerg 
3417330f729Sjoerg   if (!isValidIdentifier(Name)) {
3427330f729Sjoerg     // If we don't already have something with the form of an identifier,
3437330f729Sjoerg     // create a buffer with the sanitized name.
3447330f729Sjoerg     Buffer.clear();
3457330f729Sjoerg     if (isDigit(Name[0]))
3467330f729Sjoerg       Buffer.push_back('_');
3477330f729Sjoerg     Buffer.reserve(Buffer.size() + Name.size());
3487330f729Sjoerg     for (unsigned I = 0, N = Name.size(); I != N; ++I) {
3497330f729Sjoerg       if (isIdentifierBody(Name[I]))
3507330f729Sjoerg         Buffer.push_back(Name[I]);
3517330f729Sjoerg       else
3527330f729Sjoerg         Buffer.push_back('_');
3537330f729Sjoerg     }
3547330f729Sjoerg 
3557330f729Sjoerg     Name = StringRef(Buffer.data(), Buffer.size());
3567330f729Sjoerg   }
3577330f729Sjoerg 
3587330f729Sjoerg   while (llvm::StringSwitch<bool>(Name)
3597330f729Sjoerg #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
3607330f729Sjoerg #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
3617330f729Sjoerg #include "clang/Basic/TokenKinds.def"
3627330f729Sjoerg            .Default(false)) {
3637330f729Sjoerg     if (Name.data() != Buffer.data())
3647330f729Sjoerg       Buffer.append(Name.begin(), Name.end());
3657330f729Sjoerg     Buffer.push_back('_');
3667330f729Sjoerg     Name = StringRef(Buffer.data(), Buffer.size());
3677330f729Sjoerg   }
3687330f729Sjoerg 
3697330f729Sjoerg   return Name;
3707330f729Sjoerg }
3717330f729Sjoerg 
3727330f729Sjoerg /// Determine whether the given file name is the name of a builtin
3737330f729Sjoerg /// header, supplied by Clang to replace, override, or augment existing system
3747330f729Sjoerg /// headers.
isBuiltinHeader(StringRef FileName)3757330f729Sjoerg bool ModuleMap::isBuiltinHeader(StringRef FileName) {
3767330f729Sjoerg   return llvm::StringSwitch<bool>(FileName)
3777330f729Sjoerg            .Case("float.h", true)
3787330f729Sjoerg            .Case("iso646.h", true)
3797330f729Sjoerg            .Case("limits.h", true)
3807330f729Sjoerg            .Case("stdalign.h", true)
3817330f729Sjoerg            .Case("stdarg.h", true)
3827330f729Sjoerg            .Case("stdatomic.h", true)
3837330f729Sjoerg            .Case("stdbool.h", true)
3847330f729Sjoerg            .Case("stddef.h", true)
3857330f729Sjoerg            .Case("stdint.h", true)
3867330f729Sjoerg            .Case("tgmath.h", true)
3877330f729Sjoerg            .Case("unwind.h", true)
3887330f729Sjoerg            .Default(false);
3897330f729Sjoerg }
3907330f729Sjoerg 
isBuiltinHeader(const FileEntry * File)391*e038c9c4Sjoerg bool ModuleMap::isBuiltinHeader(const FileEntry *File) {
392*e038c9c4Sjoerg   return File->getDir() == BuiltinIncludeDir &&
393*e038c9c4Sjoerg          ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()));
394*e038c9c4Sjoerg }
395*e038c9c4Sjoerg 
3967330f729Sjoerg ModuleMap::HeadersMap::iterator
findKnownHeader(const FileEntry * File)3977330f729Sjoerg ModuleMap::findKnownHeader(const FileEntry *File) {
3987330f729Sjoerg   resolveHeaderDirectives(File);
3997330f729Sjoerg   HeadersMap::iterator Known = Headers.find(File);
4007330f729Sjoerg   if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
401*e038c9c4Sjoerg       Known == Headers.end() && ModuleMap::isBuiltinHeader(File)) {
4027330f729Sjoerg     HeaderInfo.loadTopLevelSystemModules();
4037330f729Sjoerg     return Headers.find(File);
4047330f729Sjoerg   }
4057330f729Sjoerg   return Known;
4067330f729Sjoerg }
4077330f729Sjoerg 
4087330f729Sjoerg ModuleMap::KnownHeader
findHeaderInUmbrellaDirs(const FileEntry * File,SmallVectorImpl<const DirectoryEntry * > & IntermediateDirs)4097330f729Sjoerg ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
4107330f729Sjoerg                     SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
4117330f729Sjoerg   if (UmbrellaDirs.empty())
4127330f729Sjoerg     return {};
4137330f729Sjoerg 
4147330f729Sjoerg   const DirectoryEntry *Dir = File->getDir();
4157330f729Sjoerg   assert(Dir && "file in no directory");
4167330f729Sjoerg 
4177330f729Sjoerg   // Note: as an egregious but useful hack we use the real path here, because
4187330f729Sjoerg   // frameworks moving from top-level frameworks to embedded frameworks tend
4197330f729Sjoerg   // to be symlinked from the top-level location to the embedded location,
4207330f729Sjoerg   // and we need to resolve lookups as if we had found the embedded location.
4217330f729Sjoerg   StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
4227330f729Sjoerg 
4237330f729Sjoerg   // Keep walking up the directory hierarchy, looking for a directory with
4247330f729Sjoerg   // an umbrella header.
4257330f729Sjoerg   do {
4267330f729Sjoerg     auto KnownDir = UmbrellaDirs.find(Dir);
4277330f729Sjoerg     if (KnownDir != UmbrellaDirs.end())
4287330f729Sjoerg       return KnownHeader(KnownDir->second, NormalHeader);
4297330f729Sjoerg 
4307330f729Sjoerg     IntermediateDirs.push_back(Dir);
4317330f729Sjoerg 
4327330f729Sjoerg     // Retrieve our parent path.
4337330f729Sjoerg     DirName = llvm::sys::path::parent_path(DirName);
4347330f729Sjoerg     if (DirName.empty())
4357330f729Sjoerg       break;
4367330f729Sjoerg 
4377330f729Sjoerg     // Resolve the parent path to a directory entry.
4387330f729Sjoerg     if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName))
4397330f729Sjoerg       Dir = *DirEntry;
4407330f729Sjoerg     else
4417330f729Sjoerg       Dir = nullptr;
4427330f729Sjoerg   } while (Dir);
4437330f729Sjoerg   return {};
4447330f729Sjoerg }
4457330f729Sjoerg 
violatesPrivateInclude(Module * RequestingModule,const FileEntry * IncFileEnt,ModuleMap::KnownHeader Header)4467330f729Sjoerg static bool violatesPrivateInclude(Module *RequestingModule,
4477330f729Sjoerg                                    const FileEntry *IncFileEnt,
4487330f729Sjoerg                                    ModuleMap::KnownHeader Header) {
4497330f729Sjoerg #ifndef NDEBUG
4507330f729Sjoerg   if (Header.getRole() & ModuleMap::PrivateHeader) {
4517330f729Sjoerg     // Check for consistency between the module header role
4527330f729Sjoerg     // as obtained from the lookup and as obtained from the module.
4537330f729Sjoerg     // This check is not cheap, so enable it only for debugging.
4547330f729Sjoerg     bool IsPrivate = false;
4557330f729Sjoerg     SmallVectorImpl<Module::Header> *HeaderList[] = {
4567330f729Sjoerg         &Header.getModule()->Headers[Module::HK_Private],
4577330f729Sjoerg         &Header.getModule()->Headers[Module::HK_PrivateTextual]};
4587330f729Sjoerg     for (auto *Hs : HeaderList)
4597330f729Sjoerg       IsPrivate |=
4607330f729Sjoerg           std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) {
4617330f729Sjoerg             return H.Entry == IncFileEnt;
4627330f729Sjoerg           }) != Hs->end();
4637330f729Sjoerg     assert(IsPrivate && "inconsistent headers and roles");
4647330f729Sjoerg   }
4657330f729Sjoerg #endif
4667330f729Sjoerg   return !Header.isAccessibleFrom(RequestingModule);
4677330f729Sjoerg }
4687330f729Sjoerg 
getTopLevelOrNull(Module * M)4697330f729Sjoerg static Module *getTopLevelOrNull(Module *M) {
4707330f729Sjoerg   return M ? M->getTopLevelModule() : nullptr;
4717330f729Sjoerg }
4727330f729Sjoerg 
diagnoseHeaderInclusion(Module * RequestingModule,bool RequestingModuleIsModuleInterface,SourceLocation FilenameLoc,StringRef Filename,const FileEntry * File)4737330f729Sjoerg void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
4747330f729Sjoerg                                         bool RequestingModuleIsModuleInterface,
4757330f729Sjoerg                                         SourceLocation FilenameLoc,
4767330f729Sjoerg                                         StringRef Filename,
4777330f729Sjoerg                                         const FileEntry *File) {
4787330f729Sjoerg   // No errors for indirect modules. This may be a bit of a problem for modules
4797330f729Sjoerg   // with no source files.
4807330f729Sjoerg   if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
4817330f729Sjoerg     return;
4827330f729Sjoerg 
4837330f729Sjoerg   if (RequestingModule) {
4847330f729Sjoerg     resolveUses(RequestingModule, /*Complain=*/false);
4857330f729Sjoerg     resolveHeaderDirectives(RequestingModule);
4867330f729Sjoerg   }
4877330f729Sjoerg 
4887330f729Sjoerg   bool Excluded = false;
4897330f729Sjoerg   Module *Private = nullptr;
4907330f729Sjoerg   Module *NotUsed = nullptr;
4917330f729Sjoerg 
4927330f729Sjoerg   HeadersMap::iterator Known = findKnownHeader(File);
4937330f729Sjoerg   if (Known != Headers.end()) {
4947330f729Sjoerg     for (const KnownHeader &Header : Known->second) {
4957330f729Sjoerg       // Remember private headers for later printing of a diagnostic.
4967330f729Sjoerg       if (violatesPrivateInclude(RequestingModule, File, Header)) {
4977330f729Sjoerg         Private = Header.getModule();
4987330f729Sjoerg         continue;
4997330f729Sjoerg       }
5007330f729Sjoerg 
5017330f729Sjoerg       // If uses need to be specified explicitly, we are only allowed to return
5027330f729Sjoerg       // modules that are explicitly used by the requesting module.
5037330f729Sjoerg       if (RequestingModule && LangOpts.ModulesDeclUse &&
5047330f729Sjoerg           !RequestingModule->directlyUses(Header.getModule())) {
5057330f729Sjoerg         NotUsed = Header.getModule();
5067330f729Sjoerg         continue;
5077330f729Sjoerg       }
5087330f729Sjoerg 
5097330f729Sjoerg       // We have found a module that we can happily use.
5107330f729Sjoerg       return;
5117330f729Sjoerg     }
5127330f729Sjoerg 
5137330f729Sjoerg     Excluded = true;
5147330f729Sjoerg   }
5157330f729Sjoerg 
5167330f729Sjoerg   // We have found a header, but it is private.
5177330f729Sjoerg   if (Private) {
5187330f729Sjoerg     Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
5197330f729Sjoerg         << Filename;
5207330f729Sjoerg     return;
5217330f729Sjoerg   }
5227330f729Sjoerg 
5237330f729Sjoerg   // We have found a module, but we don't use it.
5247330f729Sjoerg   if (NotUsed) {
5257330f729Sjoerg     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5267330f729Sjoerg         << RequestingModule->getTopLevelModule()->Name << Filename;
5277330f729Sjoerg     return;
5287330f729Sjoerg   }
5297330f729Sjoerg 
5307330f729Sjoerg   if (Excluded || isHeaderInUmbrellaDirs(File))
5317330f729Sjoerg     return;
5327330f729Sjoerg 
5337330f729Sjoerg   // At this point, only non-modular includes remain.
5347330f729Sjoerg 
5357330f729Sjoerg   if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
5367330f729Sjoerg     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5377330f729Sjoerg         << RequestingModule->getTopLevelModule()->Name << Filename;
5387330f729Sjoerg   } else if (RequestingModule && RequestingModuleIsModuleInterface &&
5397330f729Sjoerg              LangOpts.isCompilingModule()) {
5407330f729Sjoerg     // Do not diagnose when we are not compiling a module.
5417330f729Sjoerg     diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
5427330f729Sjoerg         diag::warn_non_modular_include_in_framework_module :
5437330f729Sjoerg         diag::warn_non_modular_include_in_module;
5447330f729Sjoerg     Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
5457330f729Sjoerg         << File->getName();
5467330f729Sjoerg   }
5477330f729Sjoerg }
5487330f729Sjoerg 
isBetterKnownHeader(const ModuleMap::KnownHeader & New,const ModuleMap::KnownHeader & Old)5497330f729Sjoerg static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
5507330f729Sjoerg                                 const ModuleMap::KnownHeader &Old) {
5517330f729Sjoerg   // Prefer available modules.
552*e038c9c4Sjoerg   // FIXME: Considering whether the module is available rather than merely
553*e038c9c4Sjoerg   // importable is non-hermetic and can result in surprising behavior for
554*e038c9c4Sjoerg   // prebuilt modules. Consider only checking for importability here.
5557330f729Sjoerg   if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
5567330f729Sjoerg     return true;
5577330f729Sjoerg 
5587330f729Sjoerg   // Prefer a public header over a private header.
5597330f729Sjoerg   if ((New.getRole() & ModuleMap::PrivateHeader) !=
5607330f729Sjoerg       (Old.getRole() & ModuleMap::PrivateHeader))
5617330f729Sjoerg     return !(New.getRole() & ModuleMap::PrivateHeader);
5627330f729Sjoerg 
5637330f729Sjoerg   // Prefer a non-textual header over a textual header.
5647330f729Sjoerg   if ((New.getRole() & ModuleMap::TextualHeader) !=
5657330f729Sjoerg       (Old.getRole() & ModuleMap::TextualHeader))
5667330f729Sjoerg     return !(New.getRole() & ModuleMap::TextualHeader);
5677330f729Sjoerg 
5687330f729Sjoerg   // Don't have a reason to choose between these. Just keep the first one.
5697330f729Sjoerg   return false;
5707330f729Sjoerg }
5717330f729Sjoerg 
findModuleForHeader(const FileEntry * File,bool AllowTextual)5727330f729Sjoerg ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
5737330f729Sjoerg                                                       bool AllowTextual) {
5747330f729Sjoerg   auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
5757330f729Sjoerg     if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
5767330f729Sjoerg       return {};
5777330f729Sjoerg     return R;
5787330f729Sjoerg   };
5797330f729Sjoerg 
5807330f729Sjoerg   HeadersMap::iterator Known = findKnownHeader(File);
5817330f729Sjoerg   if (Known != Headers.end()) {
5827330f729Sjoerg     ModuleMap::KnownHeader Result;
5837330f729Sjoerg     // Iterate over all modules that 'File' is part of to find the best fit.
5847330f729Sjoerg     for (KnownHeader &H : Known->second) {
5857330f729Sjoerg       // Prefer a header from the source module over all others.
5867330f729Sjoerg       if (H.getModule()->getTopLevelModule() == SourceModule)
5877330f729Sjoerg         return MakeResult(H);
5887330f729Sjoerg       if (!Result || isBetterKnownHeader(H, Result))
5897330f729Sjoerg         Result = H;
5907330f729Sjoerg     }
5917330f729Sjoerg     return MakeResult(Result);
5927330f729Sjoerg   }
5937330f729Sjoerg 
5947330f729Sjoerg   return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
5957330f729Sjoerg }
5967330f729Sjoerg 
5977330f729Sjoerg ModuleMap::KnownHeader
findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry * File)5987330f729Sjoerg ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
5997330f729Sjoerg   assert(!Headers.count(File) && "already have a module for this header");
6007330f729Sjoerg 
6017330f729Sjoerg   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
6027330f729Sjoerg   KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
6037330f729Sjoerg   if (H) {
6047330f729Sjoerg     Module *Result = H.getModule();
6057330f729Sjoerg 
6067330f729Sjoerg     // Search up the module stack until we find a module with an umbrella
6077330f729Sjoerg     // directory.
6087330f729Sjoerg     Module *UmbrellaModule = Result;
6097330f729Sjoerg     while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
6107330f729Sjoerg       UmbrellaModule = UmbrellaModule->Parent;
6117330f729Sjoerg 
6127330f729Sjoerg     if (UmbrellaModule->InferSubmodules) {
6137330f729Sjoerg       const FileEntry *UmbrellaModuleMap =
6147330f729Sjoerg           getModuleMapFileForUniquing(UmbrellaModule);
6157330f729Sjoerg 
6167330f729Sjoerg       // Infer submodules for each of the directories we found between
6177330f729Sjoerg       // the directory of the umbrella header and the directory where
6187330f729Sjoerg       // the actual header is located.
6197330f729Sjoerg       bool Explicit = UmbrellaModule->InferExplicitSubmodules;
6207330f729Sjoerg 
6217330f729Sjoerg       for (unsigned I = SkippedDirs.size(); I != 0; --I) {
6227330f729Sjoerg         // Find or create the module that corresponds to this directory name.
6237330f729Sjoerg         SmallString<32> NameBuf;
6247330f729Sjoerg         StringRef Name = sanitizeFilenameAsIdentifier(
6257330f729Sjoerg             llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
6267330f729Sjoerg         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6277330f729Sjoerg                                     Explicit).first;
6287330f729Sjoerg         InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
6297330f729Sjoerg         Result->IsInferred = true;
6307330f729Sjoerg 
6317330f729Sjoerg         // Associate the module and the directory.
6327330f729Sjoerg         UmbrellaDirs[SkippedDirs[I-1]] = Result;
6337330f729Sjoerg 
6347330f729Sjoerg         // If inferred submodules export everything they import, add a
6357330f729Sjoerg         // wildcard to the set of exports.
6367330f729Sjoerg         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
6377330f729Sjoerg           Result->Exports.push_back(Module::ExportDecl(nullptr, true));
6387330f729Sjoerg       }
6397330f729Sjoerg 
6407330f729Sjoerg       // Infer a submodule with the same name as this header file.
6417330f729Sjoerg       SmallString<32> NameBuf;
6427330f729Sjoerg       StringRef Name = sanitizeFilenameAsIdentifier(
6437330f729Sjoerg                          llvm::sys::path::stem(File->getName()), NameBuf);
6447330f729Sjoerg       Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6457330f729Sjoerg                                   Explicit).first;
6467330f729Sjoerg       InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
6477330f729Sjoerg       Result->IsInferred = true;
6487330f729Sjoerg       Result->addTopHeader(File);
6497330f729Sjoerg 
6507330f729Sjoerg       // If inferred submodules export everything they import, add a
6517330f729Sjoerg       // wildcard to the set of exports.
6527330f729Sjoerg       if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
6537330f729Sjoerg         Result->Exports.push_back(Module::ExportDecl(nullptr, true));
6547330f729Sjoerg     } else {
6557330f729Sjoerg       // Record each of the directories we stepped through as being part of
6567330f729Sjoerg       // the module we found, since the umbrella header covers them all.
6577330f729Sjoerg       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
6587330f729Sjoerg         UmbrellaDirs[SkippedDirs[I]] = Result;
6597330f729Sjoerg     }
6607330f729Sjoerg 
6617330f729Sjoerg     KnownHeader Header(Result, NormalHeader);
6627330f729Sjoerg     Headers[File].push_back(Header);
6637330f729Sjoerg     return Header;
6647330f729Sjoerg   }
6657330f729Sjoerg 
6667330f729Sjoerg   return {};
6677330f729Sjoerg }
6687330f729Sjoerg 
6697330f729Sjoerg ArrayRef<ModuleMap::KnownHeader>
findAllModulesForHeader(const FileEntry * File)670*e038c9c4Sjoerg ModuleMap::findAllModulesForHeader(const FileEntry *File) {
671*e038c9c4Sjoerg   HeadersMap::iterator Known = findKnownHeader(File);
672*e038c9c4Sjoerg   if (Known != Headers.end())
673*e038c9c4Sjoerg     return Known->second;
674*e038c9c4Sjoerg 
675*e038c9c4Sjoerg   if (findOrCreateModuleForHeaderInUmbrellaDir(File))
676*e038c9c4Sjoerg     return Headers.find(File)->second;
677*e038c9c4Sjoerg 
678*e038c9c4Sjoerg   return None;
679*e038c9c4Sjoerg }
680*e038c9c4Sjoerg 
681*e038c9c4Sjoerg ArrayRef<ModuleMap::KnownHeader>
findResolvedModulesForHeader(const FileEntry * File) const682*e038c9c4Sjoerg ModuleMap::findResolvedModulesForHeader(const FileEntry *File) const {
683*e038c9c4Sjoerg   // FIXME: Is this necessary?
6847330f729Sjoerg   resolveHeaderDirectives(File);
6857330f729Sjoerg   auto It = Headers.find(File);
6867330f729Sjoerg   if (It == Headers.end())
6877330f729Sjoerg     return None;
6887330f729Sjoerg   return It->second;
6897330f729Sjoerg }
6907330f729Sjoerg 
isHeaderInUnavailableModule(const FileEntry * Header) const6917330f729Sjoerg bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
6927330f729Sjoerg   return isHeaderUnavailableInModule(Header, nullptr);
6937330f729Sjoerg }
6947330f729Sjoerg 
6957330f729Sjoerg bool
isHeaderUnavailableInModule(const FileEntry * Header,const Module * RequestingModule) const6967330f729Sjoerg ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
6977330f729Sjoerg                                        const Module *RequestingModule) const {
6987330f729Sjoerg   resolveHeaderDirectives(Header);
6997330f729Sjoerg   HeadersMap::const_iterator Known = Headers.find(Header);
7007330f729Sjoerg   if (Known != Headers.end()) {
7017330f729Sjoerg     for (SmallVectorImpl<KnownHeader>::const_iterator
7027330f729Sjoerg              I = Known->second.begin(),
7037330f729Sjoerg              E = Known->second.end();
7047330f729Sjoerg          I != E; ++I) {
7057330f729Sjoerg 
7067330f729Sjoerg       if (I->isAvailable() &&
7077330f729Sjoerg           (!RequestingModule ||
7087330f729Sjoerg            I->getModule()->isSubModuleOf(RequestingModule))) {
7097330f729Sjoerg         // When no requesting module is available, the caller is looking if a
7107330f729Sjoerg         // header is part a module by only looking into the module map. This is
7117330f729Sjoerg         // done by warn_uncovered_module_header checks; don't consider textual
7127330f729Sjoerg         // headers part of it in this mode, otherwise we get misleading warnings
7137330f729Sjoerg         // that a umbrella header is not including a textual header.
7147330f729Sjoerg         if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
7157330f729Sjoerg           continue;
7167330f729Sjoerg         return false;
7177330f729Sjoerg       }
7187330f729Sjoerg     }
7197330f729Sjoerg     return true;
7207330f729Sjoerg   }
7217330f729Sjoerg 
7227330f729Sjoerg   const DirectoryEntry *Dir = Header->getDir();
7237330f729Sjoerg   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
7247330f729Sjoerg   StringRef DirName = Dir->getName();
7257330f729Sjoerg 
7267330f729Sjoerg   auto IsUnavailable = [&](const Module *M) {
7277330f729Sjoerg     return !M->isAvailable() && (!RequestingModule ||
7287330f729Sjoerg                                  M->isSubModuleOf(RequestingModule));
7297330f729Sjoerg   };
7307330f729Sjoerg 
7317330f729Sjoerg   // Keep walking up the directory hierarchy, looking for a directory with
7327330f729Sjoerg   // an umbrella header.
7337330f729Sjoerg   do {
7347330f729Sjoerg     llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
7357330f729Sjoerg       = UmbrellaDirs.find(Dir);
7367330f729Sjoerg     if (KnownDir != UmbrellaDirs.end()) {
7377330f729Sjoerg       Module *Found = KnownDir->second;
7387330f729Sjoerg       if (IsUnavailable(Found))
7397330f729Sjoerg         return true;
7407330f729Sjoerg 
7417330f729Sjoerg       // Search up the module stack until we find a module with an umbrella
7427330f729Sjoerg       // directory.
7437330f729Sjoerg       Module *UmbrellaModule = Found;
7447330f729Sjoerg       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
7457330f729Sjoerg         UmbrellaModule = UmbrellaModule->Parent;
7467330f729Sjoerg 
7477330f729Sjoerg       if (UmbrellaModule->InferSubmodules) {
7487330f729Sjoerg         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
7497330f729Sjoerg           // Find or create the module that corresponds to this directory name.
7507330f729Sjoerg           SmallString<32> NameBuf;
7517330f729Sjoerg           StringRef Name = sanitizeFilenameAsIdentifier(
7527330f729Sjoerg                              llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
7537330f729Sjoerg                              NameBuf);
7547330f729Sjoerg           Found = lookupModuleQualified(Name, Found);
7557330f729Sjoerg           if (!Found)
7567330f729Sjoerg             return false;
7577330f729Sjoerg           if (IsUnavailable(Found))
7587330f729Sjoerg             return true;
7597330f729Sjoerg         }
7607330f729Sjoerg 
7617330f729Sjoerg         // Infer a submodule with the same name as this header file.
7627330f729Sjoerg         SmallString<32> NameBuf;
7637330f729Sjoerg         StringRef Name = sanitizeFilenameAsIdentifier(
7647330f729Sjoerg                            llvm::sys::path::stem(Header->getName()),
7657330f729Sjoerg                            NameBuf);
7667330f729Sjoerg         Found = lookupModuleQualified(Name, Found);
7677330f729Sjoerg         if (!Found)
7687330f729Sjoerg           return false;
7697330f729Sjoerg       }
7707330f729Sjoerg 
7717330f729Sjoerg       return IsUnavailable(Found);
7727330f729Sjoerg     }
7737330f729Sjoerg 
7747330f729Sjoerg     SkippedDirs.push_back(Dir);
7757330f729Sjoerg 
7767330f729Sjoerg     // Retrieve our parent path.
7777330f729Sjoerg     DirName = llvm::sys::path::parent_path(DirName);
7787330f729Sjoerg     if (DirName.empty())
7797330f729Sjoerg       break;
7807330f729Sjoerg 
7817330f729Sjoerg     // Resolve the parent path to a directory entry.
7827330f729Sjoerg     if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName))
7837330f729Sjoerg       Dir = *DirEntry;
7847330f729Sjoerg     else
7857330f729Sjoerg       Dir = nullptr;
7867330f729Sjoerg   } while (Dir);
7877330f729Sjoerg 
7887330f729Sjoerg   return false;
7897330f729Sjoerg }
7907330f729Sjoerg 
findModule(StringRef Name) const7917330f729Sjoerg Module *ModuleMap::findModule(StringRef Name) const {
7927330f729Sjoerg   llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
7937330f729Sjoerg   if (Known != Modules.end())
7947330f729Sjoerg     return Known->getValue();
7957330f729Sjoerg 
7967330f729Sjoerg   return nullptr;
7977330f729Sjoerg }
7987330f729Sjoerg 
lookupModuleUnqualified(StringRef Name,Module * Context) const7997330f729Sjoerg Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
8007330f729Sjoerg                                            Module *Context) const {
8017330f729Sjoerg   for(; Context; Context = Context->Parent) {
8027330f729Sjoerg     if (Module *Sub = lookupModuleQualified(Name, Context))
8037330f729Sjoerg       return Sub;
8047330f729Sjoerg   }
8057330f729Sjoerg 
8067330f729Sjoerg   return findModule(Name);
8077330f729Sjoerg }
8087330f729Sjoerg 
lookupModuleQualified(StringRef Name,Module * Context) const8097330f729Sjoerg Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
8107330f729Sjoerg   if (!Context)
8117330f729Sjoerg     return findModule(Name);
8127330f729Sjoerg 
8137330f729Sjoerg   return Context->findSubmodule(Name);
8147330f729Sjoerg }
8157330f729Sjoerg 
findOrCreateModule(StringRef Name,Module * Parent,bool IsFramework,bool IsExplicit)8167330f729Sjoerg std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
8177330f729Sjoerg                                                         Module *Parent,
8187330f729Sjoerg                                                         bool IsFramework,
8197330f729Sjoerg                                                         bool IsExplicit) {
8207330f729Sjoerg   // Try to find an existing module with this name.
8217330f729Sjoerg   if (Module *Sub = lookupModuleQualified(Name, Parent))
8227330f729Sjoerg     return std::make_pair(Sub, false);
8237330f729Sjoerg 
8247330f729Sjoerg   // Create a new module with this name.
8257330f729Sjoerg   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
8267330f729Sjoerg                               IsExplicit, NumCreatedModules++);
8277330f729Sjoerg   if (!Parent) {
8287330f729Sjoerg     if (LangOpts.CurrentModule == Name)
8297330f729Sjoerg       SourceModule = Result;
8307330f729Sjoerg     Modules[Name] = Result;
8317330f729Sjoerg     ModuleScopeIDs[Result] = CurrentModuleScopeID;
8327330f729Sjoerg   }
8337330f729Sjoerg   return std::make_pair(Result, true);
8347330f729Sjoerg }
8357330f729Sjoerg 
createGlobalModuleFragmentForModuleUnit(SourceLocation Loc)8367330f729Sjoerg Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc) {
8377330f729Sjoerg   PendingSubmodules.emplace_back(
8387330f729Sjoerg       new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
8397330f729Sjoerg                  /*IsExplicit*/ true, NumCreatedModules++));
8407330f729Sjoerg   PendingSubmodules.back()->Kind = Module::GlobalModuleFragment;
8417330f729Sjoerg   return PendingSubmodules.back().get();
8427330f729Sjoerg }
8437330f729Sjoerg 
8447330f729Sjoerg Module *
createPrivateModuleFragmentForInterfaceUnit(Module * Parent,SourceLocation Loc)8457330f729Sjoerg ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
8467330f729Sjoerg                                                        SourceLocation Loc) {
8477330f729Sjoerg   auto *Result =
8487330f729Sjoerg       new Module("<private>", Loc, Parent, /*IsFramework*/ false,
8497330f729Sjoerg                  /*IsExplicit*/ true, NumCreatedModules++);
8507330f729Sjoerg   Result->Kind = Module::PrivateModuleFragment;
8517330f729Sjoerg   return Result;
8527330f729Sjoerg }
8537330f729Sjoerg 
createModuleForInterfaceUnit(SourceLocation Loc,StringRef Name,Module * GlobalModule)8547330f729Sjoerg Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
8557330f729Sjoerg                                                 StringRef Name,
8567330f729Sjoerg                                                 Module *GlobalModule) {
8577330f729Sjoerg   assert(LangOpts.CurrentModule == Name && "module name mismatch");
8587330f729Sjoerg   assert(!Modules[Name] && "redefining existing module");
8597330f729Sjoerg 
8607330f729Sjoerg   auto *Result =
8617330f729Sjoerg       new Module(Name, Loc, nullptr, /*IsFramework*/ false,
8627330f729Sjoerg                  /*IsExplicit*/ false, NumCreatedModules++);
8637330f729Sjoerg   Result->Kind = Module::ModuleInterfaceUnit;
8647330f729Sjoerg   Modules[Name] = SourceModule = Result;
8657330f729Sjoerg 
8667330f729Sjoerg   // Reparent the current global module fragment as a submodule of this module.
8677330f729Sjoerg   for (auto &Submodule : PendingSubmodules) {
8687330f729Sjoerg     Submodule->setParent(Result);
8697330f729Sjoerg     Submodule.release(); // now owned by parent
8707330f729Sjoerg   }
8717330f729Sjoerg   PendingSubmodules.clear();
8727330f729Sjoerg 
8737330f729Sjoerg   // Mark the main source file as being within the newly-created module so that
8747330f729Sjoerg   // declarations and macros are properly visibility-restricted to it.
8757330f729Sjoerg   auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
8767330f729Sjoerg   assert(MainFile && "no input file for module interface");
8777330f729Sjoerg   Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader));
8787330f729Sjoerg 
8797330f729Sjoerg   return Result;
8807330f729Sjoerg }
8817330f729Sjoerg 
createHeaderModule(StringRef Name,ArrayRef<Module::Header> Headers)8827330f729Sjoerg Module *ModuleMap::createHeaderModule(StringRef Name,
8837330f729Sjoerg                                       ArrayRef<Module::Header> Headers) {
8847330f729Sjoerg   assert(LangOpts.CurrentModule == Name && "module name mismatch");
8857330f729Sjoerg   assert(!Modules[Name] && "redefining existing module");
8867330f729Sjoerg 
8877330f729Sjoerg   auto *Result =
8887330f729Sjoerg       new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false,
8897330f729Sjoerg                  /*IsExplicit*/ false, NumCreatedModules++);
8907330f729Sjoerg   Result->Kind = Module::ModuleInterfaceUnit;
8917330f729Sjoerg   Modules[Name] = SourceModule = Result;
8927330f729Sjoerg 
8937330f729Sjoerg   for (const Module::Header &H : Headers) {
8947330f729Sjoerg     auto *M = new Module(H.NameAsWritten, SourceLocation(), Result,
8957330f729Sjoerg                          /*IsFramework*/ false,
8967330f729Sjoerg                          /*IsExplicit*/ true, NumCreatedModules++);
8977330f729Sjoerg     // Header modules are implicitly 'export *'.
8987330f729Sjoerg     M->Exports.push_back(Module::ExportDecl(nullptr, true));
8997330f729Sjoerg     addHeader(M, H, NormalHeader);
9007330f729Sjoerg   }
9017330f729Sjoerg 
9027330f729Sjoerg   return Result;
9037330f729Sjoerg }
9047330f729Sjoerg 
9057330f729Sjoerg /// For a framework module, infer the framework against which we
9067330f729Sjoerg /// should link.
inferFrameworkLink(Module * Mod,const DirectoryEntry * FrameworkDir,FileManager & FileMgr)9077330f729Sjoerg static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
9087330f729Sjoerg                                FileManager &FileMgr) {
9097330f729Sjoerg   assert(Mod->IsFramework && "Can only infer linking for framework modules");
9107330f729Sjoerg   assert(!Mod->isSubFramework() &&
9117330f729Sjoerg          "Can only infer linking for top-level frameworks");
9127330f729Sjoerg 
9137330f729Sjoerg   SmallString<128> LibName;
9147330f729Sjoerg   LibName += FrameworkDir->getName();
9157330f729Sjoerg   llvm::sys::path::append(LibName, Mod->Name);
9167330f729Sjoerg 
9177330f729Sjoerg   // The library name of a framework has more than one possible extension since
9187330f729Sjoerg   // the introduction of the text-based dynamic library format. We need to check
9197330f729Sjoerg   // for both before we give up.
9207330f729Sjoerg   for (const char *extension : {"", ".tbd"}) {
9217330f729Sjoerg     llvm::sys::path::replace_extension(LibName, extension);
9227330f729Sjoerg     if (FileMgr.getFile(LibName)) {
9237330f729Sjoerg       Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
9247330f729Sjoerg                                                        /*IsFramework=*/true));
9257330f729Sjoerg       return;
9267330f729Sjoerg     }
9277330f729Sjoerg   }
9287330f729Sjoerg }
9297330f729Sjoerg 
inferFrameworkModule(const DirectoryEntry * FrameworkDir,bool IsSystem,Module * Parent)9307330f729Sjoerg Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
9317330f729Sjoerg                                         bool IsSystem, Module *Parent) {
9327330f729Sjoerg   Attributes Attrs;
9337330f729Sjoerg   Attrs.IsSystem = IsSystem;
9347330f729Sjoerg   return inferFrameworkModule(FrameworkDir, Attrs, Parent);
9357330f729Sjoerg }
9367330f729Sjoerg 
inferFrameworkModule(const DirectoryEntry * FrameworkDir,Attributes Attrs,Module * Parent)9377330f729Sjoerg Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
9387330f729Sjoerg                                         Attributes Attrs, Module *Parent) {
9397330f729Sjoerg   // Note: as an egregious but useful hack we use the real path here, because
9407330f729Sjoerg   // we might be looking at an embedded framework that symlinks out to a
9417330f729Sjoerg   // top-level framework, and we need to infer as if we were naming the
9427330f729Sjoerg   // top-level framework.
9437330f729Sjoerg   StringRef FrameworkDirName =
9447330f729Sjoerg       SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
9457330f729Sjoerg 
9467330f729Sjoerg   // In case this is a case-insensitive filesystem, use the canonical
9477330f729Sjoerg   // directory name as the ModuleName, since modules are case-sensitive.
9487330f729Sjoerg   // FIXME: we should be able to give a fix-it hint for the correct spelling.
9497330f729Sjoerg   SmallString<32> ModuleNameStorage;
9507330f729Sjoerg   StringRef ModuleName = sanitizeFilenameAsIdentifier(
9517330f729Sjoerg       llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
9527330f729Sjoerg 
9537330f729Sjoerg   // Check whether we've already found this module.
9547330f729Sjoerg   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
9557330f729Sjoerg     return Mod;
9567330f729Sjoerg 
9577330f729Sjoerg   FileManager &FileMgr = SourceMgr.getFileManager();
9587330f729Sjoerg 
9597330f729Sjoerg   // If the framework has a parent path from which we're allowed to infer
9607330f729Sjoerg   // a framework module, do so.
9617330f729Sjoerg   const FileEntry *ModuleMapFile = nullptr;
9627330f729Sjoerg   if (!Parent) {
9637330f729Sjoerg     // Determine whether we're allowed to infer a module map.
9647330f729Sjoerg     bool canInfer = false;
9657330f729Sjoerg     if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
9667330f729Sjoerg       // Figure out the parent path.
9677330f729Sjoerg       StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
9687330f729Sjoerg       if (auto ParentDir = FileMgr.getDirectory(Parent)) {
9697330f729Sjoerg         // Check whether we have already looked into the parent directory
9707330f729Sjoerg         // for a module map.
9717330f729Sjoerg         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
9727330f729Sjoerg           inferred = InferredDirectories.find(*ParentDir);
9737330f729Sjoerg         if (inferred == InferredDirectories.end()) {
9747330f729Sjoerg           // We haven't looked here before. Load a module map, if there is
9757330f729Sjoerg           // one.
9767330f729Sjoerg           bool IsFrameworkDir = Parent.endswith(".framework");
9777330f729Sjoerg           if (const FileEntry *ModMapFile =
9787330f729Sjoerg                 HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) {
9797330f729Sjoerg             parseModuleMapFile(ModMapFile, Attrs.IsSystem, *ParentDir);
9807330f729Sjoerg             inferred = InferredDirectories.find(*ParentDir);
9817330f729Sjoerg           }
9827330f729Sjoerg 
9837330f729Sjoerg           if (inferred == InferredDirectories.end())
9847330f729Sjoerg             inferred = InferredDirectories.insert(
9857330f729Sjoerg                          std::make_pair(*ParentDir, InferredDirectory())).first;
9867330f729Sjoerg         }
9877330f729Sjoerg 
9887330f729Sjoerg         if (inferred->second.InferModules) {
9897330f729Sjoerg           // We're allowed to infer for this directory, but make sure it's okay
9907330f729Sjoerg           // to infer this particular module.
9917330f729Sjoerg           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
9927330f729Sjoerg           canInfer = std::find(inferred->second.ExcludedModules.begin(),
9937330f729Sjoerg                                inferred->second.ExcludedModules.end(),
9947330f729Sjoerg                                Name) == inferred->second.ExcludedModules.end();
9957330f729Sjoerg 
9967330f729Sjoerg           Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
9977330f729Sjoerg           Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
9987330f729Sjoerg           Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
9997330f729Sjoerg           Attrs.NoUndeclaredIncludes |=
10007330f729Sjoerg               inferred->second.Attrs.NoUndeclaredIncludes;
10017330f729Sjoerg           ModuleMapFile = inferred->second.ModuleMapFile;
10027330f729Sjoerg         }
10037330f729Sjoerg       }
10047330f729Sjoerg     }
10057330f729Sjoerg 
10067330f729Sjoerg     // If we're not allowed to infer a framework module, don't.
10077330f729Sjoerg     if (!canInfer)
10087330f729Sjoerg       return nullptr;
10097330f729Sjoerg   } else
10107330f729Sjoerg     ModuleMapFile = getModuleMapFileForUniquing(Parent);
10117330f729Sjoerg 
10127330f729Sjoerg 
10137330f729Sjoerg   // Look for an umbrella header.
10147330f729Sjoerg   SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
10157330f729Sjoerg   llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
10167330f729Sjoerg   auto UmbrellaHeader = FileMgr.getFile(UmbrellaName);
10177330f729Sjoerg 
10187330f729Sjoerg   // FIXME: If there's no umbrella header, we could probably scan the
10197330f729Sjoerg   // framework to load *everything*. But, it's not clear that this is a good
10207330f729Sjoerg   // idea.
10217330f729Sjoerg   if (!UmbrellaHeader)
10227330f729Sjoerg     return nullptr;
10237330f729Sjoerg 
10247330f729Sjoerg   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
10257330f729Sjoerg                               /*IsFramework=*/true, /*IsExplicit=*/false,
10267330f729Sjoerg                               NumCreatedModules++);
10277330f729Sjoerg   InferredModuleAllowedBy[Result] = ModuleMapFile;
10287330f729Sjoerg   Result->IsInferred = true;
10297330f729Sjoerg   if (!Parent) {
10307330f729Sjoerg     if (LangOpts.CurrentModule == ModuleName)
10317330f729Sjoerg       SourceModule = Result;
10327330f729Sjoerg     Modules[ModuleName] = Result;
10337330f729Sjoerg     ModuleScopeIDs[Result] = CurrentModuleScopeID;
10347330f729Sjoerg   }
10357330f729Sjoerg 
10367330f729Sjoerg   Result->IsSystem |= Attrs.IsSystem;
10377330f729Sjoerg   Result->IsExternC |= Attrs.IsExternC;
10387330f729Sjoerg   Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
10397330f729Sjoerg   Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
10407330f729Sjoerg   Result->Directory = FrameworkDir;
10417330f729Sjoerg 
1042*e038c9c4Sjoerg   // Chop off the first framework bit, as that is implied.
1043*e038c9c4Sjoerg   StringRef RelativePath = UmbrellaName.str().substr(
1044*e038c9c4Sjoerg       Result->getTopLevelModule()->Directory->getName().size());
1045*e038c9c4Sjoerg   RelativePath = llvm::sys::path::relative_path(RelativePath);
1046*e038c9c4Sjoerg 
10477330f729Sjoerg   // umbrella header "umbrella-header-name"
1048*e038c9c4Sjoerg   setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h", RelativePath);
10497330f729Sjoerg 
10507330f729Sjoerg   // export *
10517330f729Sjoerg   Result->Exports.push_back(Module::ExportDecl(nullptr, true));
10527330f729Sjoerg 
10537330f729Sjoerg   // module * { export * }
10547330f729Sjoerg   Result->InferSubmodules = true;
10557330f729Sjoerg   Result->InferExportWildcard = true;
10567330f729Sjoerg 
10577330f729Sjoerg   // Look for subframeworks.
10587330f729Sjoerg   std::error_code EC;
10597330f729Sjoerg   SmallString<128> SubframeworksDirName
10607330f729Sjoerg     = StringRef(FrameworkDir->getName());
10617330f729Sjoerg   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
10627330f729Sjoerg   llvm::sys::path::native(SubframeworksDirName);
10637330f729Sjoerg   llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
10647330f729Sjoerg   for (llvm::vfs::directory_iterator
10657330f729Sjoerg            Dir = FS.dir_begin(SubframeworksDirName, EC),
10667330f729Sjoerg            DirEnd;
10677330f729Sjoerg        Dir != DirEnd && !EC; Dir.increment(EC)) {
10687330f729Sjoerg     if (!StringRef(Dir->path()).endswith(".framework"))
10697330f729Sjoerg       continue;
10707330f729Sjoerg 
10717330f729Sjoerg     if (auto SubframeworkDir =
10727330f729Sjoerg             FileMgr.getDirectory(Dir->path())) {
10737330f729Sjoerg       // Note: as an egregious but useful hack, we use the real path here and
10747330f729Sjoerg       // check whether it is actually a subdirectory of the parent directory.
10757330f729Sjoerg       // This will not be the case if the 'subframework' is actually a symlink
10767330f729Sjoerg       // out to a top-level framework.
10777330f729Sjoerg       StringRef SubframeworkDirName =
10787330f729Sjoerg           FileMgr.getCanonicalName(*SubframeworkDir);
10797330f729Sjoerg       bool FoundParent = false;
10807330f729Sjoerg       do {
10817330f729Sjoerg         // Get the parent directory name.
10827330f729Sjoerg         SubframeworkDirName
10837330f729Sjoerg           = llvm::sys::path::parent_path(SubframeworkDirName);
10847330f729Sjoerg         if (SubframeworkDirName.empty())
10857330f729Sjoerg           break;
10867330f729Sjoerg 
10877330f729Sjoerg         if (auto SubDir = FileMgr.getDirectory(SubframeworkDirName)) {
10887330f729Sjoerg           if (*SubDir == FrameworkDir) {
10897330f729Sjoerg             FoundParent = true;
10907330f729Sjoerg             break;
10917330f729Sjoerg           }
10927330f729Sjoerg         }
10937330f729Sjoerg       } while (true);
10947330f729Sjoerg 
10957330f729Sjoerg       if (!FoundParent)
10967330f729Sjoerg         continue;
10977330f729Sjoerg 
10987330f729Sjoerg       // FIXME: Do we want to warn about subframeworks without umbrella headers?
10997330f729Sjoerg       inferFrameworkModule(*SubframeworkDir, Attrs, Result);
11007330f729Sjoerg     }
11017330f729Sjoerg   }
11027330f729Sjoerg 
11037330f729Sjoerg   // If the module is a top-level framework, automatically link against the
11047330f729Sjoerg   // framework.
11057330f729Sjoerg   if (!Result->isSubFramework()) {
11067330f729Sjoerg     inferFrameworkLink(Result, FrameworkDir, FileMgr);
11077330f729Sjoerg   }
11087330f729Sjoerg 
11097330f729Sjoerg   return Result;
11107330f729Sjoerg }
11117330f729Sjoerg 
createShadowedModule(StringRef Name,bool IsFramework,Module * ShadowingModule)11127330f729Sjoerg Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
11137330f729Sjoerg                                         Module *ShadowingModule) {
11147330f729Sjoerg 
11157330f729Sjoerg   // Create a new module with this name.
11167330f729Sjoerg   Module *Result =
11177330f729Sjoerg       new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
11187330f729Sjoerg                  /*IsExplicit=*/false, NumCreatedModules++);
11197330f729Sjoerg   Result->ShadowingModule = ShadowingModule;
1120*e038c9c4Sjoerg   Result->markUnavailable(/*Unimportable*/true);
11217330f729Sjoerg   ModuleScopeIDs[Result] = CurrentModuleScopeID;
11227330f729Sjoerg   ShadowModules.push_back(Result);
11237330f729Sjoerg 
11247330f729Sjoerg   return Result;
11257330f729Sjoerg }
11267330f729Sjoerg 
setUmbrellaHeader(Module * Mod,const FileEntry * UmbrellaHeader,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)1127*e038c9c4Sjoerg void ModuleMap::setUmbrellaHeader(
1128*e038c9c4Sjoerg     Module *Mod, const FileEntry *UmbrellaHeader, const Twine &NameAsWritten,
1129*e038c9c4Sjoerg     const Twine &PathRelativeToRootModuleDirectory) {
11307330f729Sjoerg   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
11317330f729Sjoerg   Mod->Umbrella = UmbrellaHeader;
11327330f729Sjoerg   Mod->UmbrellaAsWritten = NameAsWritten.str();
1133*e038c9c4Sjoerg   Mod->UmbrellaRelativeToRootModuleDirectory =
1134*e038c9c4Sjoerg       PathRelativeToRootModuleDirectory.str();
11357330f729Sjoerg   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
11367330f729Sjoerg 
11377330f729Sjoerg   // Notify callbacks that we just added a new header.
11387330f729Sjoerg   for (const auto &Cb : Callbacks)
11397330f729Sjoerg     Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
11407330f729Sjoerg }
11417330f729Sjoerg 
setUmbrellaDir(Module * Mod,const DirectoryEntry * UmbrellaDir,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)11427330f729Sjoerg void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
1143*e038c9c4Sjoerg                                const Twine &NameAsWritten,
1144*e038c9c4Sjoerg                                const Twine &PathRelativeToRootModuleDirectory) {
11457330f729Sjoerg   Mod->Umbrella = UmbrellaDir;
11467330f729Sjoerg   Mod->UmbrellaAsWritten = NameAsWritten.str();
1147*e038c9c4Sjoerg   Mod->UmbrellaRelativeToRootModuleDirectory =
1148*e038c9c4Sjoerg       PathRelativeToRootModuleDirectory.str();
11497330f729Sjoerg   UmbrellaDirs[UmbrellaDir] = Mod;
11507330f729Sjoerg }
11517330f729Sjoerg 
addUnresolvedHeader(Module * Mod,Module::UnresolvedHeaderDirective Header,bool & NeedsFramework)11527330f729Sjoerg void ModuleMap::addUnresolvedHeader(Module *Mod,
11537330f729Sjoerg                                     Module::UnresolvedHeaderDirective Header,
11547330f729Sjoerg                                     bool &NeedsFramework) {
11557330f729Sjoerg   // If there is a builtin counterpart to this file, add it now so it can
11567330f729Sjoerg   // wrap the system header.
11577330f729Sjoerg   if (resolveAsBuiltinHeader(Mod, Header)) {
11587330f729Sjoerg     // If we have both a builtin and system version of the file, the
11597330f729Sjoerg     // builtin version may want to inject macros into the system header, so
11607330f729Sjoerg     // force the system header to be treated as a textual header in this
11617330f729Sjoerg     // case.
11627330f729Sjoerg     Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
11637330f729Sjoerg         headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
11647330f729Sjoerg     Header.HasBuiltinHeader = true;
11657330f729Sjoerg   }
11667330f729Sjoerg 
11677330f729Sjoerg   // If possible, don't stat the header until we need to. This requires the
11687330f729Sjoerg   // user to have provided us with some stat information about the file.
11697330f729Sjoerg   // FIXME: Add support for lazily stat'ing umbrella headers and excluded
11707330f729Sjoerg   // headers.
11717330f729Sjoerg   if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
11727330f729Sjoerg       Header.Kind != Module::HK_Excluded) {
11737330f729Sjoerg     // We expect more variation in mtime than size, so if we're given both,
11747330f729Sjoerg     // use the mtime as the key.
11757330f729Sjoerg     if (Header.ModTime)
11767330f729Sjoerg       LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
11777330f729Sjoerg     else
11787330f729Sjoerg       LazyHeadersBySize[*Header.Size].push_back(Mod);
11797330f729Sjoerg     Mod->UnresolvedHeaders.push_back(Header);
11807330f729Sjoerg     return;
11817330f729Sjoerg   }
11827330f729Sjoerg 
11837330f729Sjoerg   // We don't have stat information or can't defer looking this file up.
11847330f729Sjoerg   // Perform the lookup now.
11857330f729Sjoerg   resolveHeader(Mod, Header, NeedsFramework);
11867330f729Sjoerg }
11877330f729Sjoerg 
resolveHeaderDirectives(const FileEntry * File) const11887330f729Sjoerg void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
11897330f729Sjoerg   auto BySize = LazyHeadersBySize.find(File->getSize());
11907330f729Sjoerg   if (BySize != LazyHeadersBySize.end()) {
11917330f729Sjoerg     for (auto *M : BySize->second)
11927330f729Sjoerg       resolveHeaderDirectives(M);
11937330f729Sjoerg     LazyHeadersBySize.erase(BySize);
11947330f729Sjoerg   }
11957330f729Sjoerg 
11967330f729Sjoerg   auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
11977330f729Sjoerg   if (ByModTime != LazyHeadersByModTime.end()) {
11987330f729Sjoerg     for (auto *M : ByModTime->second)
11997330f729Sjoerg       resolveHeaderDirectives(M);
12007330f729Sjoerg     LazyHeadersByModTime.erase(ByModTime);
12017330f729Sjoerg   }
12027330f729Sjoerg }
12037330f729Sjoerg 
resolveHeaderDirectives(Module * Mod) const12047330f729Sjoerg void ModuleMap::resolveHeaderDirectives(Module *Mod) const {
12057330f729Sjoerg   bool NeedsFramework = false;
12067330f729Sjoerg   for (auto &Header : Mod->UnresolvedHeaders)
12077330f729Sjoerg     // This operation is logically const; we're just changing how we represent
12087330f729Sjoerg     // the header information for this file.
12097330f729Sjoerg     const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework);
12107330f729Sjoerg   Mod->UnresolvedHeaders.clear();
12117330f729Sjoerg }
12127330f729Sjoerg 
addHeader(Module * Mod,Module::Header Header,ModuleHeaderRole Role,bool Imported)12137330f729Sjoerg void ModuleMap::addHeader(Module *Mod, Module::Header Header,
12147330f729Sjoerg                           ModuleHeaderRole Role, bool Imported) {
12157330f729Sjoerg   KnownHeader KH(Mod, Role);
12167330f729Sjoerg 
12177330f729Sjoerg   // Only add each header to the headers list once.
12187330f729Sjoerg   // FIXME: Should we diagnose if a header is listed twice in the
12197330f729Sjoerg   // same module definition?
12207330f729Sjoerg   auto &HeaderList = Headers[Header.Entry];
12217330f729Sjoerg   for (auto H : HeaderList)
12227330f729Sjoerg     if (H == KH)
12237330f729Sjoerg       return;
12247330f729Sjoerg 
12257330f729Sjoerg   HeaderList.push_back(KH);
12267330f729Sjoerg   Mod->Headers[headerRoleToKind(Role)].push_back(Header);
12277330f729Sjoerg 
12287330f729Sjoerg   bool isCompilingModuleHeader =
12297330f729Sjoerg       LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
12307330f729Sjoerg   if (!Imported || isCompilingModuleHeader) {
12317330f729Sjoerg     // When we import HeaderFileInfo, the external source is expected to
12327330f729Sjoerg     // set the isModuleHeader flag itself.
12337330f729Sjoerg     HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
12347330f729Sjoerg                                     isCompilingModuleHeader);
12357330f729Sjoerg   }
12367330f729Sjoerg 
12377330f729Sjoerg   // Notify callbacks that we just added a new header.
12387330f729Sjoerg   for (const auto &Cb : Callbacks)
12397330f729Sjoerg     Cb->moduleMapAddHeader(Header.Entry->getName());
12407330f729Sjoerg }
12417330f729Sjoerg 
excludeHeader(Module * Mod,Module::Header Header)12427330f729Sjoerg void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
12437330f729Sjoerg   // Add this as a known header so we won't implicitly add it to any
12447330f729Sjoerg   // umbrella directory module.
12457330f729Sjoerg   // FIXME: Should we only exclude it from umbrella modules within the
12467330f729Sjoerg   // specified module?
12477330f729Sjoerg   (void) Headers[Header.Entry];
12487330f729Sjoerg 
12497330f729Sjoerg   Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
12507330f729Sjoerg }
12517330f729Sjoerg 
12527330f729Sjoerg const FileEntry *
getContainingModuleMapFile(const Module * Module) const12537330f729Sjoerg ModuleMap::getContainingModuleMapFile(const Module *Module) const {
12547330f729Sjoerg   if (Module->DefinitionLoc.isInvalid())
12557330f729Sjoerg     return nullptr;
12567330f729Sjoerg 
12577330f729Sjoerg   return SourceMgr.getFileEntryForID(
12587330f729Sjoerg            SourceMgr.getFileID(Module->DefinitionLoc));
12597330f729Sjoerg }
12607330f729Sjoerg 
getModuleMapFileForUniquing(const Module * M) const12617330f729Sjoerg const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
12627330f729Sjoerg   if (M->IsInferred) {
12637330f729Sjoerg     assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
12647330f729Sjoerg     return InferredModuleAllowedBy.find(M)->second;
12657330f729Sjoerg   }
12667330f729Sjoerg   return getContainingModuleMapFile(M);
12677330f729Sjoerg }
12687330f729Sjoerg 
setInferredModuleAllowedBy(Module * M,const FileEntry * ModMap)12697330f729Sjoerg void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
12707330f729Sjoerg   assert(M->IsInferred && "module not inferred");
12717330f729Sjoerg   InferredModuleAllowedBy[M] = ModMap;
12727330f729Sjoerg }
12737330f729Sjoerg 
addAdditionalModuleMapFile(const Module * M,const FileEntry * ModuleMap)1274*e038c9c4Sjoerg void ModuleMap::addAdditionalModuleMapFile(const Module *M,
1275*e038c9c4Sjoerg                                            const FileEntry *ModuleMap) {
1276*e038c9c4Sjoerg   AdditionalModMaps[M].insert(ModuleMap);
1277*e038c9c4Sjoerg }
1278*e038c9c4Sjoerg 
dump()12797330f729Sjoerg LLVM_DUMP_METHOD void ModuleMap::dump() {
12807330f729Sjoerg   llvm::errs() << "Modules:";
12817330f729Sjoerg   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
12827330f729Sjoerg                                         MEnd = Modules.end();
12837330f729Sjoerg        M != MEnd; ++M)
12847330f729Sjoerg     M->getValue()->print(llvm::errs(), 2);
12857330f729Sjoerg 
12867330f729Sjoerg   llvm::errs() << "Headers:";
12877330f729Sjoerg   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
12887330f729Sjoerg        H != HEnd; ++H) {
12897330f729Sjoerg     llvm::errs() << "  \"" << H->first->getName() << "\" -> ";
12907330f729Sjoerg     for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
12917330f729Sjoerg                                                       E = H->second.end();
12927330f729Sjoerg          I != E; ++I) {
12937330f729Sjoerg       if (I != H->second.begin())
12947330f729Sjoerg         llvm::errs() << ",";
12957330f729Sjoerg       llvm::errs() << I->getModule()->getFullModuleName();
12967330f729Sjoerg     }
12977330f729Sjoerg     llvm::errs() << "\n";
12987330f729Sjoerg   }
12997330f729Sjoerg }
13007330f729Sjoerg 
resolveExports(Module * Mod,bool Complain)13017330f729Sjoerg bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
13027330f729Sjoerg   auto Unresolved = std::move(Mod->UnresolvedExports);
13037330f729Sjoerg   Mod->UnresolvedExports.clear();
13047330f729Sjoerg   for (auto &UE : Unresolved) {
13057330f729Sjoerg     Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
13067330f729Sjoerg     if (Export.getPointer() || Export.getInt())
13077330f729Sjoerg       Mod->Exports.push_back(Export);
13087330f729Sjoerg     else
13097330f729Sjoerg       Mod->UnresolvedExports.push_back(UE);
13107330f729Sjoerg   }
13117330f729Sjoerg   return !Mod->UnresolvedExports.empty();
13127330f729Sjoerg }
13137330f729Sjoerg 
resolveUses(Module * Mod,bool Complain)13147330f729Sjoerg bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
13157330f729Sjoerg   auto Unresolved = std::move(Mod->UnresolvedDirectUses);
13167330f729Sjoerg   Mod->UnresolvedDirectUses.clear();
13177330f729Sjoerg   for (auto &UDU : Unresolved) {
13187330f729Sjoerg     Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
13197330f729Sjoerg     if (DirectUse)
13207330f729Sjoerg       Mod->DirectUses.push_back(DirectUse);
13217330f729Sjoerg     else
13227330f729Sjoerg       Mod->UnresolvedDirectUses.push_back(UDU);
13237330f729Sjoerg   }
13247330f729Sjoerg   return !Mod->UnresolvedDirectUses.empty();
13257330f729Sjoerg }
13267330f729Sjoerg 
resolveConflicts(Module * Mod,bool Complain)13277330f729Sjoerg bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
13287330f729Sjoerg   auto Unresolved = std::move(Mod->UnresolvedConflicts);
13297330f729Sjoerg   Mod->UnresolvedConflicts.clear();
13307330f729Sjoerg   for (auto &UC : Unresolved) {
13317330f729Sjoerg     if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
13327330f729Sjoerg       Module::Conflict Conflict;
13337330f729Sjoerg       Conflict.Other = OtherMod;
13347330f729Sjoerg       Conflict.Message = UC.Message;
13357330f729Sjoerg       Mod->Conflicts.push_back(Conflict);
13367330f729Sjoerg     } else
13377330f729Sjoerg       Mod->UnresolvedConflicts.push_back(UC);
13387330f729Sjoerg   }
13397330f729Sjoerg   return !Mod->UnresolvedConflicts.empty();
13407330f729Sjoerg }
13417330f729Sjoerg 
13427330f729Sjoerg //----------------------------------------------------------------------------//
13437330f729Sjoerg // Module map file parser
13447330f729Sjoerg //----------------------------------------------------------------------------//
13457330f729Sjoerg 
13467330f729Sjoerg namespace clang {
13477330f729Sjoerg 
13487330f729Sjoerg   /// A token in a module map file.
13497330f729Sjoerg   struct MMToken {
13507330f729Sjoerg     enum TokenKind {
13517330f729Sjoerg       Comma,
13527330f729Sjoerg       ConfigMacros,
13537330f729Sjoerg       Conflict,
13547330f729Sjoerg       EndOfFile,
13557330f729Sjoerg       HeaderKeyword,
13567330f729Sjoerg       Identifier,
13577330f729Sjoerg       Exclaim,
13587330f729Sjoerg       ExcludeKeyword,
13597330f729Sjoerg       ExplicitKeyword,
13607330f729Sjoerg       ExportKeyword,
13617330f729Sjoerg       ExportAsKeyword,
13627330f729Sjoerg       ExternKeyword,
13637330f729Sjoerg       FrameworkKeyword,
13647330f729Sjoerg       LinkKeyword,
13657330f729Sjoerg       ModuleKeyword,
13667330f729Sjoerg       Period,
13677330f729Sjoerg       PrivateKeyword,
13687330f729Sjoerg       UmbrellaKeyword,
13697330f729Sjoerg       UseKeyword,
13707330f729Sjoerg       RequiresKeyword,
13717330f729Sjoerg       Star,
13727330f729Sjoerg       StringLiteral,
13737330f729Sjoerg       IntegerLiteral,
13747330f729Sjoerg       TextualKeyword,
13757330f729Sjoerg       LBrace,
13767330f729Sjoerg       RBrace,
13777330f729Sjoerg       LSquare,
13787330f729Sjoerg       RSquare
13797330f729Sjoerg     } Kind;
13807330f729Sjoerg 
13817330f729Sjoerg     unsigned Location;
13827330f729Sjoerg     unsigned StringLength;
13837330f729Sjoerg     union {
13847330f729Sjoerg       // If Kind != IntegerLiteral.
13857330f729Sjoerg       const char *StringData;
13867330f729Sjoerg 
13877330f729Sjoerg       // If Kind == IntegerLiteral.
13887330f729Sjoerg       uint64_t IntegerValue;
13897330f729Sjoerg     };
13907330f729Sjoerg 
clearclang::MMToken13917330f729Sjoerg     void clear() {
13927330f729Sjoerg       Kind = EndOfFile;
13937330f729Sjoerg       Location = 0;
13947330f729Sjoerg       StringLength = 0;
13957330f729Sjoerg       StringData = nullptr;
13967330f729Sjoerg     }
13977330f729Sjoerg 
isclang::MMToken13987330f729Sjoerg     bool is(TokenKind K) const { return Kind == K; }
13997330f729Sjoerg 
getLocationclang::MMToken14007330f729Sjoerg     SourceLocation getLocation() const {
14017330f729Sjoerg       return SourceLocation::getFromRawEncoding(Location);
14027330f729Sjoerg     }
14037330f729Sjoerg 
getIntegerclang::MMToken14047330f729Sjoerg     uint64_t getInteger() const {
14057330f729Sjoerg       return Kind == IntegerLiteral ? IntegerValue : 0;
14067330f729Sjoerg     }
14077330f729Sjoerg 
getStringclang::MMToken14087330f729Sjoerg     StringRef getString() const {
14097330f729Sjoerg       return Kind == IntegerLiteral ? StringRef()
14107330f729Sjoerg                                     : StringRef(StringData, StringLength);
14117330f729Sjoerg     }
14127330f729Sjoerg   };
14137330f729Sjoerg 
14147330f729Sjoerg   class ModuleMapParser {
14157330f729Sjoerg     Lexer &L;
14167330f729Sjoerg     SourceManager &SourceMgr;
14177330f729Sjoerg 
14187330f729Sjoerg     /// Default target information, used only for string literal
14197330f729Sjoerg     /// parsing.
14207330f729Sjoerg     const TargetInfo *Target;
14217330f729Sjoerg 
14227330f729Sjoerg     DiagnosticsEngine &Diags;
14237330f729Sjoerg     ModuleMap &Map;
14247330f729Sjoerg 
14257330f729Sjoerg     /// The current module map file.
14267330f729Sjoerg     const FileEntry *ModuleMapFile;
14277330f729Sjoerg 
14287330f729Sjoerg     /// Source location of most recent parsed module declaration
14297330f729Sjoerg     SourceLocation CurrModuleDeclLoc;
14307330f729Sjoerg 
14317330f729Sjoerg     /// The directory that file names in this module map file should
14327330f729Sjoerg     /// be resolved relative to.
14337330f729Sjoerg     const DirectoryEntry *Directory;
14347330f729Sjoerg 
14357330f729Sjoerg     /// Whether this module map is in a system header directory.
14367330f729Sjoerg     bool IsSystem;
14377330f729Sjoerg 
14387330f729Sjoerg     /// Whether an error occurred.
14397330f729Sjoerg     bool HadError = false;
14407330f729Sjoerg 
14417330f729Sjoerg     /// Stores string data for the various string literals referenced
14427330f729Sjoerg     /// during parsing.
14437330f729Sjoerg     llvm::BumpPtrAllocator StringData;
14447330f729Sjoerg 
14457330f729Sjoerg     /// The current token.
14467330f729Sjoerg     MMToken Tok;
14477330f729Sjoerg 
14487330f729Sjoerg     /// The active module.
14497330f729Sjoerg     Module *ActiveModule = nullptr;
14507330f729Sjoerg 
14517330f729Sjoerg     /// Whether a module uses the 'requires excluded' hack to mark its
14527330f729Sjoerg     /// contents as 'textual'.
14537330f729Sjoerg     ///
14547330f729Sjoerg     /// On older Darwin SDK versions, 'requires excluded' is used to mark the
14557330f729Sjoerg     /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
14567330f729Sjoerg     /// non-modular headers.  For backwards compatibility, we continue to
14577330f729Sjoerg     /// support this idiom for just these modules, and map the headers to
14587330f729Sjoerg     /// 'textual' to match the original intent.
14597330f729Sjoerg     llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
14607330f729Sjoerg 
14617330f729Sjoerg     /// Consume the current token and return its location.
14627330f729Sjoerg     SourceLocation consumeToken();
14637330f729Sjoerg 
14647330f729Sjoerg     /// Skip tokens until we reach the a token with the given kind
14657330f729Sjoerg     /// (or the end of the file).
14667330f729Sjoerg     void skipUntil(MMToken::TokenKind K);
14677330f729Sjoerg 
14687330f729Sjoerg     using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
14697330f729Sjoerg 
14707330f729Sjoerg     bool parseModuleId(ModuleId &Id);
14717330f729Sjoerg     void parseModuleDecl();
14727330f729Sjoerg     void parseExternModuleDecl();
14737330f729Sjoerg     void parseRequiresDecl();
14747330f729Sjoerg     void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
14757330f729Sjoerg     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
14767330f729Sjoerg     void parseExportDecl();
14777330f729Sjoerg     void parseExportAsDecl();
14787330f729Sjoerg     void parseUseDecl();
14797330f729Sjoerg     void parseLinkDecl();
14807330f729Sjoerg     void parseConfigMacros();
14817330f729Sjoerg     void parseConflict();
14827330f729Sjoerg     void parseInferredModuleDecl(bool Framework, bool Explicit);
14837330f729Sjoerg 
14847330f729Sjoerg     /// Private modules are canonicalized as Foo_Private. Clang provides extra
14857330f729Sjoerg     /// module map search logic to find the appropriate private module when PCH
14867330f729Sjoerg     /// is used with implicit module maps. Warn when private modules are written
14877330f729Sjoerg     /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
14887330f729Sjoerg     void diagnosePrivateModules(SourceLocation ExplicitLoc,
14897330f729Sjoerg                                 SourceLocation FrameworkLoc);
14907330f729Sjoerg 
14917330f729Sjoerg     using Attributes = ModuleMap::Attributes;
14927330f729Sjoerg 
14937330f729Sjoerg     bool parseOptionalAttributes(Attributes &Attrs);
14947330f729Sjoerg 
14957330f729Sjoerg   public:
ModuleMapParser(Lexer & L,SourceManager & SourceMgr,const TargetInfo * Target,DiagnosticsEngine & Diags,ModuleMap & Map,const FileEntry * ModuleMapFile,const DirectoryEntry * Directory,bool IsSystem)14967330f729Sjoerg     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
14977330f729Sjoerg                              const TargetInfo *Target, DiagnosticsEngine &Diags,
14987330f729Sjoerg                              ModuleMap &Map, const FileEntry *ModuleMapFile,
14997330f729Sjoerg                              const DirectoryEntry *Directory, bool IsSystem)
15007330f729Sjoerg         : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
15017330f729Sjoerg           ModuleMapFile(ModuleMapFile), Directory(Directory),
15027330f729Sjoerg           IsSystem(IsSystem) {
15037330f729Sjoerg       Tok.clear();
15047330f729Sjoerg       consumeToken();
15057330f729Sjoerg     }
15067330f729Sjoerg 
15077330f729Sjoerg     bool parseModuleMapFile();
15087330f729Sjoerg 
terminatedByDirective()15097330f729Sjoerg     bool terminatedByDirective() { return false; }
getLocation()15107330f729Sjoerg     SourceLocation getLocation() { return Tok.getLocation(); }
15117330f729Sjoerg   };
15127330f729Sjoerg 
15137330f729Sjoerg } // namespace clang
15147330f729Sjoerg 
consumeToken()15157330f729Sjoerg SourceLocation ModuleMapParser::consumeToken() {
15167330f729Sjoerg   SourceLocation Result = Tok.getLocation();
15177330f729Sjoerg 
15187330f729Sjoerg retry:
15197330f729Sjoerg   Tok.clear();
15207330f729Sjoerg   Token LToken;
15217330f729Sjoerg   L.LexFromRawLexer(LToken);
15227330f729Sjoerg   Tok.Location = LToken.getLocation().getRawEncoding();
15237330f729Sjoerg   switch (LToken.getKind()) {
15247330f729Sjoerg   case tok::raw_identifier: {
15257330f729Sjoerg     StringRef RI = LToken.getRawIdentifier();
15267330f729Sjoerg     Tok.StringData = RI.data();
15277330f729Sjoerg     Tok.StringLength = RI.size();
15287330f729Sjoerg     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
15297330f729Sjoerg                  .Case("config_macros", MMToken::ConfigMacros)
15307330f729Sjoerg                  .Case("conflict", MMToken::Conflict)
15317330f729Sjoerg                  .Case("exclude", MMToken::ExcludeKeyword)
15327330f729Sjoerg                  .Case("explicit", MMToken::ExplicitKeyword)
15337330f729Sjoerg                  .Case("export", MMToken::ExportKeyword)
15347330f729Sjoerg                  .Case("export_as", MMToken::ExportAsKeyword)
15357330f729Sjoerg                  .Case("extern", MMToken::ExternKeyword)
15367330f729Sjoerg                  .Case("framework", MMToken::FrameworkKeyword)
15377330f729Sjoerg                  .Case("header", MMToken::HeaderKeyword)
15387330f729Sjoerg                  .Case("link", MMToken::LinkKeyword)
15397330f729Sjoerg                  .Case("module", MMToken::ModuleKeyword)
15407330f729Sjoerg                  .Case("private", MMToken::PrivateKeyword)
15417330f729Sjoerg                  .Case("requires", MMToken::RequiresKeyword)
15427330f729Sjoerg                  .Case("textual", MMToken::TextualKeyword)
15437330f729Sjoerg                  .Case("umbrella", MMToken::UmbrellaKeyword)
15447330f729Sjoerg                  .Case("use", MMToken::UseKeyword)
15457330f729Sjoerg                  .Default(MMToken::Identifier);
15467330f729Sjoerg     break;
15477330f729Sjoerg   }
15487330f729Sjoerg 
15497330f729Sjoerg   case tok::comma:
15507330f729Sjoerg     Tok.Kind = MMToken::Comma;
15517330f729Sjoerg     break;
15527330f729Sjoerg 
15537330f729Sjoerg   case tok::eof:
15547330f729Sjoerg     Tok.Kind = MMToken::EndOfFile;
15557330f729Sjoerg     break;
15567330f729Sjoerg 
15577330f729Sjoerg   case tok::l_brace:
15587330f729Sjoerg     Tok.Kind = MMToken::LBrace;
15597330f729Sjoerg     break;
15607330f729Sjoerg 
15617330f729Sjoerg   case tok::l_square:
15627330f729Sjoerg     Tok.Kind = MMToken::LSquare;
15637330f729Sjoerg     break;
15647330f729Sjoerg 
15657330f729Sjoerg   case tok::period:
15667330f729Sjoerg     Tok.Kind = MMToken::Period;
15677330f729Sjoerg     break;
15687330f729Sjoerg 
15697330f729Sjoerg   case tok::r_brace:
15707330f729Sjoerg     Tok.Kind = MMToken::RBrace;
15717330f729Sjoerg     break;
15727330f729Sjoerg 
15737330f729Sjoerg   case tok::r_square:
15747330f729Sjoerg     Tok.Kind = MMToken::RSquare;
15757330f729Sjoerg     break;
15767330f729Sjoerg 
15777330f729Sjoerg   case tok::star:
15787330f729Sjoerg     Tok.Kind = MMToken::Star;
15797330f729Sjoerg     break;
15807330f729Sjoerg 
15817330f729Sjoerg   case tok::exclaim:
15827330f729Sjoerg     Tok.Kind = MMToken::Exclaim;
15837330f729Sjoerg     break;
15847330f729Sjoerg 
15857330f729Sjoerg   case tok::string_literal: {
15867330f729Sjoerg     if (LToken.hasUDSuffix()) {
15877330f729Sjoerg       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
15887330f729Sjoerg       HadError = true;
15897330f729Sjoerg       goto retry;
15907330f729Sjoerg     }
15917330f729Sjoerg 
15927330f729Sjoerg     // Parse the string literal.
15937330f729Sjoerg     LangOptions LangOpts;
15947330f729Sjoerg     StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
15957330f729Sjoerg     if (StringLiteral.hadError)
15967330f729Sjoerg       goto retry;
15977330f729Sjoerg 
15987330f729Sjoerg     // Copy the string literal into our string data allocator.
15997330f729Sjoerg     unsigned Length = StringLiteral.GetStringLength();
16007330f729Sjoerg     char *Saved = StringData.Allocate<char>(Length + 1);
16017330f729Sjoerg     memcpy(Saved, StringLiteral.GetString().data(), Length);
16027330f729Sjoerg     Saved[Length] = 0;
16037330f729Sjoerg 
16047330f729Sjoerg     // Form the token.
16057330f729Sjoerg     Tok.Kind = MMToken::StringLiteral;
16067330f729Sjoerg     Tok.StringData = Saved;
16077330f729Sjoerg     Tok.StringLength = Length;
16087330f729Sjoerg     break;
16097330f729Sjoerg   }
16107330f729Sjoerg 
16117330f729Sjoerg   case tok::numeric_constant: {
16127330f729Sjoerg     // We don't support any suffixes or other complications.
16137330f729Sjoerg     SmallString<32> SpellingBuffer;
16147330f729Sjoerg     SpellingBuffer.resize(LToken.getLength() + 1);
16157330f729Sjoerg     const char *Start = SpellingBuffer.data();
16167330f729Sjoerg     unsigned Length =
16177330f729Sjoerg         Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts());
16187330f729Sjoerg     uint64_t Value;
16197330f729Sjoerg     if (StringRef(Start, Length).getAsInteger(0, Value)) {
16207330f729Sjoerg       Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
16217330f729Sjoerg       HadError = true;
16227330f729Sjoerg       goto retry;
16237330f729Sjoerg     }
16247330f729Sjoerg 
16257330f729Sjoerg     Tok.Kind = MMToken::IntegerLiteral;
16267330f729Sjoerg     Tok.IntegerValue = Value;
16277330f729Sjoerg     break;
16287330f729Sjoerg   }
16297330f729Sjoerg 
16307330f729Sjoerg   case tok::comment:
16317330f729Sjoerg     goto retry;
16327330f729Sjoerg 
16337330f729Sjoerg   case tok::hash:
16347330f729Sjoerg     // A module map can be terminated prematurely by
16357330f729Sjoerg     //   #pragma clang module contents
16367330f729Sjoerg     // When building the module, we'll treat the rest of the file as the
16377330f729Sjoerg     // contents of the module.
16387330f729Sjoerg     {
16397330f729Sjoerg       auto NextIsIdent = [&](StringRef Str) -> bool {
16407330f729Sjoerg         L.LexFromRawLexer(LToken);
16417330f729Sjoerg         return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
16427330f729Sjoerg                LToken.getRawIdentifier() == Str;
16437330f729Sjoerg       };
16447330f729Sjoerg       if (NextIsIdent("pragma") && NextIsIdent("clang") &&
16457330f729Sjoerg           NextIsIdent("module") && NextIsIdent("contents")) {
16467330f729Sjoerg         Tok.Kind = MMToken::EndOfFile;
16477330f729Sjoerg         break;
16487330f729Sjoerg       }
16497330f729Sjoerg     }
16507330f729Sjoerg     LLVM_FALLTHROUGH;
16517330f729Sjoerg 
16527330f729Sjoerg   default:
16537330f729Sjoerg     Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
16547330f729Sjoerg     HadError = true;
16557330f729Sjoerg     goto retry;
16567330f729Sjoerg   }
16577330f729Sjoerg 
16587330f729Sjoerg   return Result;
16597330f729Sjoerg }
16607330f729Sjoerg 
skipUntil(MMToken::TokenKind K)16617330f729Sjoerg void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
16627330f729Sjoerg   unsigned braceDepth = 0;
16637330f729Sjoerg   unsigned squareDepth = 0;
16647330f729Sjoerg   do {
16657330f729Sjoerg     switch (Tok.Kind) {
16667330f729Sjoerg     case MMToken::EndOfFile:
16677330f729Sjoerg       return;
16687330f729Sjoerg 
16697330f729Sjoerg     case MMToken::LBrace:
16707330f729Sjoerg       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
16717330f729Sjoerg         return;
16727330f729Sjoerg 
16737330f729Sjoerg       ++braceDepth;
16747330f729Sjoerg       break;
16757330f729Sjoerg 
16767330f729Sjoerg     case MMToken::LSquare:
16777330f729Sjoerg       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
16787330f729Sjoerg         return;
16797330f729Sjoerg 
16807330f729Sjoerg       ++squareDepth;
16817330f729Sjoerg       break;
16827330f729Sjoerg 
16837330f729Sjoerg     case MMToken::RBrace:
16847330f729Sjoerg       if (braceDepth > 0)
16857330f729Sjoerg         --braceDepth;
16867330f729Sjoerg       else if (Tok.is(K))
16877330f729Sjoerg         return;
16887330f729Sjoerg       break;
16897330f729Sjoerg 
16907330f729Sjoerg     case MMToken::RSquare:
16917330f729Sjoerg       if (squareDepth > 0)
16927330f729Sjoerg         --squareDepth;
16937330f729Sjoerg       else if (Tok.is(K))
16947330f729Sjoerg         return;
16957330f729Sjoerg       break;
16967330f729Sjoerg 
16977330f729Sjoerg     default:
16987330f729Sjoerg       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
16997330f729Sjoerg         return;
17007330f729Sjoerg       break;
17017330f729Sjoerg     }
17027330f729Sjoerg 
17037330f729Sjoerg    consumeToken();
17047330f729Sjoerg   } while (true);
17057330f729Sjoerg }
17067330f729Sjoerg 
17077330f729Sjoerg /// Parse a module-id.
17087330f729Sjoerg ///
17097330f729Sjoerg ///   module-id:
17107330f729Sjoerg ///     identifier
17117330f729Sjoerg ///     identifier '.' module-id
17127330f729Sjoerg ///
17137330f729Sjoerg /// \returns true if an error occurred, false otherwise.
parseModuleId(ModuleId & Id)17147330f729Sjoerg bool ModuleMapParser::parseModuleId(ModuleId &Id) {
17157330f729Sjoerg   Id.clear();
17167330f729Sjoerg   do {
17177330f729Sjoerg     if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1718*e038c9c4Sjoerg       Id.push_back(
1719*e038c9c4Sjoerg           std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
17207330f729Sjoerg       consumeToken();
17217330f729Sjoerg     } else {
17227330f729Sjoerg       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
17237330f729Sjoerg       return true;
17247330f729Sjoerg     }
17257330f729Sjoerg 
17267330f729Sjoerg     if (!Tok.is(MMToken::Period))
17277330f729Sjoerg       break;
17287330f729Sjoerg 
17297330f729Sjoerg     consumeToken();
17307330f729Sjoerg   } while (true);
17317330f729Sjoerg 
17327330f729Sjoerg   return false;
17337330f729Sjoerg }
17347330f729Sjoerg 
17357330f729Sjoerg namespace {
17367330f729Sjoerg 
17377330f729Sjoerg   /// Enumerates the known attributes.
17387330f729Sjoerg   enum AttributeKind {
17397330f729Sjoerg     /// An unknown attribute.
17407330f729Sjoerg     AT_unknown,
17417330f729Sjoerg 
17427330f729Sjoerg     /// The 'system' attribute.
17437330f729Sjoerg     AT_system,
17447330f729Sjoerg 
17457330f729Sjoerg     /// The 'extern_c' attribute.
17467330f729Sjoerg     AT_extern_c,
17477330f729Sjoerg 
17487330f729Sjoerg     /// The 'exhaustive' attribute.
17497330f729Sjoerg     AT_exhaustive,
17507330f729Sjoerg 
17517330f729Sjoerg     /// The 'no_undeclared_includes' attribute.
17527330f729Sjoerg     AT_no_undeclared_includes
17537330f729Sjoerg   };
17547330f729Sjoerg 
17557330f729Sjoerg } // namespace
17567330f729Sjoerg 
17577330f729Sjoerg /// Private modules are canonicalized as Foo_Private. Clang provides extra
17587330f729Sjoerg /// module map search logic to find the appropriate private module when PCH
17597330f729Sjoerg /// is used with implicit module maps. Warn when private modules are written
17607330f729Sjoerg /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
diagnosePrivateModules(SourceLocation ExplicitLoc,SourceLocation FrameworkLoc)17617330f729Sjoerg void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
17627330f729Sjoerg                                              SourceLocation FrameworkLoc) {
17637330f729Sjoerg   auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
17647330f729Sjoerg                              const Module *M, SourceRange ReplLoc) {
17657330f729Sjoerg     auto D = Diags.Report(ActiveModule->DefinitionLoc,
17667330f729Sjoerg                           diag::note_mmap_rename_top_level_private_module);
17677330f729Sjoerg     D << BadName << M->Name;
17687330f729Sjoerg     D << FixItHint::CreateReplacement(ReplLoc, Canonical);
17697330f729Sjoerg   };
17707330f729Sjoerg 
17717330f729Sjoerg   for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
17727330f729Sjoerg     auto const *M = E->getValue();
17737330f729Sjoerg     if (M->Directory != ActiveModule->Directory)
17747330f729Sjoerg       continue;
17757330f729Sjoerg 
17767330f729Sjoerg     SmallString<128> FullName(ActiveModule->getFullModuleName());
17777330f729Sjoerg     if (!FullName.startswith(M->Name) && !FullName.endswith("Private"))
17787330f729Sjoerg       continue;
17797330f729Sjoerg     SmallString<128> FixedPrivModDecl;
17807330f729Sjoerg     SmallString<128> Canonical(M->Name);
17817330f729Sjoerg     Canonical.append("_Private");
17827330f729Sjoerg 
17837330f729Sjoerg     // Foo.Private -> Foo_Private
17847330f729Sjoerg     if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
17857330f729Sjoerg         M->Name == ActiveModule->Parent->Name) {
17867330f729Sjoerg       Diags.Report(ActiveModule->DefinitionLoc,
17877330f729Sjoerg                    diag::warn_mmap_mismatched_private_submodule)
17887330f729Sjoerg           << FullName;
17897330f729Sjoerg 
17907330f729Sjoerg       SourceLocation FixItInitBegin = CurrModuleDeclLoc;
17917330f729Sjoerg       if (FrameworkLoc.isValid())
17927330f729Sjoerg         FixItInitBegin = FrameworkLoc;
17937330f729Sjoerg       if (ExplicitLoc.isValid())
17947330f729Sjoerg         FixItInitBegin = ExplicitLoc;
17957330f729Sjoerg 
17967330f729Sjoerg       if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
17977330f729Sjoerg         FixedPrivModDecl.append("framework ");
17987330f729Sjoerg       FixedPrivModDecl.append("module ");
17997330f729Sjoerg       FixedPrivModDecl.append(Canonical);
18007330f729Sjoerg 
18017330f729Sjoerg       GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
18027330f729Sjoerg                       SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
18037330f729Sjoerg       continue;
18047330f729Sjoerg     }
18057330f729Sjoerg 
18067330f729Sjoerg     // FooPrivate and whatnots -> Foo_Private
18077330f729Sjoerg     if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
18087330f729Sjoerg         ActiveModule->Name != Canonical) {
18097330f729Sjoerg       Diags.Report(ActiveModule->DefinitionLoc,
18107330f729Sjoerg                    diag::warn_mmap_mismatched_private_module_name)
18117330f729Sjoerg           << ActiveModule->Name;
18127330f729Sjoerg       GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
18137330f729Sjoerg                       SourceRange(ActiveModule->DefinitionLoc));
18147330f729Sjoerg     }
18157330f729Sjoerg   }
18167330f729Sjoerg }
18177330f729Sjoerg 
18187330f729Sjoerg /// Parse a module declaration.
18197330f729Sjoerg ///
18207330f729Sjoerg ///   module-declaration:
18217330f729Sjoerg ///     'extern' 'module' module-id string-literal
18227330f729Sjoerg ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
18237330f729Sjoerg ///       { module-member* }
18247330f729Sjoerg ///
18257330f729Sjoerg ///   module-member:
18267330f729Sjoerg ///     requires-declaration
18277330f729Sjoerg ///     header-declaration
18287330f729Sjoerg ///     submodule-declaration
18297330f729Sjoerg ///     export-declaration
18307330f729Sjoerg ///     export-as-declaration
18317330f729Sjoerg ///     link-declaration
18327330f729Sjoerg ///
18337330f729Sjoerg ///   submodule-declaration:
18347330f729Sjoerg ///     module-declaration
18357330f729Sjoerg ///     inferred-submodule-declaration
parseModuleDecl()18367330f729Sjoerg void ModuleMapParser::parseModuleDecl() {
18377330f729Sjoerg   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
18387330f729Sjoerg          Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
18397330f729Sjoerg   if (Tok.is(MMToken::ExternKeyword)) {
18407330f729Sjoerg     parseExternModuleDecl();
18417330f729Sjoerg     return;
18427330f729Sjoerg   }
18437330f729Sjoerg 
18447330f729Sjoerg   // Parse 'explicit' or 'framework' keyword, if present.
18457330f729Sjoerg   SourceLocation ExplicitLoc;
18467330f729Sjoerg   SourceLocation FrameworkLoc;
18477330f729Sjoerg   bool Explicit = false;
18487330f729Sjoerg   bool Framework = false;
18497330f729Sjoerg 
18507330f729Sjoerg   // Parse 'explicit' keyword, if present.
18517330f729Sjoerg   if (Tok.is(MMToken::ExplicitKeyword)) {
18527330f729Sjoerg     ExplicitLoc = consumeToken();
18537330f729Sjoerg     Explicit = true;
18547330f729Sjoerg   }
18557330f729Sjoerg 
18567330f729Sjoerg   // Parse 'framework' keyword, if present.
18577330f729Sjoerg   if (Tok.is(MMToken::FrameworkKeyword)) {
18587330f729Sjoerg     FrameworkLoc = consumeToken();
18597330f729Sjoerg     Framework = true;
18607330f729Sjoerg   }
18617330f729Sjoerg 
18627330f729Sjoerg   // Parse 'module' keyword.
18637330f729Sjoerg   if (!Tok.is(MMToken::ModuleKeyword)) {
18647330f729Sjoerg     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
18657330f729Sjoerg     consumeToken();
18667330f729Sjoerg     HadError = true;
18677330f729Sjoerg     return;
18687330f729Sjoerg   }
18697330f729Sjoerg   CurrModuleDeclLoc = consumeToken(); // 'module' keyword
18707330f729Sjoerg 
18717330f729Sjoerg   // If we have a wildcard for the module name, this is an inferred submodule.
18727330f729Sjoerg   // Parse it.
18737330f729Sjoerg   if (Tok.is(MMToken::Star))
18747330f729Sjoerg     return parseInferredModuleDecl(Framework, Explicit);
18757330f729Sjoerg 
18767330f729Sjoerg   // Parse the module name.
18777330f729Sjoerg   ModuleId Id;
18787330f729Sjoerg   if (parseModuleId(Id)) {
18797330f729Sjoerg     HadError = true;
18807330f729Sjoerg     return;
18817330f729Sjoerg   }
18827330f729Sjoerg 
18837330f729Sjoerg   if (ActiveModule) {
18847330f729Sjoerg     if (Id.size() > 1) {
18857330f729Sjoerg       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
18867330f729Sjoerg         << SourceRange(Id.front().second, Id.back().second);
18877330f729Sjoerg 
18887330f729Sjoerg       HadError = true;
18897330f729Sjoerg       return;
18907330f729Sjoerg     }
18917330f729Sjoerg   } else if (Id.size() == 1 && Explicit) {
18927330f729Sjoerg     // Top-level modules can't be explicit.
18937330f729Sjoerg     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
18947330f729Sjoerg     Explicit = false;
18957330f729Sjoerg     ExplicitLoc = SourceLocation();
18967330f729Sjoerg     HadError = true;
18977330f729Sjoerg   }
18987330f729Sjoerg 
18997330f729Sjoerg   Module *PreviousActiveModule = ActiveModule;
19007330f729Sjoerg   if (Id.size() > 1) {
19017330f729Sjoerg     // This module map defines a submodule. Go find the module of which it
19027330f729Sjoerg     // is a submodule.
19037330f729Sjoerg     ActiveModule = nullptr;
19047330f729Sjoerg     const Module *TopLevelModule = nullptr;
19057330f729Sjoerg     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
19067330f729Sjoerg       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
19077330f729Sjoerg         if (I == 0)
19087330f729Sjoerg           TopLevelModule = Next;
19097330f729Sjoerg         ActiveModule = Next;
19107330f729Sjoerg         continue;
19117330f729Sjoerg       }
19127330f729Sjoerg 
1913*e038c9c4Sjoerg       Diags.Report(Id[I].second, diag::err_mmap_missing_parent_module)
1914*e038c9c4Sjoerg           << Id[I].first << (ActiveModule != nullptr)
1915*e038c9c4Sjoerg           << (ActiveModule
1916*e038c9c4Sjoerg                   ? ActiveModule->getTopLevelModule()->getFullModuleName()
1917*e038c9c4Sjoerg                   : "");
19187330f729Sjoerg       HadError = true;
19197330f729Sjoerg     }
19207330f729Sjoerg 
1921*e038c9c4Sjoerg     if (TopLevelModule &&
1922*e038c9c4Sjoerg         ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
19237330f729Sjoerg       assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
19247330f729Sjoerg              "submodule defined in same file as 'module *' that allowed its "
19257330f729Sjoerg              "top-level module");
19267330f729Sjoerg       Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
19277330f729Sjoerg     }
19287330f729Sjoerg   }
19297330f729Sjoerg 
19307330f729Sjoerg   StringRef ModuleName = Id.back().first;
19317330f729Sjoerg   SourceLocation ModuleNameLoc = Id.back().second;
19327330f729Sjoerg 
19337330f729Sjoerg   // Parse the optional attribute list.
19347330f729Sjoerg   Attributes Attrs;
19357330f729Sjoerg   if (parseOptionalAttributes(Attrs))
19367330f729Sjoerg     return;
19377330f729Sjoerg 
19387330f729Sjoerg   // Parse the opening brace.
19397330f729Sjoerg   if (!Tok.is(MMToken::LBrace)) {
19407330f729Sjoerg     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
19417330f729Sjoerg       << ModuleName;
19427330f729Sjoerg     HadError = true;
19437330f729Sjoerg     return;
19447330f729Sjoerg   }
19457330f729Sjoerg   SourceLocation LBraceLoc = consumeToken();
19467330f729Sjoerg 
19477330f729Sjoerg   // Determine whether this (sub)module has already been defined.
19487330f729Sjoerg   Module *ShadowingModule = nullptr;
19497330f729Sjoerg   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
19507330f729Sjoerg     // We might see a (re)definition of a module that we already have a
19517330f729Sjoerg     // definition for in two cases:
19527330f729Sjoerg     //  - If we loaded one definition from an AST file and we've just found a
19537330f729Sjoerg     //    corresponding definition in a module map file, or
19547330f729Sjoerg     bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
19557330f729Sjoerg     //  - If we're building a (preprocessed) module and we've just loaded the
19567330f729Sjoerg     //    module map file from which it was created.
19577330f729Sjoerg     bool ParsedAsMainInput =
19587330f729Sjoerg         Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
19597330f729Sjoerg         Map.LangOpts.CurrentModule == ModuleName &&
19607330f729Sjoerg         SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
19617330f729Sjoerg             SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
19627330f729Sjoerg     if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
19637330f729Sjoerg       // Skip the module definition.
19647330f729Sjoerg       skipUntil(MMToken::RBrace);
19657330f729Sjoerg       if (Tok.is(MMToken::RBrace))
19667330f729Sjoerg         consumeToken();
19677330f729Sjoerg       else {
19687330f729Sjoerg         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
19697330f729Sjoerg         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
19707330f729Sjoerg         HadError = true;
19717330f729Sjoerg       }
19727330f729Sjoerg       return;
19737330f729Sjoerg     }
19747330f729Sjoerg 
19757330f729Sjoerg     if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
19767330f729Sjoerg       ShadowingModule = Existing;
19777330f729Sjoerg     } else {
19787330f729Sjoerg       // This is not a shawdowed module decl, it is an illegal redefinition.
19797330f729Sjoerg       Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
19807330f729Sjoerg           << ModuleName;
19817330f729Sjoerg       Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
19827330f729Sjoerg 
19837330f729Sjoerg       // Skip the module definition.
19847330f729Sjoerg       skipUntil(MMToken::RBrace);
19857330f729Sjoerg       if (Tok.is(MMToken::RBrace))
19867330f729Sjoerg         consumeToken();
19877330f729Sjoerg 
19887330f729Sjoerg       HadError = true;
19897330f729Sjoerg       return;
19907330f729Sjoerg     }
19917330f729Sjoerg   }
19927330f729Sjoerg 
19937330f729Sjoerg   // Start defining this module.
19947330f729Sjoerg   if (ShadowingModule) {
19957330f729Sjoerg     ActiveModule =
19967330f729Sjoerg         Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
19977330f729Sjoerg   } else {
19987330f729Sjoerg     ActiveModule =
19997330f729Sjoerg         Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
20007330f729Sjoerg             .first;
20017330f729Sjoerg   }
20027330f729Sjoerg 
20037330f729Sjoerg   ActiveModule->DefinitionLoc = ModuleNameLoc;
20047330f729Sjoerg   if (Attrs.IsSystem || IsSystem)
20057330f729Sjoerg     ActiveModule->IsSystem = true;
20067330f729Sjoerg   if (Attrs.IsExternC)
20077330f729Sjoerg     ActiveModule->IsExternC = true;
20087330f729Sjoerg   if (Attrs.NoUndeclaredIncludes ||
20097330f729Sjoerg       (!ActiveModule->Parent && ModuleName == "Darwin"))
20107330f729Sjoerg     ActiveModule->NoUndeclaredIncludes = true;
20117330f729Sjoerg   ActiveModule->Directory = Directory;
20127330f729Sjoerg 
20137330f729Sjoerg   StringRef MapFileName(ModuleMapFile->getName());
20147330f729Sjoerg   if (MapFileName.endswith("module.private.modulemap") ||
20157330f729Sjoerg       MapFileName.endswith("module_private.map")) {
20167330f729Sjoerg     ActiveModule->ModuleMapIsPrivate = true;
20177330f729Sjoerg   }
20187330f729Sjoerg 
20197330f729Sjoerg   // Private modules named as FooPrivate, Foo.Private or similar are likely a
20207330f729Sjoerg   // user error; provide warnings, notes and fixits to direct users to use
20217330f729Sjoerg   // Foo_Private instead.
20227330f729Sjoerg   SourceLocation StartLoc =
20237330f729Sjoerg       SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
20247330f729Sjoerg   if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
20257330f729Sjoerg       !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
20267330f729Sjoerg                        StartLoc) &&
20277330f729Sjoerg       !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
20287330f729Sjoerg                        StartLoc) &&
20297330f729Sjoerg       ActiveModule->ModuleMapIsPrivate)
20307330f729Sjoerg     diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
20317330f729Sjoerg 
20327330f729Sjoerg   bool Done = false;
20337330f729Sjoerg   do {
20347330f729Sjoerg     switch (Tok.Kind) {
20357330f729Sjoerg     case MMToken::EndOfFile:
20367330f729Sjoerg     case MMToken::RBrace:
20377330f729Sjoerg       Done = true;
20387330f729Sjoerg       break;
20397330f729Sjoerg 
20407330f729Sjoerg     case MMToken::ConfigMacros:
20417330f729Sjoerg       parseConfigMacros();
20427330f729Sjoerg       break;
20437330f729Sjoerg 
20447330f729Sjoerg     case MMToken::Conflict:
20457330f729Sjoerg       parseConflict();
20467330f729Sjoerg       break;
20477330f729Sjoerg 
20487330f729Sjoerg     case MMToken::ExplicitKeyword:
20497330f729Sjoerg     case MMToken::ExternKeyword:
20507330f729Sjoerg     case MMToken::FrameworkKeyword:
20517330f729Sjoerg     case MMToken::ModuleKeyword:
20527330f729Sjoerg       parseModuleDecl();
20537330f729Sjoerg       break;
20547330f729Sjoerg 
20557330f729Sjoerg     case MMToken::ExportKeyword:
20567330f729Sjoerg       parseExportDecl();
20577330f729Sjoerg       break;
20587330f729Sjoerg 
20597330f729Sjoerg     case MMToken::ExportAsKeyword:
20607330f729Sjoerg       parseExportAsDecl();
20617330f729Sjoerg       break;
20627330f729Sjoerg 
20637330f729Sjoerg     case MMToken::UseKeyword:
20647330f729Sjoerg       parseUseDecl();
20657330f729Sjoerg       break;
20667330f729Sjoerg 
20677330f729Sjoerg     case MMToken::RequiresKeyword:
20687330f729Sjoerg       parseRequiresDecl();
20697330f729Sjoerg       break;
20707330f729Sjoerg 
20717330f729Sjoerg     case MMToken::TextualKeyword:
20727330f729Sjoerg       parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
20737330f729Sjoerg       break;
20747330f729Sjoerg 
20757330f729Sjoerg     case MMToken::UmbrellaKeyword: {
20767330f729Sjoerg       SourceLocation UmbrellaLoc = consumeToken();
20777330f729Sjoerg       if (Tok.is(MMToken::HeaderKeyword))
20787330f729Sjoerg         parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
20797330f729Sjoerg       else
20807330f729Sjoerg         parseUmbrellaDirDecl(UmbrellaLoc);
20817330f729Sjoerg       break;
20827330f729Sjoerg     }
20837330f729Sjoerg 
20847330f729Sjoerg     case MMToken::ExcludeKeyword:
20857330f729Sjoerg       parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
20867330f729Sjoerg       break;
20877330f729Sjoerg 
20887330f729Sjoerg     case MMToken::PrivateKeyword:
20897330f729Sjoerg       parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
20907330f729Sjoerg       break;
20917330f729Sjoerg 
20927330f729Sjoerg     case MMToken::HeaderKeyword:
20937330f729Sjoerg       parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
20947330f729Sjoerg       break;
20957330f729Sjoerg 
20967330f729Sjoerg     case MMToken::LinkKeyword:
20977330f729Sjoerg       parseLinkDecl();
20987330f729Sjoerg       break;
20997330f729Sjoerg 
21007330f729Sjoerg     default:
21017330f729Sjoerg       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
21027330f729Sjoerg       consumeToken();
21037330f729Sjoerg       break;
21047330f729Sjoerg     }
21057330f729Sjoerg   } while (!Done);
21067330f729Sjoerg 
21077330f729Sjoerg   if (Tok.is(MMToken::RBrace))
21087330f729Sjoerg     consumeToken();
21097330f729Sjoerg   else {
21107330f729Sjoerg     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
21117330f729Sjoerg     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
21127330f729Sjoerg     HadError = true;
21137330f729Sjoerg   }
21147330f729Sjoerg 
21157330f729Sjoerg   // If the active module is a top-level framework, and there are no link
21167330f729Sjoerg   // libraries, automatically link against the framework.
21177330f729Sjoerg   if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
21187330f729Sjoerg       ActiveModule->LinkLibraries.empty()) {
21197330f729Sjoerg     inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
21207330f729Sjoerg   }
21217330f729Sjoerg 
21227330f729Sjoerg   // If the module meets all requirements but is still unavailable, mark the
21237330f729Sjoerg   // whole tree as unavailable to prevent it from building.
2124*e038c9c4Sjoerg   if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
21257330f729Sjoerg       ActiveModule->Parent) {
2126*e038c9c4Sjoerg     ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false);
21277330f729Sjoerg     ActiveModule->getTopLevelModule()->MissingHeaders.append(
21287330f729Sjoerg       ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
21297330f729Sjoerg   }
21307330f729Sjoerg 
21317330f729Sjoerg   // We're done parsing this module. Pop back to the previous module.
21327330f729Sjoerg   ActiveModule = PreviousActiveModule;
21337330f729Sjoerg }
21347330f729Sjoerg 
21357330f729Sjoerg /// Parse an extern module declaration.
21367330f729Sjoerg ///
21377330f729Sjoerg ///   extern module-declaration:
21387330f729Sjoerg ///     'extern' 'module' module-id string-literal
parseExternModuleDecl()21397330f729Sjoerg void ModuleMapParser::parseExternModuleDecl() {
21407330f729Sjoerg   assert(Tok.is(MMToken::ExternKeyword));
21417330f729Sjoerg   SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
21427330f729Sjoerg 
21437330f729Sjoerg   // Parse 'module' keyword.
21447330f729Sjoerg   if (!Tok.is(MMToken::ModuleKeyword)) {
21457330f729Sjoerg     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
21467330f729Sjoerg     consumeToken();
21477330f729Sjoerg     HadError = true;
21487330f729Sjoerg     return;
21497330f729Sjoerg   }
21507330f729Sjoerg   consumeToken(); // 'module' keyword
21517330f729Sjoerg 
21527330f729Sjoerg   // Parse the module name.
21537330f729Sjoerg   ModuleId Id;
21547330f729Sjoerg   if (parseModuleId(Id)) {
21557330f729Sjoerg     HadError = true;
21567330f729Sjoerg     return;
21577330f729Sjoerg   }
21587330f729Sjoerg 
21597330f729Sjoerg   // Parse the referenced module map file name.
21607330f729Sjoerg   if (!Tok.is(MMToken::StringLiteral)) {
21617330f729Sjoerg     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
21627330f729Sjoerg     HadError = true;
21637330f729Sjoerg     return;
21647330f729Sjoerg   }
2165*e038c9c4Sjoerg   std::string FileName = std::string(Tok.getString());
21667330f729Sjoerg   consumeToken(); // filename
21677330f729Sjoerg 
21687330f729Sjoerg   StringRef FileNameRef = FileName;
21697330f729Sjoerg   SmallString<128> ModuleMapFileName;
21707330f729Sjoerg   if (llvm::sys::path::is_relative(FileNameRef)) {
21717330f729Sjoerg     ModuleMapFileName += Directory->getName();
21727330f729Sjoerg     llvm::sys::path::append(ModuleMapFileName, FileName);
21737330f729Sjoerg     FileNameRef = ModuleMapFileName;
21747330f729Sjoerg   }
21757330f729Sjoerg   if (auto File = SourceMgr.getFileManager().getFile(FileNameRef))
21767330f729Sjoerg     Map.parseModuleMapFile(
21777330f729Sjoerg         *File, /*IsSystem=*/false,
21787330f729Sjoerg         Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
21797330f729Sjoerg             ? Directory
21807330f729Sjoerg             : (*File)->getDir(),
21817330f729Sjoerg         FileID(), nullptr, ExternLoc);
21827330f729Sjoerg }
21837330f729Sjoerg 
21847330f729Sjoerg /// Whether to add the requirement \p Feature to the module \p M.
21857330f729Sjoerg ///
21867330f729Sjoerg /// This preserves backwards compatibility for two hacks in the Darwin system
21877330f729Sjoerg /// module map files:
21887330f729Sjoerg ///
21897330f729Sjoerg /// 1. The use of 'requires excluded' to make headers non-modular, which
21907330f729Sjoerg ///    should really be mapped to 'textual' now that we have this feature.  We
21917330f729Sjoerg ///    drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
21927330f729Sjoerg ///    true.  Later, this bit will be used to map all the headers inside this
21937330f729Sjoerg ///    module to 'textual'.
21947330f729Sjoerg ///
21957330f729Sjoerg ///    This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
21967330f729Sjoerg ///
21977330f729Sjoerg /// 2. Removes a bogus cplusplus requirement from IOKit.avc.  This requirement
21987330f729Sjoerg ///    was never correct and causes issues now that we check it, so drop it.
shouldAddRequirement(Module * M,StringRef Feature,bool & IsRequiresExcludedHack)21997330f729Sjoerg static bool shouldAddRequirement(Module *M, StringRef Feature,
22007330f729Sjoerg                                  bool &IsRequiresExcludedHack) {
22017330f729Sjoerg   if (Feature == "excluded" &&
22027330f729Sjoerg       (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
22037330f729Sjoerg        M->fullModuleNameIs({"Tcl", "Private"}))) {
22047330f729Sjoerg     IsRequiresExcludedHack = true;
22057330f729Sjoerg     return false;
22067330f729Sjoerg   } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
22077330f729Sjoerg     return false;
22087330f729Sjoerg   }
22097330f729Sjoerg 
22107330f729Sjoerg   return true;
22117330f729Sjoerg }
22127330f729Sjoerg 
22137330f729Sjoerg /// Parse a requires declaration.
22147330f729Sjoerg ///
22157330f729Sjoerg ///   requires-declaration:
22167330f729Sjoerg ///     'requires' feature-list
22177330f729Sjoerg ///
22187330f729Sjoerg ///   feature-list:
22197330f729Sjoerg ///     feature ',' feature-list
22207330f729Sjoerg ///     feature
22217330f729Sjoerg ///
22227330f729Sjoerg ///   feature:
22237330f729Sjoerg ///     '!'[opt] identifier
parseRequiresDecl()22247330f729Sjoerg void ModuleMapParser::parseRequiresDecl() {
22257330f729Sjoerg   assert(Tok.is(MMToken::RequiresKeyword));
22267330f729Sjoerg 
22277330f729Sjoerg   // Parse 'requires' keyword.
22287330f729Sjoerg   consumeToken();
22297330f729Sjoerg 
22307330f729Sjoerg   // Parse the feature-list.
22317330f729Sjoerg   do {
22327330f729Sjoerg     bool RequiredState = true;
22337330f729Sjoerg     if (Tok.is(MMToken::Exclaim)) {
22347330f729Sjoerg       RequiredState = false;
22357330f729Sjoerg       consumeToken();
22367330f729Sjoerg     }
22377330f729Sjoerg 
22387330f729Sjoerg     if (!Tok.is(MMToken::Identifier)) {
22397330f729Sjoerg       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
22407330f729Sjoerg       HadError = true;
22417330f729Sjoerg       return;
22427330f729Sjoerg     }
22437330f729Sjoerg 
22447330f729Sjoerg     // Consume the feature name.
2245*e038c9c4Sjoerg     std::string Feature = std::string(Tok.getString());
22467330f729Sjoerg     consumeToken();
22477330f729Sjoerg 
22487330f729Sjoerg     bool IsRequiresExcludedHack = false;
22497330f729Sjoerg     bool ShouldAddRequirement =
22507330f729Sjoerg         shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
22517330f729Sjoerg 
22527330f729Sjoerg     if (IsRequiresExcludedHack)
22537330f729Sjoerg       UsesRequiresExcludedHack.insert(ActiveModule);
22547330f729Sjoerg 
22557330f729Sjoerg     if (ShouldAddRequirement) {
22567330f729Sjoerg       // Add this feature.
22577330f729Sjoerg       ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
22587330f729Sjoerg                                    *Map.Target);
22597330f729Sjoerg     }
22607330f729Sjoerg 
22617330f729Sjoerg     if (!Tok.is(MMToken::Comma))
22627330f729Sjoerg       break;
22637330f729Sjoerg 
22647330f729Sjoerg     // Consume the comma.
22657330f729Sjoerg     consumeToken();
22667330f729Sjoerg   } while (true);
22677330f729Sjoerg }
22687330f729Sjoerg 
22697330f729Sjoerg /// Parse a header declaration.
22707330f729Sjoerg ///
22717330f729Sjoerg ///   header-declaration:
22727330f729Sjoerg ///     'textual'[opt] 'header' string-literal
22737330f729Sjoerg ///     'private' 'textual'[opt] 'header' string-literal
22747330f729Sjoerg ///     'exclude' 'header' string-literal
22757330f729Sjoerg ///     'umbrella' 'header' string-literal
22767330f729Sjoerg ///
22777330f729Sjoerg /// FIXME: Support 'private textual header'.
parseHeaderDecl(MMToken::TokenKind LeadingToken,SourceLocation LeadingLoc)22787330f729Sjoerg void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
22797330f729Sjoerg                                       SourceLocation LeadingLoc) {
22807330f729Sjoerg   // We've already consumed the first token.
22817330f729Sjoerg   ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
22827330f729Sjoerg   if (LeadingToken == MMToken::PrivateKeyword) {
22837330f729Sjoerg     Role = ModuleMap::PrivateHeader;
22847330f729Sjoerg     // 'private' may optionally be followed by 'textual'.
22857330f729Sjoerg     if (Tok.is(MMToken::TextualKeyword)) {
22867330f729Sjoerg       LeadingToken = Tok.Kind;
22877330f729Sjoerg       consumeToken();
22887330f729Sjoerg     }
22897330f729Sjoerg   }
22907330f729Sjoerg 
22917330f729Sjoerg   if (LeadingToken == MMToken::TextualKeyword)
22927330f729Sjoerg     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
22937330f729Sjoerg 
22947330f729Sjoerg   if (UsesRequiresExcludedHack.count(ActiveModule)) {
22957330f729Sjoerg     // Mark this header 'textual' (see doc comment for
22967330f729Sjoerg     // Module::UsesRequiresExcludedHack).
22977330f729Sjoerg     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
22987330f729Sjoerg   }
22997330f729Sjoerg 
23007330f729Sjoerg   if (LeadingToken != MMToken::HeaderKeyword) {
23017330f729Sjoerg     if (!Tok.is(MMToken::HeaderKeyword)) {
23027330f729Sjoerg       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
23037330f729Sjoerg           << (LeadingToken == MMToken::PrivateKeyword ? "private" :
23047330f729Sjoerg               LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
23057330f729Sjoerg               LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
23067330f729Sjoerg       return;
23077330f729Sjoerg     }
23087330f729Sjoerg     consumeToken();
23097330f729Sjoerg   }
23107330f729Sjoerg 
23117330f729Sjoerg   // Parse the header name.
23127330f729Sjoerg   if (!Tok.is(MMToken::StringLiteral)) {
23137330f729Sjoerg     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
23147330f729Sjoerg       << "header";
23157330f729Sjoerg     HadError = true;
23167330f729Sjoerg     return;
23177330f729Sjoerg   }
23187330f729Sjoerg   Module::UnresolvedHeaderDirective Header;
2319*e038c9c4Sjoerg   Header.FileName = std::string(Tok.getString());
23207330f729Sjoerg   Header.FileNameLoc = consumeToken();
23217330f729Sjoerg   Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
23227330f729Sjoerg   Header.Kind =
23237330f729Sjoerg       (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded
23247330f729Sjoerg                                                : Map.headerRoleToKind(Role));
23257330f729Sjoerg 
23267330f729Sjoerg   // Check whether we already have an umbrella.
23277330f729Sjoerg   if (Header.IsUmbrella && ActiveModule->Umbrella) {
23287330f729Sjoerg     Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
23297330f729Sjoerg       << ActiveModule->getFullModuleName();
23307330f729Sjoerg     HadError = true;
23317330f729Sjoerg     return;
23327330f729Sjoerg   }
23337330f729Sjoerg 
23347330f729Sjoerg   // If we were given stat information, parse it so we can skip looking for
23357330f729Sjoerg   // the file.
23367330f729Sjoerg   if (Tok.is(MMToken::LBrace)) {
23377330f729Sjoerg     SourceLocation LBraceLoc = consumeToken();
23387330f729Sjoerg 
23397330f729Sjoerg     while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
23407330f729Sjoerg       enum Attribute { Size, ModTime, Unknown };
23417330f729Sjoerg       StringRef Str = Tok.getString();
23427330f729Sjoerg       SourceLocation Loc = consumeToken();
23437330f729Sjoerg       switch (llvm::StringSwitch<Attribute>(Str)
23447330f729Sjoerg                   .Case("size", Size)
23457330f729Sjoerg                   .Case("mtime", ModTime)
23467330f729Sjoerg                   .Default(Unknown)) {
23477330f729Sjoerg       case Size:
23487330f729Sjoerg         if (Header.Size)
23497330f729Sjoerg           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
23507330f729Sjoerg         if (!Tok.is(MMToken::IntegerLiteral)) {
23517330f729Sjoerg           Diags.Report(Tok.getLocation(),
23527330f729Sjoerg                        diag::err_mmap_invalid_header_attribute_value) << Str;
23537330f729Sjoerg           skipUntil(MMToken::RBrace);
23547330f729Sjoerg           break;
23557330f729Sjoerg         }
23567330f729Sjoerg         Header.Size = Tok.getInteger();
23577330f729Sjoerg         consumeToken();
23587330f729Sjoerg         break;
23597330f729Sjoerg 
23607330f729Sjoerg       case ModTime:
23617330f729Sjoerg         if (Header.ModTime)
23627330f729Sjoerg           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
23637330f729Sjoerg         if (!Tok.is(MMToken::IntegerLiteral)) {
23647330f729Sjoerg           Diags.Report(Tok.getLocation(),
23657330f729Sjoerg                        diag::err_mmap_invalid_header_attribute_value) << Str;
23667330f729Sjoerg           skipUntil(MMToken::RBrace);
23677330f729Sjoerg           break;
23687330f729Sjoerg         }
23697330f729Sjoerg         Header.ModTime = Tok.getInteger();
23707330f729Sjoerg         consumeToken();
23717330f729Sjoerg         break;
23727330f729Sjoerg 
23737330f729Sjoerg       case Unknown:
23747330f729Sjoerg         Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
23757330f729Sjoerg         skipUntil(MMToken::RBrace);
23767330f729Sjoerg         break;
23777330f729Sjoerg       }
23787330f729Sjoerg     }
23797330f729Sjoerg 
23807330f729Sjoerg     if (Tok.is(MMToken::RBrace))
23817330f729Sjoerg       consumeToken();
23827330f729Sjoerg     else {
23837330f729Sjoerg       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
23847330f729Sjoerg       Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
23857330f729Sjoerg       HadError = true;
23867330f729Sjoerg     }
23877330f729Sjoerg   }
23887330f729Sjoerg 
23897330f729Sjoerg   bool NeedsFramework = false;
23907330f729Sjoerg   Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
23917330f729Sjoerg 
23927330f729Sjoerg   if (NeedsFramework && ActiveModule)
23937330f729Sjoerg     Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
23947330f729Sjoerg       << ActiveModule->getFullModuleName()
23957330f729Sjoerg       << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
23967330f729Sjoerg }
23977330f729Sjoerg 
compareModuleHeaders(const Module::Header * A,const Module::Header * B)23987330f729Sjoerg static int compareModuleHeaders(const Module::Header *A,
23997330f729Sjoerg                                 const Module::Header *B) {
24007330f729Sjoerg   return A->NameAsWritten.compare(B->NameAsWritten);
24017330f729Sjoerg }
24027330f729Sjoerg 
24037330f729Sjoerg /// Parse an umbrella directory declaration.
24047330f729Sjoerg ///
24057330f729Sjoerg ///   umbrella-dir-declaration:
24067330f729Sjoerg ///     umbrella string-literal
parseUmbrellaDirDecl(SourceLocation UmbrellaLoc)24077330f729Sjoerg void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
24087330f729Sjoerg   // Parse the directory name.
24097330f729Sjoerg   if (!Tok.is(MMToken::StringLiteral)) {
24107330f729Sjoerg     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
24117330f729Sjoerg       << "umbrella";
24127330f729Sjoerg     HadError = true;
24137330f729Sjoerg     return;
24147330f729Sjoerg   }
24157330f729Sjoerg 
2416*e038c9c4Sjoerg   std::string DirName = std::string(Tok.getString());
2417*e038c9c4Sjoerg   std::string DirNameAsWritten = DirName;
24187330f729Sjoerg   SourceLocation DirNameLoc = consumeToken();
24197330f729Sjoerg 
24207330f729Sjoerg   // Check whether we already have an umbrella.
24217330f729Sjoerg   if (ActiveModule->Umbrella) {
24227330f729Sjoerg     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
24237330f729Sjoerg       << ActiveModule->getFullModuleName();
24247330f729Sjoerg     HadError = true;
24257330f729Sjoerg     return;
24267330f729Sjoerg   }
24277330f729Sjoerg 
24287330f729Sjoerg   // Look for this file.
24297330f729Sjoerg   const DirectoryEntry *Dir = nullptr;
24307330f729Sjoerg   if (llvm::sys::path::is_absolute(DirName)) {
24317330f729Sjoerg     if (auto D = SourceMgr.getFileManager().getDirectory(DirName))
24327330f729Sjoerg       Dir = *D;
24337330f729Sjoerg   } else {
24347330f729Sjoerg     SmallString<128> PathName;
24357330f729Sjoerg     PathName = Directory->getName();
24367330f729Sjoerg     llvm::sys::path::append(PathName, DirName);
24377330f729Sjoerg     if (auto D = SourceMgr.getFileManager().getDirectory(PathName))
24387330f729Sjoerg       Dir = *D;
24397330f729Sjoerg   }
24407330f729Sjoerg 
24417330f729Sjoerg   if (!Dir) {
24427330f729Sjoerg     Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
24437330f729Sjoerg       << DirName;
24447330f729Sjoerg     return;
24457330f729Sjoerg   }
24467330f729Sjoerg 
24477330f729Sjoerg   if (UsesRequiresExcludedHack.count(ActiveModule)) {
24487330f729Sjoerg     // Mark this header 'textual' (see doc comment for
24497330f729Sjoerg     // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
24507330f729Sjoerg     // directory is relatively expensive, in practice this only applies to the
24517330f729Sjoerg     // uncommonly used Tcl module on Darwin platforms.
24527330f729Sjoerg     std::error_code EC;
24537330f729Sjoerg     SmallVector<Module::Header, 6> Headers;
24547330f729Sjoerg     llvm::vfs::FileSystem &FS =
24557330f729Sjoerg         SourceMgr.getFileManager().getVirtualFileSystem();
24567330f729Sjoerg     for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
24577330f729Sjoerg          I != E && !EC; I.increment(EC)) {
24587330f729Sjoerg       if (auto FE = SourceMgr.getFileManager().getFile(I->path())) {
2459*e038c9c4Sjoerg         Module::Header Header = {"", std::string(I->path()), *FE};
24607330f729Sjoerg         Headers.push_back(std::move(Header));
24617330f729Sjoerg       }
24627330f729Sjoerg     }
24637330f729Sjoerg 
24647330f729Sjoerg     // Sort header paths so that the pcm doesn't depend on iteration order.
24657330f729Sjoerg     llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
24667330f729Sjoerg 
24677330f729Sjoerg     for (auto &Header : Headers)
24687330f729Sjoerg       Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
24697330f729Sjoerg     return;
24707330f729Sjoerg   }
24717330f729Sjoerg 
24727330f729Sjoerg   if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
24737330f729Sjoerg     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
24747330f729Sjoerg       << OwningModule->getFullModuleName();
24757330f729Sjoerg     HadError = true;
24767330f729Sjoerg     return;
24777330f729Sjoerg   }
24787330f729Sjoerg 
24797330f729Sjoerg   // Record this umbrella directory.
2480*e038c9c4Sjoerg   Map.setUmbrellaDir(ActiveModule, Dir, DirNameAsWritten, DirName);
24817330f729Sjoerg }
24827330f729Sjoerg 
24837330f729Sjoerg /// Parse a module export declaration.
24847330f729Sjoerg ///
24857330f729Sjoerg ///   export-declaration:
24867330f729Sjoerg ///     'export' wildcard-module-id
24877330f729Sjoerg ///
24887330f729Sjoerg ///   wildcard-module-id:
24897330f729Sjoerg ///     identifier
24907330f729Sjoerg ///     '*'
24917330f729Sjoerg ///     identifier '.' wildcard-module-id
parseExportDecl()24927330f729Sjoerg void ModuleMapParser::parseExportDecl() {
24937330f729Sjoerg   assert(Tok.is(MMToken::ExportKeyword));
24947330f729Sjoerg   SourceLocation ExportLoc = consumeToken();
24957330f729Sjoerg 
24967330f729Sjoerg   // Parse the module-id with an optional wildcard at the end.
24977330f729Sjoerg   ModuleId ParsedModuleId;
24987330f729Sjoerg   bool Wildcard = false;
24997330f729Sjoerg   do {
25007330f729Sjoerg     // FIXME: Support string-literal module names here.
25017330f729Sjoerg     if (Tok.is(MMToken::Identifier)) {
2502*e038c9c4Sjoerg       ParsedModuleId.push_back(
2503*e038c9c4Sjoerg           std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
25047330f729Sjoerg       consumeToken();
25057330f729Sjoerg 
25067330f729Sjoerg       if (Tok.is(MMToken::Period)) {
25077330f729Sjoerg         consumeToken();
25087330f729Sjoerg         continue;
25097330f729Sjoerg       }
25107330f729Sjoerg 
25117330f729Sjoerg       break;
25127330f729Sjoerg     }
25137330f729Sjoerg 
25147330f729Sjoerg     if(Tok.is(MMToken::Star)) {
25157330f729Sjoerg       Wildcard = true;
25167330f729Sjoerg       consumeToken();
25177330f729Sjoerg       break;
25187330f729Sjoerg     }
25197330f729Sjoerg 
25207330f729Sjoerg     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
25217330f729Sjoerg     HadError = true;
25227330f729Sjoerg     return;
25237330f729Sjoerg   } while (true);
25247330f729Sjoerg 
25257330f729Sjoerg   Module::UnresolvedExportDecl Unresolved = {
25267330f729Sjoerg     ExportLoc, ParsedModuleId, Wildcard
25277330f729Sjoerg   };
25287330f729Sjoerg   ActiveModule->UnresolvedExports.push_back(Unresolved);
25297330f729Sjoerg }
25307330f729Sjoerg 
25317330f729Sjoerg /// Parse a module export_as declaration.
25327330f729Sjoerg ///
25337330f729Sjoerg ///   export-as-declaration:
25347330f729Sjoerg ///     'export_as' identifier
parseExportAsDecl()25357330f729Sjoerg void ModuleMapParser::parseExportAsDecl() {
25367330f729Sjoerg   assert(Tok.is(MMToken::ExportAsKeyword));
25377330f729Sjoerg   consumeToken();
25387330f729Sjoerg 
25397330f729Sjoerg   if (!Tok.is(MMToken::Identifier)) {
25407330f729Sjoerg     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
25417330f729Sjoerg     HadError = true;
25427330f729Sjoerg     return;
25437330f729Sjoerg   }
25447330f729Sjoerg 
25457330f729Sjoerg   if (ActiveModule->Parent) {
25467330f729Sjoerg     Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
25477330f729Sjoerg     consumeToken();
25487330f729Sjoerg     return;
25497330f729Sjoerg   }
25507330f729Sjoerg 
25517330f729Sjoerg   if (!ActiveModule->ExportAsModule.empty()) {
25527330f729Sjoerg     if (ActiveModule->ExportAsModule == Tok.getString()) {
25537330f729Sjoerg       Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
25547330f729Sjoerg         << ActiveModule->Name << Tok.getString();
25557330f729Sjoerg     } else {
25567330f729Sjoerg       Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
25577330f729Sjoerg         << ActiveModule->Name << ActiveModule->ExportAsModule
25587330f729Sjoerg         << Tok.getString();
25597330f729Sjoerg     }
25607330f729Sjoerg   }
25617330f729Sjoerg 
2562*e038c9c4Sjoerg   ActiveModule->ExportAsModule = std::string(Tok.getString());
25637330f729Sjoerg   Map.addLinkAsDependency(ActiveModule);
25647330f729Sjoerg 
25657330f729Sjoerg   consumeToken();
25667330f729Sjoerg }
25677330f729Sjoerg 
25687330f729Sjoerg /// Parse a module use declaration.
25697330f729Sjoerg ///
25707330f729Sjoerg ///   use-declaration:
25717330f729Sjoerg ///     'use' wildcard-module-id
parseUseDecl()25727330f729Sjoerg void ModuleMapParser::parseUseDecl() {
25737330f729Sjoerg   assert(Tok.is(MMToken::UseKeyword));
25747330f729Sjoerg   auto KWLoc = consumeToken();
25757330f729Sjoerg   // Parse the module-id.
25767330f729Sjoerg   ModuleId ParsedModuleId;
25777330f729Sjoerg   parseModuleId(ParsedModuleId);
25787330f729Sjoerg 
25797330f729Sjoerg   if (ActiveModule->Parent)
25807330f729Sjoerg     Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
25817330f729Sjoerg   else
25827330f729Sjoerg     ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
25837330f729Sjoerg }
25847330f729Sjoerg 
25857330f729Sjoerg /// Parse a link declaration.
25867330f729Sjoerg ///
25877330f729Sjoerg ///   module-declaration:
25887330f729Sjoerg ///     'link' 'framework'[opt] string-literal
parseLinkDecl()25897330f729Sjoerg void ModuleMapParser::parseLinkDecl() {
25907330f729Sjoerg   assert(Tok.is(MMToken::LinkKeyword));
25917330f729Sjoerg   SourceLocation LinkLoc = consumeToken();
25927330f729Sjoerg 
25937330f729Sjoerg   // Parse the optional 'framework' keyword.
25947330f729Sjoerg   bool IsFramework = false;
25957330f729Sjoerg   if (Tok.is(MMToken::FrameworkKeyword)) {
25967330f729Sjoerg     consumeToken();
25977330f729Sjoerg     IsFramework = true;
25987330f729Sjoerg   }
25997330f729Sjoerg 
26007330f729Sjoerg   // Parse the library name
26017330f729Sjoerg   if (!Tok.is(MMToken::StringLiteral)) {
26027330f729Sjoerg     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
26037330f729Sjoerg       << IsFramework << SourceRange(LinkLoc);
26047330f729Sjoerg     HadError = true;
26057330f729Sjoerg     return;
26067330f729Sjoerg   }
26077330f729Sjoerg 
2608*e038c9c4Sjoerg   std::string LibraryName = std::string(Tok.getString());
26097330f729Sjoerg   consumeToken();
26107330f729Sjoerg   ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
26117330f729Sjoerg                                                             IsFramework));
26127330f729Sjoerg }
26137330f729Sjoerg 
26147330f729Sjoerg /// Parse a configuration macro declaration.
26157330f729Sjoerg ///
26167330f729Sjoerg ///   module-declaration:
26177330f729Sjoerg ///     'config_macros' attributes[opt] config-macro-list?
26187330f729Sjoerg ///
26197330f729Sjoerg ///   config-macro-list:
26207330f729Sjoerg ///     identifier (',' identifier)?
parseConfigMacros()26217330f729Sjoerg void ModuleMapParser::parseConfigMacros() {
26227330f729Sjoerg   assert(Tok.is(MMToken::ConfigMacros));
26237330f729Sjoerg   SourceLocation ConfigMacrosLoc = consumeToken();
26247330f729Sjoerg 
26257330f729Sjoerg   // Only top-level modules can have configuration macros.
26267330f729Sjoerg   if (ActiveModule->Parent) {
26277330f729Sjoerg     Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
26287330f729Sjoerg   }
26297330f729Sjoerg 
26307330f729Sjoerg   // Parse the optional attributes.
26317330f729Sjoerg   Attributes Attrs;
26327330f729Sjoerg   if (parseOptionalAttributes(Attrs))
26337330f729Sjoerg     return;
26347330f729Sjoerg 
26357330f729Sjoerg   if (Attrs.IsExhaustive && !ActiveModule->Parent) {
26367330f729Sjoerg     ActiveModule->ConfigMacrosExhaustive = true;
26377330f729Sjoerg   }
26387330f729Sjoerg 
26397330f729Sjoerg   // If we don't have an identifier, we're done.
26407330f729Sjoerg   // FIXME: Support macros with the same name as a keyword here.
26417330f729Sjoerg   if (!Tok.is(MMToken::Identifier))
26427330f729Sjoerg     return;
26437330f729Sjoerg 
26447330f729Sjoerg   // Consume the first identifier.
26457330f729Sjoerg   if (!ActiveModule->Parent) {
26467330f729Sjoerg     ActiveModule->ConfigMacros.push_back(Tok.getString().str());
26477330f729Sjoerg   }
26487330f729Sjoerg   consumeToken();
26497330f729Sjoerg 
26507330f729Sjoerg   do {
26517330f729Sjoerg     // If there's a comma, consume it.
26527330f729Sjoerg     if (!Tok.is(MMToken::Comma))
26537330f729Sjoerg       break;
26547330f729Sjoerg     consumeToken();
26557330f729Sjoerg 
26567330f729Sjoerg     // We expect to see a macro name here.
26577330f729Sjoerg     // FIXME: Support macros with the same name as a keyword here.
26587330f729Sjoerg     if (!Tok.is(MMToken::Identifier)) {
26597330f729Sjoerg       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
26607330f729Sjoerg       break;
26617330f729Sjoerg     }
26627330f729Sjoerg 
26637330f729Sjoerg     // Consume the macro name.
26647330f729Sjoerg     if (!ActiveModule->Parent) {
26657330f729Sjoerg       ActiveModule->ConfigMacros.push_back(Tok.getString().str());
26667330f729Sjoerg     }
26677330f729Sjoerg     consumeToken();
26687330f729Sjoerg   } while (true);
26697330f729Sjoerg }
26707330f729Sjoerg 
26717330f729Sjoerg /// Format a module-id into a string.
formatModuleId(const ModuleId & Id)26727330f729Sjoerg static std::string formatModuleId(const ModuleId &Id) {
26737330f729Sjoerg   std::string result;
26747330f729Sjoerg   {
26757330f729Sjoerg     llvm::raw_string_ostream OS(result);
26767330f729Sjoerg 
26777330f729Sjoerg     for (unsigned I = 0, N = Id.size(); I != N; ++I) {
26787330f729Sjoerg       if (I)
26797330f729Sjoerg         OS << ".";
26807330f729Sjoerg       OS << Id[I].first;
26817330f729Sjoerg     }
26827330f729Sjoerg   }
26837330f729Sjoerg 
26847330f729Sjoerg   return result;
26857330f729Sjoerg }
26867330f729Sjoerg 
26877330f729Sjoerg /// Parse a conflict declaration.
26887330f729Sjoerg ///
26897330f729Sjoerg ///   module-declaration:
26907330f729Sjoerg ///     'conflict' module-id ',' string-literal
parseConflict()26917330f729Sjoerg void ModuleMapParser::parseConflict() {
26927330f729Sjoerg   assert(Tok.is(MMToken::Conflict));
26937330f729Sjoerg   SourceLocation ConflictLoc = consumeToken();
26947330f729Sjoerg   Module::UnresolvedConflict Conflict;
26957330f729Sjoerg 
26967330f729Sjoerg   // Parse the module-id.
26977330f729Sjoerg   if (parseModuleId(Conflict.Id))
26987330f729Sjoerg     return;
26997330f729Sjoerg 
27007330f729Sjoerg   // Parse the ','.
27017330f729Sjoerg   if (!Tok.is(MMToken::Comma)) {
27027330f729Sjoerg     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
27037330f729Sjoerg       << SourceRange(ConflictLoc);
27047330f729Sjoerg     return;
27057330f729Sjoerg   }
27067330f729Sjoerg   consumeToken();
27077330f729Sjoerg 
27087330f729Sjoerg   // Parse the message.
27097330f729Sjoerg   if (!Tok.is(MMToken::StringLiteral)) {
27107330f729Sjoerg     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
27117330f729Sjoerg       << formatModuleId(Conflict.Id);
27127330f729Sjoerg     return;
27137330f729Sjoerg   }
27147330f729Sjoerg   Conflict.Message = Tok.getString().str();
27157330f729Sjoerg   consumeToken();
27167330f729Sjoerg 
27177330f729Sjoerg   // Add this unresolved conflict.
27187330f729Sjoerg   ActiveModule->UnresolvedConflicts.push_back(Conflict);
27197330f729Sjoerg }
27207330f729Sjoerg 
27217330f729Sjoerg /// Parse an inferred module declaration (wildcard modules).
27227330f729Sjoerg ///
27237330f729Sjoerg ///   module-declaration:
27247330f729Sjoerg ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
27257330f729Sjoerg ///       { inferred-module-member* }
27267330f729Sjoerg ///
27277330f729Sjoerg ///   inferred-module-member:
27287330f729Sjoerg ///     'export' '*'
27297330f729Sjoerg ///     'exclude' identifier
parseInferredModuleDecl(bool Framework,bool Explicit)27307330f729Sjoerg void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
27317330f729Sjoerg   assert(Tok.is(MMToken::Star));
27327330f729Sjoerg   SourceLocation StarLoc = consumeToken();
27337330f729Sjoerg   bool Failed = false;
27347330f729Sjoerg 
27357330f729Sjoerg   // Inferred modules must be submodules.
27367330f729Sjoerg   if (!ActiveModule && !Framework) {
27377330f729Sjoerg     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
27387330f729Sjoerg     Failed = true;
27397330f729Sjoerg   }
27407330f729Sjoerg 
27417330f729Sjoerg   if (ActiveModule) {
27427330f729Sjoerg     // Inferred modules must have umbrella directories.
27437330f729Sjoerg     if (!Failed && ActiveModule->IsAvailable &&
27447330f729Sjoerg         !ActiveModule->getUmbrellaDir()) {
27457330f729Sjoerg       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
27467330f729Sjoerg       Failed = true;
27477330f729Sjoerg     }
27487330f729Sjoerg 
27497330f729Sjoerg     // Check for redefinition of an inferred module.
27507330f729Sjoerg     if (!Failed && ActiveModule->InferSubmodules) {
27517330f729Sjoerg       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
27527330f729Sjoerg       if (ActiveModule->InferredSubmoduleLoc.isValid())
27537330f729Sjoerg         Diags.Report(ActiveModule->InferredSubmoduleLoc,
27547330f729Sjoerg                      diag::note_mmap_prev_definition);
27557330f729Sjoerg       Failed = true;
27567330f729Sjoerg     }
27577330f729Sjoerg 
27587330f729Sjoerg     // Check for the 'framework' keyword, which is not permitted here.
27597330f729Sjoerg     if (Framework) {
27607330f729Sjoerg       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
27617330f729Sjoerg       Framework = false;
27627330f729Sjoerg     }
27637330f729Sjoerg   } else if (Explicit) {
27647330f729Sjoerg     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
27657330f729Sjoerg     Explicit = false;
27667330f729Sjoerg   }
27677330f729Sjoerg 
27687330f729Sjoerg   // If there were any problems with this inferred submodule, skip its body.
27697330f729Sjoerg   if (Failed) {
27707330f729Sjoerg     if (Tok.is(MMToken::LBrace)) {
27717330f729Sjoerg       consumeToken();
27727330f729Sjoerg       skipUntil(MMToken::RBrace);
27737330f729Sjoerg       if (Tok.is(MMToken::RBrace))
27747330f729Sjoerg         consumeToken();
27757330f729Sjoerg     }
27767330f729Sjoerg     HadError = true;
27777330f729Sjoerg     return;
27787330f729Sjoerg   }
27797330f729Sjoerg 
27807330f729Sjoerg   // Parse optional attributes.
27817330f729Sjoerg   Attributes Attrs;
27827330f729Sjoerg   if (parseOptionalAttributes(Attrs))
27837330f729Sjoerg     return;
27847330f729Sjoerg 
27857330f729Sjoerg   if (ActiveModule) {
27867330f729Sjoerg     // Note that we have an inferred submodule.
27877330f729Sjoerg     ActiveModule->InferSubmodules = true;
27887330f729Sjoerg     ActiveModule->InferredSubmoduleLoc = StarLoc;
27897330f729Sjoerg     ActiveModule->InferExplicitSubmodules = Explicit;
27907330f729Sjoerg   } else {
27917330f729Sjoerg     // We'll be inferring framework modules for this directory.
27927330f729Sjoerg     Map.InferredDirectories[Directory].InferModules = true;
27937330f729Sjoerg     Map.InferredDirectories[Directory].Attrs = Attrs;
27947330f729Sjoerg     Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
27957330f729Sjoerg     // FIXME: Handle the 'framework' keyword.
27967330f729Sjoerg   }
27977330f729Sjoerg 
27987330f729Sjoerg   // Parse the opening brace.
27997330f729Sjoerg   if (!Tok.is(MMToken::LBrace)) {
28007330f729Sjoerg     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
28017330f729Sjoerg     HadError = true;
28027330f729Sjoerg     return;
28037330f729Sjoerg   }
28047330f729Sjoerg   SourceLocation LBraceLoc = consumeToken();
28057330f729Sjoerg 
28067330f729Sjoerg   // Parse the body of the inferred submodule.
28077330f729Sjoerg   bool Done = false;
28087330f729Sjoerg   do {
28097330f729Sjoerg     switch (Tok.Kind) {
28107330f729Sjoerg     case MMToken::EndOfFile:
28117330f729Sjoerg     case MMToken::RBrace:
28127330f729Sjoerg       Done = true;
28137330f729Sjoerg       break;
28147330f729Sjoerg 
28157330f729Sjoerg     case MMToken::ExcludeKeyword:
28167330f729Sjoerg       if (ActiveModule) {
28177330f729Sjoerg         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
28187330f729Sjoerg           << (ActiveModule != nullptr);
28197330f729Sjoerg         consumeToken();
28207330f729Sjoerg         break;
28217330f729Sjoerg       }
28227330f729Sjoerg 
28237330f729Sjoerg       consumeToken();
28247330f729Sjoerg       // FIXME: Support string-literal module names here.
28257330f729Sjoerg       if (!Tok.is(MMToken::Identifier)) {
28267330f729Sjoerg         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
28277330f729Sjoerg         break;
28287330f729Sjoerg       }
28297330f729Sjoerg 
2830*e038c9c4Sjoerg       Map.InferredDirectories[Directory].ExcludedModules.push_back(
2831*e038c9c4Sjoerg           std::string(Tok.getString()));
28327330f729Sjoerg       consumeToken();
28337330f729Sjoerg       break;
28347330f729Sjoerg 
28357330f729Sjoerg     case MMToken::ExportKeyword:
28367330f729Sjoerg       if (!ActiveModule) {
28377330f729Sjoerg         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
28387330f729Sjoerg           << (ActiveModule != nullptr);
28397330f729Sjoerg         consumeToken();
28407330f729Sjoerg         break;
28417330f729Sjoerg       }
28427330f729Sjoerg 
28437330f729Sjoerg       consumeToken();
28447330f729Sjoerg       if (Tok.is(MMToken::Star))
28457330f729Sjoerg         ActiveModule->InferExportWildcard = true;
28467330f729Sjoerg       else
28477330f729Sjoerg         Diags.Report(Tok.getLocation(),
28487330f729Sjoerg                      diag::err_mmap_expected_export_wildcard);
28497330f729Sjoerg       consumeToken();
28507330f729Sjoerg       break;
28517330f729Sjoerg 
28527330f729Sjoerg     case MMToken::ExplicitKeyword:
28537330f729Sjoerg     case MMToken::ModuleKeyword:
28547330f729Sjoerg     case MMToken::HeaderKeyword:
28557330f729Sjoerg     case MMToken::PrivateKeyword:
28567330f729Sjoerg     case MMToken::UmbrellaKeyword:
28577330f729Sjoerg     default:
28587330f729Sjoerg       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
28597330f729Sjoerg           << (ActiveModule != nullptr);
28607330f729Sjoerg       consumeToken();
28617330f729Sjoerg       break;
28627330f729Sjoerg     }
28637330f729Sjoerg   } while (!Done);
28647330f729Sjoerg 
28657330f729Sjoerg   if (Tok.is(MMToken::RBrace))
28667330f729Sjoerg     consumeToken();
28677330f729Sjoerg   else {
28687330f729Sjoerg     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
28697330f729Sjoerg     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
28707330f729Sjoerg     HadError = true;
28717330f729Sjoerg   }
28727330f729Sjoerg }
28737330f729Sjoerg 
28747330f729Sjoerg /// Parse optional attributes.
28757330f729Sjoerg ///
28767330f729Sjoerg ///   attributes:
28777330f729Sjoerg ///     attribute attributes
28787330f729Sjoerg ///     attribute
28797330f729Sjoerg ///
28807330f729Sjoerg ///   attribute:
28817330f729Sjoerg ///     [ identifier ]
28827330f729Sjoerg ///
28837330f729Sjoerg /// \param Attrs Will be filled in with the parsed attributes.
28847330f729Sjoerg ///
28857330f729Sjoerg /// \returns true if an error occurred, false otherwise.
parseOptionalAttributes(Attributes & Attrs)28867330f729Sjoerg bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
28877330f729Sjoerg   bool HadError = false;
28887330f729Sjoerg 
28897330f729Sjoerg   while (Tok.is(MMToken::LSquare)) {
28907330f729Sjoerg     // Consume the '['.
28917330f729Sjoerg     SourceLocation LSquareLoc = consumeToken();
28927330f729Sjoerg 
28937330f729Sjoerg     // Check whether we have an attribute name here.
28947330f729Sjoerg     if (!Tok.is(MMToken::Identifier)) {
28957330f729Sjoerg       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
28967330f729Sjoerg       skipUntil(MMToken::RSquare);
28977330f729Sjoerg       if (Tok.is(MMToken::RSquare))
28987330f729Sjoerg         consumeToken();
28997330f729Sjoerg       HadError = true;
29007330f729Sjoerg     }
29017330f729Sjoerg 
29027330f729Sjoerg     // Decode the attribute name.
29037330f729Sjoerg     AttributeKind Attribute
29047330f729Sjoerg       = llvm::StringSwitch<AttributeKind>(Tok.getString())
29057330f729Sjoerg           .Case("exhaustive", AT_exhaustive)
29067330f729Sjoerg           .Case("extern_c", AT_extern_c)
29077330f729Sjoerg           .Case("no_undeclared_includes", AT_no_undeclared_includes)
29087330f729Sjoerg           .Case("system", AT_system)
29097330f729Sjoerg           .Default(AT_unknown);
29107330f729Sjoerg     switch (Attribute) {
29117330f729Sjoerg     case AT_unknown:
29127330f729Sjoerg       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
29137330f729Sjoerg         << Tok.getString();
29147330f729Sjoerg       break;
29157330f729Sjoerg 
29167330f729Sjoerg     case AT_system:
29177330f729Sjoerg       Attrs.IsSystem = true;
29187330f729Sjoerg       break;
29197330f729Sjoerg 
29207330f729Sjoerg     case AT_extern_c:
29217330f729Sjoerg       Attrs.IsExternC = true;
29227330f729Sjoerg       break;
29237330f729Sjoerg 
29247330f729Sjoerg     case AT_exhaustive:
29257330f729Sjoerg       Attrs.IsExhaustive = true;
29267330f729Sjoerg       break;
29277330f729Sjoerg 
29287330f729Sjoerg     case AT_no_undeclared_includes:
29297330f729Sjoerg       Attrs.NoUndeclaredIncludes = true;
29307330f729Sjoerg       break;
29317330f729Sjoerg     }
29327330f729Sjoerg     consumeToken();
29337330f729Sjoerg 
29347330f729Sjoerg     // Consume the ']'.
29357330f729Sjoerg     if (!Tok.is(MMToken::RSquare)) {
29367330f729Sjoerg       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
29377330f729Sjoerg       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
29387330f729Sjoerg       skipUntil(MMToken::RSquare);
29397330f729Sjoerg       HadError = true;
29407330f729Sjoerg     }
29417330f729Sjoerg 
29427330f729Sjoerg     if (Tok.is(MMToken::RSquare))
29437330f729Sjoerg       consumeToken();
29447330f729Sjoerg   }
29457330f729Sjoerg 
29467330f729Sjoerg   return HadError;
29477330f729Sjoerg }
29487330f729Sjoerg 
29497330f729Sjoerg /// Parse a module map file.
29507330f729Sjoerg ///
29517330f729Sjoerg ///   module-map-file:
29527330f729Sjoerg ///     module-declaration*
parseModuleMapFile()29537330f729Sjoerg bool ModuleMapParser::parseModuleMapFile() {
29547330f729Sjoerg   do {
29557330f729Sjoerg     switch (Tok.Kind) {
29567330f729Sjoerg     case MMToken::EndOfFile:
29577330f729Sjoerg       return HadError;
29587330f729Sjoerg 
29597330f729Sjoerg     case MMToken::ExplicitKeyword:
29607330f729Sjoerg     case MMToken::ExternKeyword:
29617330f729Sjoerg     case MMToken::ModuleKeyword:
29627330f729Sjoerg     case MMToken::FrameworkKeyword:
29637330f729Sjoerg       parseModuleDecl();
29647330f729Sjoerg       break;
29657330f729Sjoerg 
29667330f729Sjoerg     case MMToken::Comma:
29677330f729Sjoerg     case MMToken::ConfigMacros:
29687330f729Sjoerg     case MMToken::Conflict:
29697330f729Sjoerg     case MMToken::Exclaim:
29707330f729Sjoerg     case MMToken::ExcludeKeyword:
29717330f729Sjoerg     case MMToken::ExportKeyword:
29727330f729Sjoerg     case MMToken::ExportAsKeyword:
29737330f729Sjoerg     case MMToken::HeaderKeyword:
29747330f729Sjoerg     case MMToken::Identifier:
29757330f729Sjoerg     case MMToken::LBrace:
29767330f729Sjoerg     case MMToken::LinkKeyword:
29777330f729Sjoerg     case MMToken::LSquare:
29787330f729Sjoerg     case MMToken::Period:
29797330f729Sjoerg     case MMToken::PrivateKeyword:
29807330f729Sjoerg     case MMToken::RBrace:
29817330f729Sjoerg     case MMToken::RSquare:
29827330f729Sjoerg     case MMToken::RequiresKeyword:
29837330f729Sjoerg     case MMToken::Star:
29847330f729Sjoerg     case MMToken::StringLiteral:
29857330f729Sjoerg     case MMToken::IntegerLiteral:
29867330f729Sjoerg     case MMToken::TextualKeyword:
29877330f729Sjoerg     case MMToken::UmbrellaKeyword:
29887330f729Sjoerg     case MMToken::UseKeyword:
29897330f729Sjoerg       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
29907330f729Sjoerg       HadError = true;
29917330f729Sjoerg       consumeToken();
29927330f729Sjoerg       break;
29937330f729Sjoerg     }
29947330f729Sjoerg   } while (true);
29957330f729Sjoerg }
29967330f729Sjoerg 
parseModuleMapFile(const FileEntry * File,bool IsSystem,const DirectoryEntry * Dir,FileID ID,unsigned * Offset,SourceLocation ExternModuleLoc)29977330f729Sjoerg bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
29987330f729Sjoerg                                    const DirectoryEntry *Dir, FileID ID,
29997330f729Sjoerg                                    unsigned *Offset,
30007330f729Sjoerg                                    SourceLocation ExternModuleLoc) {
30017330f729Sjoerg   assert(Target && "Missing target information");
30027330f729Sjoerg   llvm::DenseMap<const FileEntry *, bool>::iterator Known
30037330f729Sjoerg     = ParsedModuleMap.find(File);
30047330f729Sjoerg   if (Known != ParsedModuleMap.end())
30057330f729Sjoerg     return Known->second;
30067330f729Sjoerg 
30077330f729Sjoerg   // If the module map file wasn't already entered, do so now.
30087330f729Sjoerg   if (ID.isInvalid()) {
30097330f729Sjoerg     auto FileCharacter =
30107330f729Sjoerg         IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
30117330f729Sjoerg     ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
30127330f729Sjoerg   }
30137330f729Sjoerg 
30147330f729Sjoerg   assert(Target && "Missing target information");
3015*e038c9c4Sjoerg   llvm::Optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
30167330f729Sjoerg   if (!Buffer)
30177330f729Sjoerg     return ParsedModuleMap[File] = true;
30187330f729Sjoerg   assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
30197330f729Sjoerg          "invalid buffer offset");
30207330f729Sjoerg 
30217330f729Sjoerg   // Parse this module map file.
30227330f729Sjoerg   Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
30237330f729Sjoerg           Buffer->getBufferStart(),
30247330f729Sjoerg           Buffer->getBufferStart() + (Offset ? *Offset : 0),
30257330f729Sjoerg           Buffer->getBufferEnd());
30267330f729Sjoerg   SourceLocation Start = L.getSourceLocation();
30277330f729Sjoerg   ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
30287330f729Sjoerg                          IsSystem);
30297330f729Sjoerg   bool Result = Parser.parseModuleMapFile();
30307330f729Sjoerg   ParsedModuleMap[File] = Result;
30317330f729Sjoerg 
30327330f729Sjoerg   if (Offset) {
30337330f729Sjoerg     auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
30347330f729Sjoerg     assert(Loc.first == ID && "stopped in a different file?");
30357330f729Sjoerg     *Offset = Loc.second;
30367330f729Sjoerg   }
30377330f729Sjoerg 
30387330f729Sjoerg   // Notify callbacks that we parsed it.
30397330f729Sjoerg   for (const auto &Cb : Callbacks)
30407330f729Sjoerg     Cb->moduleMapFileRead(Start, *File, IsSystem);
30417330f729Sjoerg 
30427330f729Sjoerg   return Result;
30437330f729Sjoerg }
3044