19a199699SDimitry Andric //===- ModuleMap.cpp - Describe the layout of modules ---------------------===//
2dff0c46cSDimitry Andric //
3dff0c46cSDimitry Andric //                     The LLVM Compiler Infrastructure
4dff0c46cSDimitry Andric //
5dff0c46cSDimitry Andric // This file is distributed under the University of Illinois Open Source
6dff0c46cSDimitry Andric // License. See LICENSE.TXT for details.
7dff0c46cSDimitry Andric //
8dff0c46cSDimitry Andric //===----------------------------------------------------------------------===//
9dff0c46cSDimitry Andric //
10dff0c46cSDimitry Andric // This file defines the ModuleMap implementation, which describes the layout
11dff0c46cSDimitry Andric // of a module as it relates to headers.
12dff0c46cSDimitry Andric //
13dff0c46cSDimitry Andric //===----------------------------------------------------------------------===//
149a199699SDimitry Andric 
15dff0c46cSDimitry Andric #include "clang/Lex/ModuleMap.h"
16139f7f9bSDimitry Andric #include "clang/Basic/CharInfo.h"
17dff0c46cSDimitry Andric #include "clang/Basic/Diagnostic.h"
18dff0c46cSDimitry Andric #include "clang/Basic/FileManager.h"
199a199699SDimitry Andric #include "clang/Basic/LLVM.h"
209a199699SDimitry Andric #include "clang/Basic/LangOptions.h"
219a199699SDimitry Andric #include "clang/Basic/Module.h"
229a199699SDimitry Andric #include "clang/Basic/SourceLocation.h"
239a199699SDimitry Andric #include "clang/Basic/SourceManager.h"
24dff0c46cSDimitry Andric #include "clang/Basic/TargetInfo.h"
25139f7f9bSDimitry Andric #include "clang/Lex/HeaderSearch.h"
2639d628a0SDimitry Andric #include "clang/Lex/HeaderSearchOptions.h"
27139f7f9bSDimitry Andric #include "clang/Lex/LexDiagnostic.h"
28139f7f9bSDimitry Andric #include "clang/Lex/Lexer.h"
29139f7f9bSDimitry Andric #include "clang/Lex/LiteralSupport.h"
309a199699SDimitry Andric #include "clang/Lex/Token.h"
319a199699SDimitry Andric #include "llvm/ADT/DenseMap.h"
329a199699SDimitry Andric #include "llvm/ADT/None.h"
339a199699SDimitry Andric #include "llvm/ADT/STLExtras.h"
349a199699SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
359a199699SDimitry Andric #include "llvm/ADT/SmallString.h"
369a199699SDimitry Andric #include "llvm/ADT/SmallVector.h"
379a199699SDimitry Andric #include "llvm/ADT/StringMap.h"
38139f7f9bSDimitry Andric #include "llvm/ADT/StringRef.h"
39139f7f9bSDimitry Andric #include "llvm/ADT/StringSwitch.h"
40dff0c46cSDimitry Andric #include "llvm/Support/Allocator.h"
419a199699SDimitry Andric #include "llvm/Support/Compiler.h"
429a199699SDimitry Andric #include "llvm/Support/ErrorHandling.h"
439a199699SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
44f785676fSDimitry Andric #include "llvm/Support/Path.h"
45*b5893f02SDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
46dff0c46cSDimitry Andric #include "llvm/Support/raw_ostream.h"
479a199699SDimitry Andric #include <algorithm>
489a199699SDimitry Andric #include <cassert>
499a199699SDimitry Andric #include <cstdint>
509a199699SDimitry Andric #include <cstring>
519a199699SDimitry Andric #include <string>
529a199699SDimitry Andric #include <system_error>
539a199699SDimitry Andric #include <utility>
549a199699SDimitry Andric 
55dff0c46cSDimitry Andric using namespace clang;
56dff0c46cSDimitry Andric 
anchor()57*b5893f02SDimitry Andric void ModuleMapCallbacks::anchor() {}
58*b5893f02SDimitry Andric 
resolveLinkAsDependencies(Module * Mod)594ba319b5SDimitry Andric void ModuleMap::resolveLinkAsDependencies(Module *Mod) {
604ba319b5SDimitry Andric   auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name);
614ba319b5SDimitry Andric   if (PendingLinkAs != PendingLinkAsModule.end()) {
624ba319b5SDimitry Andric     for (auto &Name : PendingLinkAs->second) {
634ba319b5SDimitry Andric       auto *M = findModule(Name.getKey());
644ba319b5SDimitry Andric       if (M)
654ba319b5SDimitry Andric         M->UseExportAsModuleLinkName = true;
664ba319b5SDimitry Andric     }
674ba319b5SDimitry Andric   }
684ba319b5SDimitry Andric }
694ba319b5SDimitry Andric 
addLinkAsDependency(Module * Mod)704ba319b5SDimitry Andric void ModuleMap::addLinkAsDependency(Module *Mod) {
714ba319b5SDimitry Andric   if (findModule(Mod->ExportAsModule))
724ba319b5SDimitry Andric     Mod->UseExportAsModuleLinkName = true;
734ba319b5SDimitry Andric   else
744ba319b5SDimitry Andric     PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name);
754ba319b5SDimitry Andric }
764ba319b5SDimitry Andric 
headerRoleToKind(ModuleHeaderRole Role)776d97bb29SDimitry Andric Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
786d97bb29SDimitry Andric   switch ((int)Role) {
796d97bb29SDimitry Andric   default: llvm_unreachable("unknown header role");
806d97bb29SDimitry Andric   case NormalHeader:
816d97bb29SDimitry Andric     return Module::HK_Normal;
826d97bb29SDimitry Andric   case PrivateHeader:
836d97bb29SDimitry Andric     return Module::HK_Private;
846d97bb29SDimitry Andric   case TextualHeader:
856d97bb29SDimitry Andric     return Module::HK_Textual;
866d97bb29SDimitry Andric   case PrivateHeader | TextualHeader:
876d97bb29SDimitry Andric     return Module::HK_PrivateTextual;
886d97bb29SDimitry Andric   }
896d97bb29SDimitry Andric }
906d97bb29SDimitry Andric 
916d97bb29SDimitry Andric ModuleMap::ModuleHeaderRole
headerKindToRole(Module::HeaderKind Kind)926d97bb29SDimitry Andric ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
936d97bb29SDimitry Andric   switch ((int)Kind) {
946d97bb29SDimitry Andric   case Module::HK_Normal:
956d97bb29SDimitry Andric     return NormalHeader;
966d97bb29SDimitry Andric   case Module::HK_Private:
976d97bb29SDimitry Andric     return PrivateHeader;
986d97bb29SDimitry Andric   case Module::HK_Textual:
996d97bb29SDimitry Andric     return TextualHeader;
1006d97bb29SDimitry Andric   case Module::HK_PrivateTextual:
1016d97bb29SDimitry Andric     return ModuleHeaderRole(PrivateHeader | TextualHeader);
1026d97bb29SDimitry Andric   case Module::HK_Excluded:
1036d97bb29SDimitry Andric     llvm_unreachable("unexpected header kind");
1046d97bb29SDimitry Andric   }
1056d97bb29SDimitry Andric   llvm_unreachable("unknown header kind");
1066d97bb29SDimitry Andric }
1076d97bb29SDimitry Andric 
108dff0c46cSDimitry Andric Module::ExportDecl
resolveExport(Module * Mod,const Module::UnresolvedExportDecl & Unresolved,bool Complain) const109dff0c46cSDimitry Andric ModuleMap::resolveExport(Module *Mod,
110dff0c46cSDimitry Andric                          const Module::UnresolvedExportDecl &Unresolved,
111139f7f9bSDimitry Andric                          bool Complain) const {
112dff0c46cSDimitry Andric   // We may have just a wildcard.
113dff0c46cSDimitry Andric   if (Unresolved.Id.empty()) {
114dff0c46cSDimitry Andric     assert(Unresolved.Wildcard && "Invalid unresolved export");
11559d1ed5bSDimitry Andric     return Module::ExportDecl(nullptr, true);
116dff0c46cSDimitry Andric   }
117dff0c46cSDimitry Andric 
118139f7f9bSDimitry Andric   // Resolve the module-id.
119139f7f9bSDimitry Andric   Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
120139f7f9bSDimitry Andric   if (!Context)
1219a199699SDimitry Andric     return {};
122139f7f9bSDimitry Andric 
123139f7f9bSDimitry Andric   return Module::ExportDecl(Context, Unresolved.Wildcard);
124139f7f9bSDimitry Andric }
125139f7f9bSDimitry Andric 
resolveModuleId(const ModuleId & Id,Module * Mod,bool Complain) const126139f7f9bSDimitry Andric Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
127139f7f9bSDimitry Andric                                    bool Complain) const {
128dff0c46cSDimitry Andric   // Find the starting module.
129139f7f9bSDimitry Andric   Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
130dff0c46cSDimitry Andric   if (!Context) {
131dff0c46cSDimitry Andric     if (Complain)
13259d1ed5bSDimitry Andric       Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
133139f7f9bSDimitry Andric       << Id[0].first << Mod->getFullModuleName();
134dff0c46cSDimitry Andric 
13559d1ed5bSDimitry Andric     return nullptr;
136dff0c46cSDimitry Andric   }
137dff0c46cSDimitry Andric 
138dff0c46cSDimitry Andric   // Dig into the module path.
139139f7f9bSDimitry Andric   for (unsigned I = 1, N = Id.size(); I != N; ++I) {
140139f7f9bSDimitry Andric     Module *Sub = lookupModuleQualified(Id[I].first, Context);
141dff0c46cSDimitry Andric     if (!Sub) {
142dff0c46cSDimitry Andric       if (Complain)
14359d1ed5bSDimitry Andric         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
144139f7f9bSDimitry Andric         << Id[I].first << Context->getFullModuleName()
145139f7f9bSDimitry Andric         << SourceRange(Id[0].second, Id[I-1].second);
146dff0c46cSDimitry Andric 
14759d1ed5bSDimitry Andric       return nullptr;
148dff0c46cSDimitry Andric     }
149dff0c46cSDimitry Andric 
150dff0c46cSDimitry Andric     Context = Sub;
151dff0c46cSDimitry Andric   }
152dff0c46cSDimitry Andric 
153139f7f9bSDimitry Andric   return Context;
154dff0c46cSDimitry Andric }
155dff0c46cSDimitry Andric 
1564ba319b5SDimitry Andric /// Append to \p Paths the set of paths needed to get to the
157302affcbSDimitry Andric /// subframework in which the given module lives.
appendSubframeworkPaths(Module * Mod,SmallVectorImpl<char> & Path)158302affcbSDimitry Andric static void appendSubframeworkPaths(Module *Mod,
159302affcbSDimitry Andric                                     SmallVectorImpl<char> &Path) {
160302affcbSDimitry Andric   // Collect the framework names from the given module to the top-level module.
161302affcbSDimitry Andric   SmallVector<StringRef, 2> Paths;
162302affcbSDimitry Andric   for (; Mod; Mod = Mod->Parent) {
163302affcbSDimitry Andric     if (Mod->IsFramework)
164302affcbSDimitry Andric       Paths.push_back(Mod->Name);
165302affcbSDimitry Andric   }
166302affcbSDimitry Andric 
167302affcbSDimitry Andric   if (Paths.empty())
168302affcbSDimitry Andric     return;
169302affcbSDimitry Andric 
170302affcbSDimitry Andric   // Add Frameworks/Name.framework for each subframework.
171302affcbSDimitry Andric   for (unsigned I = Paths.size() - 1; I != 0; --I)
172302affcbSDimitry Andric     llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework");
173302affcbSDimitry Andric }
174302affcbSDimitry Andric 
findHeader(Module * M,const Module::UnresolvedHeaderDirective & Header,SmallVectorImpl<char> & RelativePathName,bool & NeedsFramework)1754ba319b5SDimitry Andric const FileEntry *ModuleMap::findHeader(
1764ba319b5SDimitry Andric     Module *M, const Module::UnresolvedHeaderDirective &Header,
1774ba319b5SDimitry Andric     SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) {
1784ba319b5SDimitry Andric   // Search for the header file within the module's home directory.
1794ba319b5SDimitry Andric   auto *Directory = M->Directory;
1804ba319b5SDimitry Andric   SmallString<128> FullPathName(Directory->getName());
1814ba319b5SDimitry Andric 
1826d97bb29SDimitry Andric   auto GetFile = [&](StringRef Filename) -> const FileEntry * {
1836d97bb29SDimitry Andric     auto *File = SourceMgr.getFileManager().getFile(Filename);
1846d97bb29SDimitry Andric     if (!File ||
1856d97bb29SDimitry Andric         (Header.Size && File->getSize() != *Header.Size) ||
1866d97bb29SDimitry Andric         (Header.ModTime && File->getModificationTime() != *Header.ModTime))
1876d97bb29SDimitry Andric       return nullptr;
1886d97bb29SDimitry Andric     return File;
1896d97bb29SDimitry Andric   };
1906d97bb29SDimitry Andric 
1914ba319b5SDimitry Andric   auto GetFrameworkFile = [&]() -> const FileEntry * {
192302affcbSDimitry Andric     unsigned FullPathLength = FullPathName.size();
193302affcbSDimitry Andric     appendSubframeworkPaths(M, RelativePathName);
194302affcbSDimitry Andric     unsigned RelativePathLength = RelativePathName.size();
195302affcbSDimitry Andric 
196302affcbSDimitry Andric     // Check whether this file is in the public headers.
197302affcbSDimitry Andric     llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
198302affcbSDimitry Andric     llvm::sys::path::append(FullPathName, RelativePathName);
1996d97bb29SDimitry Andric     if (auto *File = GetFile(FullPathName))
200302affcbSDimitry Andric       return File;
201302affcbSDimitry Andric 
202302affcbSDimitry Andric     // Check whether this file is in the private headers.
203302affcbSDimitry Andric     // Ideally, private modules in the form 'FrameworkName.Private' should
204302affcbSDimitry Andric     // be defined as 'module FrameworkName.Private', and not as
205302affcbSDimitry Andric     // 'framework module FrameworkName.Private', since a 'Private.Framework'
206302affcbSDimitry Andric     // does not usually exist. However, since both are currently widely used
207302affcbSDimitry Andric     // for private modules, make sure we find the right path in both cases.
208302affcbSDimitry Andric     if (M->IsFramework && M->Name == "Private")
209302affcbSDimitry Andric       RelativePathName.clear();
210302affcbSDimitry Andric     else
211302affcbSDimitry Andric       RelativePathName.resize(RelativePathLength);
212302affcbSDimitry Andric     FullPathName.resize(FullPathLength);
213302affcbSDimitry Andric     llvm::sys::path::append(RelativePathName, "PrivateHeaders",
214302affcbSDimitry Andric                             Header.FileName);
215302affcbSDimitry Andric     llvm::sys::path::append(FullPathName, RelativePathName);
2166d97bb29SDimitry Andric     return GetFile(FullPathName);
2174ba319b5SDimitry Andric   };
2184ba319b5SDimitry Andric 
2194ba319b5SDimitry Andric   if (llvm::sys::path::is_absolute(Header.FileName)) {
2204ba319b5SDimitry Andric     RelativePathName.clear();
2214ba319b5SDimitry Andric     RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
2224ba319b5SDimitry Andric     return GetFile(Header.FileName);
223302affcbSDimitry Andric   }
224302affcbSDimitry Andric 
2254ba319b5SDimitry Andric   if (M->isPartOfFramework())
2264ba319b5SDimitry Andric     return GetFrameworkFile();
2274ba319b5SDimitry Andric 
228302affcbSDimitry Andric   // Lookup for normal headers.
229302affcbSDimitry Andric   llvm::sys::path::append(RelativePathName, Header.FileName);
230302affcbSDimitry Andric   llvm::sys::path::append(FullPathName, RelativePathName);
2314ba319b5SDimitry Andric   auto *NormalHdrFile = GetFile(FullPathName);
2324ba319b5SDimitry Andric 
2334ba319b5SDimitry Andric   if (M && !NormalHdrFile && Directory->getName().endswith(".framework")) {
2344ba319b5SDimitry Andric     // The lack of 'framework' keyword in a module declaration it's a simple
2354ba319b5SDimitry Andric     // mistake we can diagnose when the header exists within the proper
2364ba319b5SDimitry Andric     // framework style path.
2374ba319b5SDimitry Andric     FullPathName.assign(Directory->getName());
2384ba319b5SDimitry Andric     RelativePathName.clear();
2394ba319b5SDimitry Andric     if (GetFrameworkFile()) {
2404ba319b5SDimitry Andric       Diags.Report(Header.FileNameLoc,
2414ba319b5SDimitry Andric                    diag::warn_mmap_incomplete_framework_module_declaration)
2424ba319b5SDimitry Andric           << Header.FileName << M->getFullModuleName();
2434ba319b5SDimitry Andric       NeedsFramework = true;
2444ba319b5SDimitry Andric     }
2454ba319b5SDimitry Andric     return nullptr;
2464ba319b5SDimitry Andric   }
2474ba319b5SDimitry Andric 
2484ba319b5SDimitry Andric   return NormalHdrFile;
249302affcbSDimitry Andric }
250302affcbSDimitry Andric 
resolveHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header,bool & NeedsFramework)2516d97bb29SDimitry Andric void ModuleMap::resolveHeader(Module *Mod,
2524ba319b5SDimitry Andric                               const Module::UnresolvedHeaderDirective &Header,
2534ba319b5SDimitry Andric                               bool &NeedsFramework) {
2546d97bb29SDimitry Andric   SmallString<128> RelativePathName;
2554ba319b5SDimitry Andric   if (const FileEntry *File =
2564ba319b5SDimitry Andric           findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
2576d97bb29SDimitry Andric     if (Header.IsUmbrella) {
2586d97bb29SDimitry Andric       const DirectoryEntry *UmbrellaDir = File->getDir();
2596d97bb29SDimitry Andric       if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
2606d97bb29SDimitry Andric         Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2616d97bb29SDimitry Andric           << UmbrellaMod->getFullModuleName();
2626d97bb29SDimitry Andric       else
2636d97bb29SDimitry Andric         // Record this umbrella header.
2646d97bb29SDimitry Andric         setUmbrellaHeader(Mod, File, RelativePathName.str());
2656d97bb29SDimitry Andric     } else {
2666d97bb29SDimitry Andric       Module::Header H = {RelativePathName.str(), File};
2676d97bb29SDimitry Andric       if (Header.Kind == Module::HK_Excluded)
2686d97bb29SDimitry Andric         excludeHeader(Mod, H);
2696d97bb29SDimitry Andric       else
2706d97bb29SDimitry Andric         addHeader(Mod, H, headerKindToRole(Header.Kind));
2716d97bb29SDimitry Andric     }
2726d97bb29SDimitry Andric   } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
2736d97bb29SDimitry Andric     // There's a builtin header but no corresponding on-disk header. Assume
2746d97bb29SDimitry Andric     // this was supposed to modularize the builtin header alone.
2756d97bb29SDimitry Andric   } else if (Header.Kind == Module::HK_Excluded) {
2766d97bb29SDimitry Andric     // Ignore missing excluded header files. They're optional anyway.
2776d97bb29SDimitry Andric   } else {
2786d97bb29SDimitry Andric     // If we find a module that has a missing header, we mark this module as
2796d97bb29SDimitry Andric     // unavailable and store the header directive for displaying diagnostics.
2806d97bb29SDimitry Andric     Mod->MissingHeaders.push_back(Header);
2816d97bb29SDimitry Andric     // A missing header with stat information doesn't make the module
2826d97bb29SDimitry Andric     // unavailable; this keeps our behavior consistent as headers are lazily
2836d97bb29SDimitry Andric     // resolved. (Such a module still can't be built though, except from
2846d97bb29SDimitry Andric     // preprocessed source.)
2856d97bb29SDimitry Andric     if (!Header.Size && !Header.ModTime)
2866d97bb29SDimitry Andric       Mod->markUnavailable();
2876d97bb29SDimitry Andric   }
2886d97bb29SDimitry Andric }
2896d97bb29SDimitry Andric 
resolveAsBuiltinHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header)2906d97bb29SDimitry Andric bool ModuleMap::resolveAsBuiltinHeader(
2916d97bb29SDimitry Andric     Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
2926d97bb29SDimitry Andric   if (Header.Kind == Module::HK_Excluded ||
2936d97bb29SDimitry Andric       llvm::sys::path::is_absolute(Header.FileName) ||
2946d97bb29SDimitry Andric       Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
2956d97bb29SDimitry Andric       !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
2966d97bb29SDimitry Andric       !isBuiltinHeader(Header.FileName))
2976d97bb29SDimitry Andric     return false;
298302affcbSDimitry Andric 
299302affcbSDimitry Andric   // This is a system module with a top-level header. This header
300302affcbSDimitry Andric   // may have a counterpart (or replacement) in the set of headers
301302affcbSDimitry Andric   // supplied by Clang. Find that builtin header.
3026d97bb29SDimitry Andric   SmallString<128> Path;
3036d97bb29SDimitry Andric   llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
3046d97bb29SDimitry Andric   auto *File = SourceMgr.getFileManager().getFile(Path);
3056d97bb29SDimitry Andric   if (!File)
3066d97bb29SDimitry Andric     return false;
3076d97bb29SDimitry Andric 
3086d97bb29SDimitry Andric   auto Role = headerKindToRole(Header.Kind);
3096d97bb29SDimitry Andric   Module::Header H = {Path.str(), File};
3106d97bb29SDimitry Andric   addHeader(Mod, H, Role);
3116d97bb29SDimitry Andric   return true;
312302affcbSDimitry Andric }
313302affcbSDimitry Andric 
ModuleMap(SourceManager & SourceMgr,DiagnosticsEngine & Diags,const LangOptions & LangOpts,const TargetInfo * Target,HeaderSearch & HeaderInfo)31459d1ed5bSDimitry Andric ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
315139f7f9bSDimitry Andric                      const LangOptions &LangOpts, const TargetInfo *Target,
316139f7f9bSDimitry Andric                      HeaderSearch &HeaderInfo)
31759d1ed5bSDimitry Andric     : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
3189a199699SDimitry Andric       HeaderInfo(HeaderInfo) {
31933956c43SDimitry Andric   MMapLangOpts.LineComment = true;
32033956c43SDimitry Andric }
321dff0c46cSDimitry Andric 
~ModuleMap()322dff0c46cSDimitry Andric ModuleMap::~ModuleMap() {
323e7145dcbSDimitry Andric   for (auto &M : Modules)
324e7145dcbSDimitry Andric     delete M.getValue();
3254ba319b5SDimitry Andric   for (auto *M : ShadowModules)
3264ba319b5SDimitry Andric     delete M;
327dff0c46cSDimitry Andric }
328dff0c46cSDimitry Andric 
setTarget(const TargetInfo & Target)329dff0c46cSDimitry Andric void ModuleMap::setTarget(const TargetInfo &Target) {
330dff0c46cSDimitry Andric   assert((!this->Target || this->Target == &Target) &&
331dff0c46cSDimitry Andric          "Improper target override");
332dff0c46cSDimitry Andric   this->Target = &Target;
333dff0c46cSDimitry Andric }
334dff0c46cSDimitry Andric 
3354ba319b5SDimitry Andric /// "Sanitize" a filename so that it can be used as an identifier.
sanitizeFilenameAsIdentifier(StringRef Name,SmallVectorImpl<char> & Buffer)3363861d79fSDimitry Andric static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
3373861d79fSDimitry Andric                                               SmallVectorImpl<char> &Buffer) {
3383861d79fSDimitry Andric   if (Name.empty())
3393861d79fSDimitry Andric     return Name;
3403861d79fSDimitry Andric 
341139f7f9bSDimitry Andric   if (!isValidIdentifier(Name)) {
3423861d79fSDimitry Andric     // If we don't already have something with the form of an identifier,
3433861d79fSDimitry Andric     // create a buffer with the sanitized name.
3443861d79fSDimitry Andric     Buffer.clear();
345139f7f9bSDimitry Andric     if (isDigit(Name[0]))
3463861d79fSDimitry Andric       Buffer.push_back('_');
3473861d79fSDimitry Andric     Buffer.reserve(Buffer.size() + Name.size());
3483861d79fSDimitry Andric     for (unsigned I = 0, N = Name.size(); I != N; ++I) {
349139f7f9bSDimitry Andric       if (isIdentifierBody(Name[I]))
3503861d79fSDimitry Andric         Buffer.push_back(Name[I]);
3513861d79fSDimitry Andric       else
3523861d79fSDimitry Andric         Buffer.push_back('_');
3533861d79fSDimitry Andric     }
3543861d79fSDimitry Andric 
3553861d79fSDimitry Andric     Name = StringRef(Buffer.data(), Buffer.size());
3563861d79fSDimitry Andric   }
3573861d79fSDimitry Andric 
3583861d79fSDimitry Andric   while (llvm::StringSwitch<bool>(Name)
3593861d79fSDimitry Andric #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
3603861d79fSDimitry Andric #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
3613861d79fSDimitry Andric #include "clang/Basic/TokenKinds.def"
3623861d79fSDimitry Andric            .Default(false)) {
3633861d79fSDimitry Andric     if (Name.data() != Buffer.data())
3643861d79fSDimitry Andric       Buffer.append(Name.begin(), Name.end());
3653861d79fSDimitry Andric     Buffer.push_back('_');
3663861d79fSDimitry Andric     Name = StringRef(Buffer.data(), Buffer.size());
3673861d79fSDimitry Andric   }
3683861d79fSDimitry Andric 
3693861d79fSDimitry Andric   return Name;
3703861d79fSDimitry Andric }
3713861d79fSDimitry Andric 
3724ba319b5SDimitry Andric /// Determine whether the given file name is the name of a builtin
373284c1978SDimitry Andric /// header, supplied by Clang to replace, override, or augment existing system
374284c1978SDimitry Andric /// headers.
isBuiltinHeader(StringRef FileName)375f1a29dd3SDimitry Andric bool ModuleMap::isBuiltinHeader(StringRef FileName) {
376284c1978SDimitry Andric   return llvm::StringSwitch<bool>(FileName)
377284c1978SDimitry Andric            .Case("float.h", true)
378284c1978SDimitry Andric            .Case("iso646.h", true)
379284c1978SDimitry Andric            .Case("limits.h", true)
380284c1978SDimitry Andric            .Case("stdalign.h", true)
381284c1978SDimitry Andric            .Case("stdarg.h", true)
382e7145dcbSDimitry Andric            .Case("stdatomic.h", true)
383284c1978SDimitry Andric            .Case("stdbool.h", true)
384284c1978SDimitry Andric            .Case("stddef.h", true)
385284c1978SDimitry Andric            .Case("stdint.h", true)
386284c1978SDimitry Andric            .Case("tgmath.h", true)
387284c1978SDimitry Andric            .Case("unwind.h", true)
388284c1978SDimitry Andric            .Default(false);
389284c1978SDimitry Andric }
390284c1978SDimitry Andric 
39159d1ed5bSDimitry Andric ModuleMap::HeadersMap::iterator
findKnownHeader(const FileEntry * File)39259d1ed5bSDimitry Andric ModuleMap::findKnownHeader(const FileEntry *File) {
3936d97bb29SDimitry Andric   resolveHeaderDirectives(File);
3943861d79fSDimitry Andric   HeadersMap::iterator Known = Headers.find(File);
3958f0fd8f6SDimitry Andric   if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
3968f0fd8f6SDimitry Andric       Known == Headers.end() && File->getDir() == BuiltinIncludeDir &&
397f1a29dd3SDimitry Andric       ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()))) {
398f785676fSDimitry Andric     HeaderInfo.loadTopLevelSystemModules();
39959d1ed5bSDimitry Andric     return Headers.find(File);
40059d1ed5bSDimitry Andric   }
40159d1ed5bSDimitry Andric   return Known;
402284c1978SDimitry Andric }
403284c1978SDimitry Andric 
40459d1ed5bSDimitry Andric ModuleMap::KnownHeader
findHeaderInUmbrellaDirs(const FileEntry * File,SmallVectorImpl<const DirectoryEntry * > & IntermediateDirs)40559d1ed5bSDimitry Andric ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
40659d1ed5bSDimitry Andric                     SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
4078f0fd8f6SDimitry Andric   if (UmbrellaDirs.empty())
4089a199699SDimitry Andric     return {};
4098f0fd8f6SDimitry Andric 
410dff0c46cSDimitry Andric   const DirectoryEntry *Dir = File->getDir();
41159d1ed5bSDimitry Andric   assert(Dir && "file in no directory");
412139f7f9bSDimitry Andric 
413139f7f9bSDimitry Andric   // Note: as an egregious but useful hack we use the real path here, because
414139f7f9bSDimitry Andric   // frameworks moving from top-level frameworks to embedded frameworks tend
415139f7f9bSDimitry Andric   // to be symlinked from the top-level location to the embedded location,
416139f7f9bSDimitry Andric   // and we need to resolve lookups as if we had found the embedded location.
417f785676fSDimitry Andric   StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
418dff0c46cSDimitry Andric 
419dff0c46cSDimitry Andric   // Keep walking up the directory hierarchy, looking for a directory with
420dff0c46cSDimitry Andric   // an umbrella header.
421dff0c46cSDimitry Andric   do {
42259d1ed5bSDimitry Andric     auto KnownDir = UmbrellaDirs.find(Dir);
42359d1ed5bSDimitry Andric     if (KnownDir != UmbrellaDirs.end())
42459d1ed5bSDimitry Andric       return KnownHeader(KnownDir->second, NormalHeader);
42559d1ed5bSDimitry Andric 
42659d1ed5bSDimitry Andric     IntermediateDirs.push_back(Dir);
42759d1ed5bSDimitry Andric 
42859d1ed5bSDimitry Andric     // Retrieve our parent path.
42959d1ed5bSDimitry Andric     DirName = llvm::sys::path::parent_path(DirName);
43059d1ed5bSDimitry Andric     if (DirName.empty())
43159d1ed5bSDimitry Andric       break;
43259d1ed5bSDimitry Andric 
43359d1ed5bSDimitry Andric     // Resolve the parent path to a directory entry.
43459d1ed5bSDimitry Andric     Dir = SourceMgr.getFileManager().getDirectory(DirName);
43559d1ed5bSDimitry Andric   } while (Dir);
4369a199699SDimitry Andric   return {};
43759d1ed5bSDimitry Andric }
43859d1ed5bSDimitry Andric 
violatesPrivateInclude(Module * RequestingModule,const FileEntry * IncFileEnt,ModuleMap::KnownHeader Header)43959d1ed5bSDimitry Andric static bool violatesPrivateInclude(Module *RequestingModule,
44059d1ed5bSDimitry Andric                                    const FileEntry *IncFileEnt,
441e7145dcbSDimitry Andric                                    ModuleMap::KnownHeader Header) {
44259d1ed5bSDimitry Andric #ifndef NDEBUG
443e7145dcbSDimitry Andric   if (Header.getRole() & ModuleMap::PrivateHeader) {
44459d1ed5bSDimitry Andric     // Check for consistency between the module header role
44559d1ed5bSDimitry Andric     // as obtained from the lookup and as obtained from the module.
44659d1ed5bSDimitry Andric     // This check is not cheap, so enable it only for debugging.
44739d628a0SDimitry Andric     bool IsPrivate = false;
44833956c43SDimitry Andric     SmallVectorImpl<Module::Header> *HeaderList[] = {
449e7145dcbSDimitry Andric         &Header.getModule()->Headers[Module::HK_Private],
450e7145dcbSDimitry Andric         &Header.getModule()->Headers[Module::HK_PrivateTextual]};
45133956c43SDimitry Andric     for (auto *Hs : HeaderList)
45239d628a0SDimitry Andric       IsPrivate |=
45333956c43SDimitry Andric           std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) {
45439d628a0SDimitry Andric             return H.Entry == IncFileEnt;
45533956c43SDimitry Andric           }) != Hs->end();
456e7145dcbSDimitry Andric     assert(IsPrivate && "inconsistent headers and roles");
45733956c43SDimitry Andric   }
45859d1ed5bSDimitry Andric #endif
459e7145dcbSDimitry Andric   return !Header.isAccessibleFrom(RequestingModule);
46059d1ed5bSDimitry Andric }
46159d1ed5bSDimitry Andric 
getTopLevelOrNull(Module * M)46259d1ed5bSDimitry Andric static Module *getTopLevelOrNull(Module *M) {
46359d1ed5bSDimitry Andric   return M ? M->getTopLevelModule() : nullptr;
46459d1ed5bSDimitry Andric }
46559d1ed5bSDimitry Andric 
diagnoseHeaderInclusion(Module * RequestingModule,bool RequestingModuleIsModuleInterface,SourceLocation FilenameLoc,StringRef Filename,const FileEntry * File)46659d1ed5bSDimitry Andric void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
467e7145dcbSDimitry Andric                                         bool RequestingModuleIsModuleInterface,
46859d1ed5bSDimitry Andric                                         SourceLocation FilenameLoc,
46959d1ed5bSDimitry Andric                                         StringRef Filename,
47059d1ed5bSDimitry Andric                                         const FileEntry *File) {
47159d1ed5bSDimitry Andric   // No errors for indirect modules. This may be a bit of a problem for modules
47259d1ed5bSDimitry Andric   // with no source files.
47359d1ed5bSDimitry Andric   if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
47459d1ed5bSDimitry Andric     return;
47559d1ed5bSDimitry Andric 
4766d97bb29SDimitry Andric   if (RequestingModule) {
47759d1ed5bSDimitry Andric     resolveUses(RequestingModule, /*Complain=*/false);
4786d97bb29SDimitry Andric     resolveHeaderDirectives(RequestingModule);
4796d97bb29SDimitry Andric   }
48059d1ed5bSDimitry Andric 
48159d1ed5bSDimitry Andric   bool Excluded = false;
48259d1ed5bSDimitry Andric   Module *Private = nullptr;
48359d1ed5bSDimitry Andric   Module *NotUsed = nullptr;
48459d1ed5bSDimitry Andric 
48559d1ed5bSDimitry Andric   HeadersMap::iterator Known = findKnownHeader(File);
48659d1ed5bSDimitry Andric   if (Known != Headers.end()) {
48759d1ed5bSDimitry Andric     for (const KnownHeader &Header : Known->second) {
48859d1ed5bSDimitry Andric       // Remember private headers for later printing of a diagnostic.
489e7145dcbSDimitry Andric       if (violatesPrivateInclude(RequestingModule, File, Header)) {
49059d1ed5bSDimitry Andric         Private = Header.getModule();
49159d1ed5bSDimitry Andric         continue;
49259d1ed5bSDimitry Andric       }
49359d1ed5bSDimitry Andric 
49459d1ed5bSDimitry Andric       // If uses need to be specified explicitly, we are only allowed to return
49559d1ed5bSDimitry Andric       // modules that are explicitly used by the requesting module.
49659d1ed5bSDimitry Andric       if (RequestingModule && LangOpts.ModulesDeclUse &&
49733956c43SDimitry Andric           !RequestingModule->directlyUses(Header.getModule())) {
49859d1ed5bSDimitry Andric         NotUsed = Header.getModule();
49959d1ed5bSDimitry Andric         continue;
50059d1ed5bSDimitry Andric       }
50159d1ed5bSDimitry Andric 
50259d1ed5bSDimitry Andric       // We have found a module that we can happily use.
50359d1ed5bSDimitry Andric       return;
50459d1ed5bSDimitry Andric     }
50539d628a0SDimitry Andric 
50639d628a0SDimitry Andric     Excluded = true;
50759d1ed5bSDimitry Andric   }
50859d1ed5bSDimitry Andric 
50959d1ed5bSDimitry Andric   // We have found a header, but it is private.
51059d1ed5bSDimitry Andric   if (Private) {
51133956c43SDimitry Andric     Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
51259d1ed5bSDimitry Andric         << Filename;
51359d1ed5bSDimitry Andric     return;
51459d1ed5bSDimitry Andric   }
51559d1ed5bSDimitry Andric 
51659d1ed5bSDimitry Andric   // We have found a module, but we don't use it.
51759d1ed5bSDimitry Andric   if (NotUsed) {
51833956c43SDimitry Andric     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5194ba319b5SDimitry Andric         << RequestingModule->getTopLevelModule()->Name << Filename;
52059d1ed5bSDimitry Andric     return;
52159d1ed5bSDimitry Andric   }
52259d1ed5bSDimitry Andric 
52359d1ed5bSDimitry Andric   if (Excluded || isHeaderInUmbrellaDirs(File))
52459d1ed5bSDimitry Andric     return;
52559d1ed5bSDimitry Andric 
52659d1ed5bSDimitry Andric   // At this point, only non-modular includes remain.
52759d1ed5bSDimitry Andric 
528*b5893f02SDimitry Andric   if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
52933956c43SDimitry Andric     Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5304ba319b5SDimitry Andric         << RequestingModule->getTopLevelModule()->Name << Filename;
53144290647SDimitry Andric   } else if (RequestingModule && RequestingModuleIsModuleInterface &&
53244290647SDimitry Andric              LangOpts.isCompilingModule()) {
53344290647SDimitry Andric     // Do not diagnose when we are not compiling a module.
53459d1ed5bSDimitry Andric     diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
53559d1ed5bSDimitry Andric         diag::warn_non_modular_include_in_framework_module :
53659d1ed5bSDimitry Andric         diag::warn_non_modular_include_in_module;
53744290647SDimitry Andric     Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
53844290647SDimitry Andric         << File->getName();
53959d1ed5bSDimitry Andric   }
54059d1ed5bSDimitry Andric }
54159d1ed5bSDimitry Andric 
isBetterKnownHeader(const ModuleMap::KnownHeader & New,const ModuleMap::KnownHeader & Old)54233956c43SDimitry Andric static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
54333956c43SDimitry Andric                                 const ModuleMap::KnownHeader &Old) {
5440623d748SDimitry Andric   // Prefer available modules.
5450623d748SDimitry Andric   if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
5460623d748SDimitry Andric     return true;
5470623d748SDimitry Andric 
54833956c43SDimitry Andric   // Prefer a public header over a private header.
54933956c43SDimitry Andric   if ((New.getRole() & ModuleMap::PrivateHeader) !=
55033956c43SDimitry Andric       (Old.getRole() & ModuleMap::PrivateHeader))
55133956c43SDimitry Andric     return !(New.getRole() & ModuleMap::PrivateHeader);
55233956c43SDimitry Andric 
55333956c43SDimitry Andric   // Prefer a non-textual header over a textual header.
55433956c43SDimitry Andric   if ((New.getRole() & ModuleMap::TextualHeader) !=
55533956c43SDimitry Andric       (Old.getRole() & ModuleMap::TextualHeader))
55633956c43SDimitry Andric     return !(New.getRole() & ModuleMap::TextualHeader);
55733956c43SDimitry Andric 
55833956c43SDimitry Andric   // Don't have a reason to choose between these. Just keep the first one.
55933956c43SDimitry Andric   return false;
56033956c43SDimitry Andric }
56133956c43SDimitry Andric 
findModuleForHeader(const FileEntry * File,bool AllowTextual)56244290647SDimitry Andric ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
56344290647SDimitry Andric                                                       bool AllowTextual) {
56439d628a0SDimitry Andric   auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
56544290647SDimitry Andric     if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
5669a199699SDimitry Andric       return {};
56739d628a0SDimitry Andric     return R;
56839d628a0SDimitry Andric   };
56939d628a0SDimitry Andric 
5708f0fd8f6SDimitry Andric   HeadersMap::iterator Known = findKnownHeader(File);
57159d1ed5bSDimitry Andric   if (Known != Headers.end()) {
57239d628a0SDimitry Andric     ModuleMap::KnownHeader Result;
57359d1ed5bSDimitry Andric     // Iterate over all modules that 'File' is part of to find the best fit.
5748f0fd8f6SDimitry Andric     for (KnownHeader &H : Known->second) {
575e7145dcbSDimitry Andric       // Prefer a header from the source module over all others.
576e7145dcbSDimitry Andric       if (H.getModule()->getTopLevelModule() == SourceModule)
5773dac3a9bSDimitry Andric         return MakeResult(H);
5788f0fd8f6SDimitry Andric       if (!Result || isBetterKnownHeader(H, Result))
5798f0fd8f6SDimitry Andric         Result = H;
58059d1ed5bSDimitry Andric     }
58139d628a0SDimitry Andric     return MakeResult(Result);
58259d1ed5bSDimitry Andric   }
58359d1ed5bSDimitry Andric 
5840623d748SDimitry Andric   return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
5850623d748SDimitry Andric }
5860623d748SDimitry Andric 
5870623d748SDimitry Andric ModuleMap::KnownHeader
findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry * File)5880623d748SDimitry Andric ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
5890623d748SDimitry Andric   assert(!Headers.count(File) && "already have a module for this header");
5900623d748SDimitry Andric 
59159d1ed5bSDimitry Andric   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
59259d1ed5bSDimitry Andric   KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
59359d1ed5bSDimitry Andric   if (H) {
59459d1ed5bSDimitry Andric     Module *Result = H.getModule();
595dff0c46cSDimitry Andric 
596dff0c46cSDimitry Andric     // Search up the module stack until we find a module with an umbrella
597dff0c46cSDimitry Andric     // directory.
598dff0c46cSDimitry Andric     Module *UmbrellaModule = Result;
599dff0c46cSDimitry Andric     while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
600dff0c46cSDimitry Andric       UmbrellaModule = UmbrellaModule->Parent;
601dff0c46cSDimitry Andric 
602dff0c46cSDimitry Andric     if (UmbrellaModule->InferSubmodules) {
60339d628a0SDimitry Andric       const FileEntry *UmbrellaModuleMap =
60439d628a0SDimitry Andric           getModuleMapFileForUniquing(UmbrellaModule);
60539d628a0SDimitry Andric 
606dff0c46cSDimitry Andric       // Infer submodules for each of the directories we found between
607dff0c46cSDimitry Andric       // the directory of the umbrella header and the directory where
608dff0c46cSDimitry Andric       // the actual header is located.
609dff0c46cSDimitry Andric       bool Explicit = UmbrellaModule->InferExplicitSubmodules;
610dff0c46cSDimitry Andric 
611dff0c46cSDimitry Andric       for (unsigned I = SkippedDirs.size(); I != 0; --I) {
612dff0c46cSDimitry Andric         // Find or create the module that corresponds to this directory name.
6133861d79fSDimitry Andric         SmallString<32> NameBuf;
6143861d79fSDimitry Andric         StringRef Name = sanitizeFilenameAsIdentifier(
61559d1ed5bSDimitry Andric             llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
61639d628a0SDimitry Andric         Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
61739d628a0SDimitry Andric                                     Explicit).first;
61839d628a0SDimitry Andric         InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
61959d1ed5bSDimitry Andric         Result->IsInferred = true;
620dff0c46cSDimitry Andric 
621dff0c46cSDimitry Andric         // Associate the module and the directory.
622dff0c46cSDimitry Andric         UmbrellaDirs[SkippedDirs[I-1]] = Result;
623dff0c46cSDimitry Andric 
624dff0c46cSDimitry Andric         // If inferred submodules export everything they import, add a
625dff0c46cSDimitry Andric         // wildcard to the set of exports.
626dff0c46cSDimitry Andric         if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
62759d1ed5bSDimitry Andric           Result->Exports.push_back(Module::ExportDecl(nullptr, true));
628dff0c46cSDimitry Andric       }
629dff0c46cSDimitry Andric 
630dff0c46cSDimitry Andric       // Infer a submodule with the same name as this header file.
6313861d79fSDimitry Andric       SmallString<32> NameBuf;
6323861d79fSDimitry Andric       StringRef Name = sanitizeFilenameAsIdentifier(
6333861d79fSDimitry Andric                          llvm::sys::path::stem(File->getName()), NameBuf);
63439d628a0SDimitry Andric       Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
63539d628a0SDimitry Andric                                   Explicit).first;
63639d628a0SDimitry Andric       InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
63759d1ed5bSDimitry Andric       Result->IsInferred = true;
638139f7f9bSDimitry Andric       Result->addTopHeader(File);
639dff0c46cSDimitry Andric 
640dff0c46cSDimitry Andric       // If inferred submodules export everything they import, add a
641dff0c46cSDimitry Andric       // wildcard to the set of exports.
642dff0c46cSDimitry Andric       if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
64359d1ed5bSDimitry Andric         Result->Exports.push_back(Module::ExportDecl(nullptr, true));
644dff0c46cSDimitry Andric     } else {
645dff0c46cSDimitry Andric       // Record each of the directories we stepped through as being part of
646dff0c46cSDimitry Andric       // the module we found, since the umbrella header covers them all.
647dff0c46cSDimitry Andric       for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
648dff0c46cSDimitry Andric         UmbrellaDirs[SkippedDirs[I]] = Result;
649dff0c46cSDimitry Andric     }
650dff0c46cSDimitry Andric 
6510623d748SDimitry Andric     KnownHeader Header(Result, NormalHeader);
6520623d748SDimitry Andric     Headers[File].push_back(Header);
6530623d748SDimitry Andric     return Header;
654dff0c46cSDimitry Andric   }
655dff0c46cSDimitry Andric 
6569a199699SDimitry Andric   return {};
657dff0c46cSDimitry Andric }
658dff0c46cSDimitry Andric 
6590623d748SDimitry Andric ArrayRef<ModuleMap::KnownHeader>
findAllModulesForHeader(const FileEntry * File) const6600623d748SDimitry Andric ModuleMap::findAllModulesForHeader(const FileEntry *File) const {
6616d97bb29SDimitry Andric   resolveHeaderDirectives(File);
6620623d748SDimitry Andric   auto It = Headers.find(File);
6630623d748SDimitry Andric   if (It == Headers.end())
6640623d748SDimitry Andric     return None;
6650623d748SDimitry Andric   return It->second;
6660623d748SDimitry Andric }
6670623d748SDimitry Andric 
isHeaderInUnavailableModule(const FileEntry * Header) const668139f7f9bSDimitry Andric bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
66959d1ed5bSDimitry Andric   return isHeaderUnavailableInModule(Header, nullptr);
67059d1ed5bSDimitry Andric }
67159d1ed5bSDimitry Andric 
67259d1ed5bSDimitry Andric bool
isHeaderUnavailableInModule(const FileEntry * Header,const Module * RequestingModule) const67359d1ed5bSDimitry Andric ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
67459d1ed5bSDimitry Andric                                        const Module *RequestingModule) const {
6756d97bb29SDimitry Andric   resolveHeaderDirectives(Header);
676139f7f9bSDimitry Andric   HeadersMap::const_iterator Known = Headers.find(Header);
677f785676fSDimitry Andric   if (Known != Headers.end()) {
678f785676fSDimitry Andric     for (SmallVectorImpl<KnownHeader>::const_iterator
679f785676fSDimitry Andric              I = Known->second.begin(),
680f785676fSDimitry Andric              E = Known->second.end();
681f785676fSDimitry Andric          I != E; ++I) {
682f1a29dd3SDimitry Andric 
683f1a29dd3SDimitry Andric       if (I->isAvailable() &&
684f1a29dd3SDimitry Andric           (!RequestingModule ||
685f1a29dd3SDimitry Andric            I->getModule()->isSubModuleOf(RequestingModule))) {
686f1a29dd3SDimitry Andric         // When no requesting module is available, the caller is looking if a
687f1a29dd3SDimitry Andric         // header is part a module by only looking into the module map. This is
688f1a29dd3SDimitry Andric         // done by warn_uncovered_module_header checks; don't consider textual
689f1a29dd3SDimitry Andric         // headers part of it in this mode, otherwise we get misleading warnings
690f1a29dd3SDimitry Andric         // that a umbrella header is not including a textual header.
691f1a29dd3SDimitry Andric         if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
692f1a29dd3SDimitry Andric           continue;
693f785676fSDimitry Andric         return false;
694f785676fSDimitry Andric       }
695f1a29dd3SDimitry Andric     }
696f785676fSDimitry Andric     return true;
697f785676fSDimitry Andric   }
698dff0c46cSDimitry Andric 
699dff0c46cSDimitry Andric   const DirectoryEntry *Dir = Header->getDir();
700139f7f9bSDimitry Andric   SmallVector<const DirectoryEntry *, 2> SkippedDirs;
701dff0c46cSDimitry Andric   StringRef DirName = Dir->getName();
702dff0c46cSDimitry Andric 
70359d1ed5bSDimitry Andric   auto IsUnavailable = [&](const Module *M) {
70459d1ed5bSDimitry Andric     return !M->isAvailable() && (!RequestingModule ||
70559d1ed5bSDimitry Andric                                  M->isSubModuleOf(RequestingModule));
70659d1ed5bSDimitry Andric   };
70759d1ed5bSDimitry Andric 
708dff0c46cSDimitry Andric   // Keep walking up the directory hierarchy, looking for a directory with
709dff0c46cSDimitry Andric   // an umbrella header.
710dff0c46cSDimitry Andric   do {
711139f7f9bSDimitry Andric     llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
712dff0c46cSDimitry Andric       = UmbrellaDirs.find(Dir);
713dff0c46cSDimitry Andric     if (KnownDir != UmbrellaDirs.end()) {
714dff0c46cSDimitry Andric       Module *Found = KnownDir->second;
71559d1ed5bSDimitry Andric       if (IsUnavailable(Found))
716dff0c46cSDimitry Andric         return true;
717dff0c46cSDimitry Andric 
718dff0c46cSDimitry Andric       // Search up the module stack until we find a module with an umbrella
719dff0c46cSDimitry Andric       // directory.
720dff0c46cSDimitry Andric       Module *UmbrellaModule = Found;
721dff0c46cSDimitry Andric       while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
722dff0c46cSDimitry Andric         UmbrellaModule = UmbrellaModule->Parent;
723dff0c46cSDimitry Andric 
724dff0c46cSDimitry Andric       if (UmbrellaModule->InferSubmodules) {
725dff0c46cSDimitry Andric         for (unsigned I = SkippedDirs.size(); I != 0; --I) {
726dff0c46cSDimitry Andric           // Find or create the module that corresponds to this directory name.
7273861d79fSDimitry Andric           SmallString<32> NameBuf;
7283861d79fSDimitry Andric           StringRef Name = sanitizeFilenameAsIdentifier(
7293861d79fSDimitry Andric                              llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
7303861d79fSDimitry Andric                              NameBuf);
731dff0c46cSDimitry Andric           Found = lookupModuleQualified(Name, Found);
732dff0c46cSDimitry Andric           if (!Found)
733dff0c46cSDimitry Andric             return false;
73459d1ed5bSDimitry Andric           if (IsUnavailable(Found))
735dff0c46cSDimitry Andric             return true;
736dff0c46cSDimitry Andric         }
737dff0c46cSDimitry Andric 
738dff0c46cSDimitry Andric         // Infer a submodule with the same name as this header file.
7393861d79fSDimitry Andric         SmallString<32> NameBuf;
7403861d79fSDimitry Andric         StringRef Name = sanitizeFilenameAsIdentifier(
7413861d79fSDimitry Andric                            llvm::sys::path::stem(Header->getName()),
7423861d79fSDimitry Andric                            NameBuf);
743dff0c46cSDimitry Andric         Found = lookupModuleQualified(Name, Found);
744dff0c46cSDimitry Andric         if (!Found)
745dff0c46cSDimitry Andric           return false;
746dff0c46cSDimitry Andric       }
747dff0c46cSDimitry Andric 
74859d1ed5bSDimitry Andric       return IsUnavailable(Found);
749dff0c46cSDimitry Andric     }
750dff0c46cSDimitry Andric 
751dff0c46cSDimitry Andric     SkippedDirs.push_back(Dir);
752dff0c46cSDimitry Andric 
753dff0c46cSDimitry Andric     // Retrieve our parent path.
754dff0c46cSDimitry Andric     DirName = llvm::sys::path::parent_path(DirName);
755dff0c46cSDimitry Andric     if (DirName.empty())
756dff0c46cSDimitry Andric       break;
757dff0c46cSDimitry Andric 
758dff0c46cSDimitry Andric     // Resolve the parent path to a directory entry.
759f785676fSDimitry Andric     Dir = SourceMgr.getFileManager().getDirectory(DirName);
760dff0c46cSDimitry Andric   } while (Dir);
761dff0c46cSDimitry Andric 
762dff0c46cSDimitry Andric   return false;
763dff0c46cSDimitry Andric }
764dff0c46cSDimitry Andric 
findModule(StringRef Name) const765139f7f9bSDimitry Andric Module *ModuleMap::findModule(StringRef Name) const {
766139f7f9bSDimitry Andric   llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
767dff0c46cSDimitry Andric   if (Known != Modules.end())
768dff0c46cSDimitry Andric     return Known->getValue();
769dff0c46cSDimitry Andric 
77059d1ed5bSDimitry Andric   return nullptr;
771dff0c46cSDimitry Andric }
772dff0c46cSDimitry Andric 
lookupModuleUnqualified(StringRef Name,Module * Context) const773139f7f9bSDimitry Andric Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
774139f7f9bSDimitry Andric                                            Module *Context) const {
775dff0c46cSDimitry Andric   for(; Context; Context = Context->Parent) {
776dff0c46cSDimitry Andric     if (Module *Sub = lookupModuleQualified(Name, Context))
777dff0c46cSDimitry Andric       return Sub;
778dff0c46cSDimitry Andric   }
779dff0c46cSDimitry Andric 
780dff0c46cSDimitry Andric   return findModule(Name);
781dff0c46cSDimitry Andric }
782dff0c46cSDimitry Andric 
lookupModuleQualified(StringRef Name,Module * Context) const783139f7f9bSDimitry Andric Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
784dff0c46cSDimitry Andric   if (!Context)
785dff0c46cSDimitry Andric     return findModule(Name);
786dff0c46cSDimitry Andric 
787dff0c46cSDimitry Andric   return Context->findSubmodule(Name);
788dff0c46cSDimitry Andric }
789dff0c46cSDimitry Andric 
findOrCreateModule(StringRef Name,Module * Parent,bool IsFramework,bool IsExplicit)79020e90f04SDimitry Andric std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
79120e90f04SDimitry Andric                                                         Module *Parent,
79220e90f04SDimitry Andric                                                         bool IsFramework,
793dff0c46cSDimitry Andric                                                         bool IsExplicit) {
794dff0c46cSDimitry Andric   // Try to find an existing module with this name.
795dff0c46cSDimitry Andric   if (Module *Sub = lookupModuleQualified(Name, Parent))
796dff0c46cSDimitry Andric     return std::make_pair(Sub, false);
797dff0c46cSDimitry Andric 
798dff0c46cSDimitry Andric   // Create a new module with this name.
79920e90f04SDimitry Andric   Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
80020e90f04SDimitry Andric                               IsExplicit, NumCreatedModules++);
801f785676fSDimitry Andric   if (!Parent) {
802e7145dcbSDimitry Andric     if (LangOpts.CurrentModule == Name)
803e7145dcbSDimitry Andric       SourceModule = Result;
804dff0c46cSDimitry Andric     Modules[Name] = Result;
8054ba319b5SDimitry Andric     ModuleScopeIDs[Result] = CurrentModuleScopeID;
806f785676fSDimitry Andric   }
807dff0c46cSDimitry Andric   return std::make_pair(Result, true);
808dff0c46cSDimitry Andric }
809dff0c46cSDimitry Andric 
createGlobalModuleForInterfaceUnit(SourceLocation Loc)8109a199699SDimitry Andric Module *ModuleMap::createGlobalModuleForInterfaceUnit(SourceLocation Loc) {
811*b5893f02SDimitry Andric   PendingSubmodules.emplace_back(
8129a199699SDimitry Andric       new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
8139a199699SDimitry Andric                  /*IsExplicit*/ true, NumCreatedModules++));
814*b5893f02SDimitry Andric   PendingSubmodules.back()->Kind = Module::GlobalModuleFragment;
815*b5893f02SDimitry Andric   return PendingSubmodules.back().get();
8169a199699SDimitry Andric }
8179a199699SDimitry Andric 
createModuleForInterfaceUnit(SourceLocation Loc,StringRef Name,Module * GlobalModule)81844290647SDimitry Andric Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
8199a199699SDimitry Andric                                                 StringRef Name,
8209a199699SDimitry Andric                                                 Module *GlobalModule) {
82144290647SDimitry Andric   assert(LangOpts.CurrentModule == Name && "module name mismatch");
82244290647SDimitry Andric   assert(!Modules[Name] && "redefining existing module");
82344290647SDimitry Andric 
82444290647SDimitry Andric   auto *Result =
82544290647SDimitry Andric       new Module(Name, Loc, nullptr, /*IsFramework*/ false,
82644290647SDimitry Andric                  /*IsExplicit*/ false, NumCreatedModules++);
82751690af2SDimitry Andric   Result->Kind = Module::ModuleInterfaceUnit;
82844290647SDimitry Andric   Modules[Name] = SourceModule = Result;
82944290647SDimitry Andric 
8309a199699SDimitry Andric   // Reparent the current global module fragment as a submodule of this module.
831*b5893f02SDimitry Andric   for (auto &Submodule : PendingSubmodules) {
832*b5893f02SDimitry Andric     Submodule->setParent(Result);
833*b5893f02SDimitry Andric     Submodule.release(); // now owned by parent
834*b5893f02SDimitry Andric   }
835*b5893f02SDimitry Andric   PendingSubmodules.clear();
8369a199699SDimitry Andric 
83744290647SDimitry Andric   // Mark the main source file as being within the newly-created module so that
83844290647SDimitry Andric   // declarations and macros are properly visibility-restricted to it.
83944290647SDimitry Andric   auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
84044290647SDimitry Andric   assert(MainFile && "no input file for module interface");
84144290647SDimitry Andric   Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader));
84244290647SDimitry Andric 
84344290647SDimitry Andric   return Result;
84444290647SDimitry Andric }
84544290647SDimitry Andric 
createHeaderModule(StringRef Name,ArrayRef<Module::Header> Headers)846*b5893f02SDimitry Andric Module *ModuleMap::createHeaderModule(StringRef Name,
847*b5893f02SDimitry Andric                                       ArrayRef<Module::Header> Headers) {
848*b5893f02SDimitry Andric   assert(LangOpts.CurrentModule == Name && "module name mismatch");
849*b5893f02SDimitry Andric   assert(!Modules[Name] && "redefining existing module");
850*b5893f02SDimitry Andric 
851*b5893f02SDimitry Andric   auto *Result =
852*b5893f02SDimitry Andric       new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false,
853*b5893f02SDimitry Andric                  /*IsExplicit*/ false, NumCreatedModules++);
854*b5893f02SDimitry Andric   Result->Kind = Module::ModuleInterfaceUnit;
855*b5893f02SDimitry Andric   Modules[Name] = SourceModule = Result;
856*b5893f02SDimitry Andric 
857*b5893f02SDimitry Andric   for (const Module::Header &H : Headers) {
858*b5893f02SDimitry Andric     auto *M = new Module(H.NameAsWritten, SourceLocation(), Result,
859*b5893f02SDimitry Andric                          /*IsFramework*/ false,
860*b5893f02SDimitry Andric                          /*IsExplicit*/ true, NumCreatedModules++);
861*b5893f02SDimitry Andric     // Header modules are implicitly 'export *'.
862*b5893f02SDimitry Andric     M->Exports.push_back(Module::ExportDecl(nullptr, true));
863*b5893f02SDimitry Andric     addHeader(M, H, NormalHeader);
864*b5893f02SDimitry Andric   }
865*b5893f02SDimitry Andric 
866*b5893f02SDimitry Andric   return Result;
867*b5893f02SDimitry Andric }
868*b5893f02SDimitry Andric 
8694ba319b5SDimitry Andric /// For a framework module, infer the framework against which we
870139f7f9bSDimitry Andric /// should link.
inferFrameworkLink(Module * Mod,const DirectoryEntry * FrameworkDir,FileManager & FileMgr)871139f7f9bSDimitry Andric static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
872139f7f9bSDimitry Andric                                FileManager &FileMgr) {
873139f7f9bSDimitry Andric   assert(Mod->IsFramework && "Can only infer linking for framework modules");
874139f7f9bSDimitry Andric   assert(!Mod->isSubFramework() &&
875139f7f9bSDimitry Andric          "Can only infer linking for top-level frameworks");
876139f7f9bSDimitry Andric 
877139f7f9bSDimitry Andric   SmallString<128> LibName;
878139f7f9bSDimitry Andric   LibName += FrameworkDir->getName();
879139f7f9bSDimitry Andric   llvm::sys::path::append(LibName, Mod->Name);
8800623d748SDimitry Andric 
8810623d748SDimitry Andric   // The library name of a framework has more than one possible extension since
8820623d748SDimitry Andric   // the introduction of the text-based dynamic library format. We need to check
8830623d748SDimitry Andric   // for both before we give up.
88444290647SDimitry Andric   for (const char *extension : {"", ".tbd"}) {
8850623d748SDimitry Andric     llvm::sys::path::replace_extension(LibName, extension);
886139f7f9bSDimitry Andric     if (FileMgr.getFile(LibName)) {
887139f7f9bSDimitry Andric       Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
888139f7f9bSDimitry Andric                                                        /*IsFramework=*/true));
8890623d748SDimitry Andric       return;
8900623d748SDimitry Andric     }
891139f7f9bSDimitry Andric   }
892139f7f9bSDimitry Andric }
893139f7f9bSDimitry Andric 
inferFrameworkModule(const DirectoryEntry * FrameworkDir,bool IsSystem,Module * Parent)8943dac3a9bSDimitry Andric Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
8953dac3a9bSDimitry Andric                                         bool IsSystem, Module *Parent) {
89639d628a0SDimitry Andric   Attributes Attrs;
89739d628a0SDimitry Andric   Attrs.IsSystem = IsSystem;
8983dac3a9bSDimitry Andric   return inferFrameworkModule(FrameworkDir, Attrs, Parent);
89939d628a0SDimitry Andric }
90039d628a0SDimitry Andric 
inferFrameworkModule(const DirectoryEntry * FrameworkDir,Attributes Attrs,Module * Parent)9013dac3a9bSDimitry Andric Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
90239d628a0SDimitry Andric                                         Attributes Attrs, Module *Parent) {
9033dac3a9bSDimitry Andric   // Note: as an egregious but useful hack we use the real path here, because
9043dac3a9bSDimitry Andric   // we might be looking at an embedded framework that symlinks out to a
9053dac3a9bSDimitry Andric   // top-level framework, and we need to infer as if we were naming the
9063dac3a9bSDimitry Andric   // top-level framework.
9073dac3a9bSDimitry Andric   StringRef FrameworkDirName =
9083dac3a9bSDimitry Andric       SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
9093dac3a9bSDimitry Andric 
9103dac3a9bSDimitry Andric   // In case this is a case-insensitive filesystem, use the canonical
9113dac3a9bSDimitry Andric   // directory name as the ModuleName, since modules are case-sensitive.
9123dac3a9bSDimitry Andric   // FIXME: we should be able to give a fix-it hint for the correct spelling.
9133dac3a9bSDimitry Andric   SmallString<32> ModuleNameStorage;
9143dac3a9bSDimitry Andric   StringRef ModuleName = sanitizeFilenameAsIdentifier(
9153dac3a9bSDimitry Andric       llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
91639d628a0SDimitry Andric 
917dff0c46cSDimitry Andric   // Check whether we've already found this module.
918dff0c46cSDimitry Andric   if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
919dff0c46cSDimitry Andric     return Mod;
920dff0c46cSDimitry Andric 
921f785676fSDimitry Andric   FileManager &FileMgr = SourceMgr.getFileManager();
922dff0c46cSDimitry Andric 
9233861d79fSDimitry Andric   // If the framework has a parent path from which we're allowed to infer
9243861d79fSDimitry Andric   // a framework module, do so.
92559d1ed5bSDimitry Andric   const FileEntry *ModuleMapFile = nullptr;
9263861d79fSDimitry Andric   if (!Parent) {
927139f7f9bSDimitry Andric     // Determine whether we're allowed to infer a module map.
9283861d79fSDimitry Andric     bool canInfer = false;
929139f7f9bSDimitry Andric     if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
9303861d79fSDimitry Andric       // Figure out the parent path.
931139f7f9bSDimitry Andric       StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
9323861d79fSDimitry Andric       if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) {
9333861d79fSDimitry Andric         // Check whether we have already looked into the parent directory
9343861d79fSDimitry Andric         // for a module map.
935139f7f9bSDimitry Andric         llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
9363861d79fSDimitry Andric           inferred = InferredDirectories.find(ParentDir);
9373861d79fSDimitry Andric         if (inferred == InferredDirectories.end()) {
9383861d79fSDimitry Andric           // We haven't looked here before. Load a module map, if there is
9393861d79fSDimitry Andric           // one.
94059d1ed5bSDimitry Andric           bool IsFrameworkDir = Parent.endswith(".framework");
94159d1ed5bSDimitry Andric           if (const FileEntry *ModMapFile =
94259d1ed5bSDimitry Andric                 HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) {
94339d628a0SDimitry Andric             parseModuleMapFile(ModMapFile, Attrs.IsSystem, ParentDir);
9443861d79fSDimitry Andric             inferred = InferredDirectories.find(ParentDir);
9453861d79fSDimitry Andric           }
9463861d79fSDimitry Andric 
9473861d79fSDimitry Andric           if (inferred == InferredDirectories.end())
9483861d79fSDimitry Andric             inferred = InferredDirectories.insert(
9493861d79fSDimitry Andric                          std::make_pair(ParentDir, InferredDirectory())).first;
9503861d79fSDimitry Andric         }
9513861d79fSDimitry Andric 
9523861d79fSDimitry Andric         if (inferred->second.InferModules) {
9533861d79fSDimitry Andric           // We're allowed to infer for this directory, but make sure it's okay
9543861d79fSDimitry Andric           // to infer this particular module.
955139f7f9bSDimitry Andric           StringRef Name = llvm::sys::path::stem(FrameworkDirName);
9563861d79fSDimitry Andric           canInfer = std::find(inferred->second.ExcludedModules.begin(),
9573861d79fSDimitry Andric                                inferred->second.ExcludedModules.end(),
9583861d79fSDimitry Andric                                Name) == inferred->second.ExcludedModules.end();
9593861d79fSDimitry Andric 
96039d628a0SDimitry Andric           Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
96139d628a0SDimitry Andric           Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
96239d628a0SDimitry Andric           Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
96344290647SDimitry Andric           Attrs.NoUndeclaredIncludes |=
96444290647SDimitry Andric               inferred->second.Attrs.NoUndeclaredIncludes;
96559d1ed5bSDimitry Andric           ModuleMapFile = inferred->second.ModuleMapFile;
9663861d79fSDimitry Andric         }
9673861d79fSDimitry Andric       }
9683861d79fSDimitry Andric     }
9693861d79fSDimitry Andric 
9703861d79fSDimitry Andric     // If we're not allowed to infer a framework module, don't.
9713861d79fSDimitry Andric     if (!canInfer)
97259d1ed5bSDimitry Andric       return nullptr;
97359d1ed5bSDimitry Andric   } else
97439d628a0SDimitry Andric     ModuleMapFile = getModuleMapFileForUniquing(Parent);
9753861d79fSDimitry Andric 
9763861d79fSDimitry Andric 
977dff0c46cSDimitry Andric   // Look for an umbrella header.
978dff0c46cSDimitry Andric   SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
979f785676fSDimitry Andric   llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
980dff0c46cSDimitry Andric   const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
981dff0c46cSDimitry Andric 
982dff0c46cSDimitry Andric   // FIXME: If there's no umbrella header, we could probably scan the
983dff0c46cSDimitry Andric   // framework to load *everything*. But, it's not clear that this is a good
984dff0c46cSDimitry Andric   // idea.
985dff0c46cSDimitry Andric   if (!UmbrellaHeader)
98659d1ed5bSDimitry Andric     return nullptr;
987dff0c46cSDimitry Andric 
98839d628a0SDimitry Andric   Module *Result = new Module(ModuleName, SourceLocation(), Parent,
98933956c43SDimitry Andric                               /*IsFramework=*/true, /*IsExplicit=*/false,
99033956c43SDimitry Andric                               NumCreatedModules++);
99139d628a0SDimitry Andric   InferredModuleAllowedBy[Result] = ModuleMapFile;
99239d628a0SDimitry Andric   Result->IsInferred = true;
993e7145dcbSDimitry Andric   if (!Parent) {
994e7145dcbSDimitry Andric     if (LangOpts.CurrentModule == ModuleName)
995f785676fSDimitry Andric       SourceModule = Result;
996e7145dcbSDimitry Andric     Modules[ModuleName] = Result;
9974ba319b5SDimitry Andric     ModuleScopeIDs[Result] = CurrentModuleScopeID;
998f785676fSDimitry Andric   }
99939d628a0SDimitry Andric 
100039d628a0SDimitry Andric   Result->IsSystem |= Attrs.IsSystem;
100139d628a0SDimitry Andric   Result->IsExternC |= Attrs.IsExternC;
100239d628a0SDimitry Andric   Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
100344290647SDimitry Andric   Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
100433956c43SDimitry Andric   Result->Directory = FrameworkDir;
1005dff0c46cSDimitry Andric 
1006dff0c46cSDimitry Andric   // umbrella header "umbrella-header-name"
100733956c43SDimitry Andric   //
100833956c43SDimitry Andric   // The "Headers/" component of the name is implied because this is
100933956c43SDimitry Andric   // a framework module.
101033956c43SDimitry Andric   setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h");
1011dff0c46cSDimitry Andric 
1012dff0c46cSDimitry Andric   // export *
101359d1ed5bSDimitry Andric   Result->Exports.push_back(Module::ExportDecl(nullptr, true));
1014dff0c46cSDimitry Andric 
1015dff0c46cSDimitry Andric   // module * { export * }
1016dff0c46cSDimitry Andric   Result->InferSubmodules = true;
1017dff0c46cSDimitry Andric   Result->InferExportWildcard = true;
1018dff0c46cSDimitry Andric 
1019dff0c46cSDimitry Andric   // Look for subframeworks.
102059d1ed5bSDimitry Andric   std::error_code EC;
1021dff0c46cSDimitry Andric   SmallString<128> SubframeworksDirName
1022dff0c46cSDimitry Andric     = StringRef(FrameworkDir->getName());
1023dff0c46cSDimitry Andric   llvm::sys::path::append(SubframeworksDirName, "Frameworks");
1024f785676fSDimitry Andric   llvm::sys::path::native(SubframeworksDirName);
1025*b5893f02SDimitry Andric   llvm::vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem();
1026*b5893f02SDimitry Andric   for (llvm::vfs::directory_iterator
1027*b5893f02SDimitry Andric            Dir = FS.dir_begin(SubframeworksDirName, EC),
1028e7145dcbSDimitry Andric            DirEnd;
1029dff0c46cSDimitry Andric        Dir != DirEnd && !EC; Dir.increment(EC)) {
1030*b5893f02SDimitry Andric     if (!StringRef(Dir->path()).endswith(".framework"))
1031dff0c46cSDimitry Andric       continue;
1032dff0c46cSDimitry Andric 
1033e7145dcbSDimitry Andric     if (const DirectoryEntry *SubframeworkDir =
1034*b5893f02SDimitry Andric             FileMgr.getDirectory(Dir->path())) {
10353861d79fSDimitry Andric       // Note: as an egregious but useful hack, we use the real path here and
10363861d79fSDimitry Andric       // check whether it is actually a subdirectory of the parent directory.
10373861d79fSDimitry Andric       // This will not be the case if the 'subframework' is actually a symlink
10383861d79fSDimitry Andric       // out to a top-level framework.
1039139f7f9bSDimitry Andric       StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir);
10403861d79fSDimitry Andric       bool FoundParent = false;
10413861d79fSDimitry Andric       do {
10423861d79fSDimitry Andric         // Get the parent directory name.
10433861d79fSDimitry Andric         SubframeworkDirName
10443861d79fSDimitry Andric           = llvm::sys::path::parent_path(SubframeworkDirName);
10453861d79fSDimitry Andric         if (SubframeworkDirName.empty())
10463861d79fSDimitry Andric           break;
10473861d79fSDimitry Andric 
10483861d79fSDimitry Andric         if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) {
10493861d79fSDimitry Andric           FoundParent = true;
10503861d79fSDimitry Andric           break;
10513861d79fSDimitry Andric         }
10523861d79fSDimitry Andric       } while (true);
10533861d79fSDimitry Andric 
10543861d79fSDimitry Andric       if (!FoundParent)
10553861d79fSDimitry Andric         continue;
10563861d79fSDimitry Andric 
1057dff0c46cSDimitry Andric       // FIXME: Do we want to warn about subframeworks without umbrella headers?
10583dac3a9bSDimitry Andric       inferFrameworkModule(SubframeworkDir, Attrs, Result);
1059dff0c46cSDimitry Andric     }
1060dff0c46cSDimitry Andric   }
1061dff0c46cSDimitry Andric 
1062139f7f9bSDimitry Andric   // If the module is a top-level framework, automatically link against the
1063139f7f9bSDimitry Andric   // framework.
1064139f7f9bSDimitry Andric   if (!Result->isSubFramework()) {
1065139f7f9bSDimitry Andric     inferFrameworkLink(Result, FrameworkDir, FileMgr);
1066139f7f9bSDimitry Andric   }
1067139f7f9bSDimitry Andric 
1068dff0c46cSDimitry Andric   return Result;
1069dff0c46cSDimitry Andric }
1070dff0c46cSDimitry Andric 
createShadowedModule(StringRef Name,bool IsFramework,Module * ShadowingModule)10714ba319b5SDimitry Andric Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
10724ba319b5SDimitry Andric                                         Module *ShadowingModule) {
10734ba319b5SDimitry Andric 
10744ba319b5SDimitry Andric   // Create a new module with this name.
10754ba319b5SDimitry Andric   Module *Result =
10764ba319b5SDimitry Andric       new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
10774ba319b5SDimitry Andric                  /*IsExplicit=*/false, NumCreatedModules++);
10784ba319b5SDimitry Andric   Result->ShadowingModule = ShadowingModule;
10794ba319b5SDimitry Andric   Result->IsAvailable = false;
10804ba319b5SDimitry Andric   ModuleScopeIDs[Result] = CurrentModuleScopeID;
10814ba319b5SDimitry Andric   ShadowModules.push_back(Result);
10824ba319b5SDimitry Andric 
10834ba319b5SDimitry Andric   return Result;
10844ba319b5SDimitry Andric }
10854ba319b5SDimitry Andric 
setUmbrellaHeader(Module * Mod,const FileEntry * UmbrellaHeader,Twine NameAsWritten)108633956c43SDimitry Andric void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader,
108733956c43SDimitry Andric                                   Twine NameAsWritten) {
1088f785676fSDimitry Andric   Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
1089dff0c46cSDimitry Andric   Mod->Umbrella = UmbrellaHeader;
109033956c43SDimitry Andric   Mod->UmbrellaAsWritten = NameAsWritten.str();
1091dff0c46cSDimitry Andric   UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
1092e7145dcbSDimitry Andric 
1093e7145dcbSDimitry Andric   // Notify callbacks that we just added a new header.
1094e7145dcbSDimitry Andric   for (const auto &Cb : Callbacks)
1095e7145dcbSDimitry Andric     Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
1096dff0c46cSDimitry Andric }
1097dff0c46cSDimitry Andric 
setUmbrellaDir(Module * Mod,const DirectoryEntry * UmbrellaDir,Twine NameAsWritten)109833956c43SDimitry Andric void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
109933956c43SDimitry Andric                                Twine NameAsWritten) {
1100dff0c46cSDimitry Andric   Mod->Umbrella = UmbrellaDir;
110133956c43SDimitry Andric   Mod->UmbrellaAsWritten = NameAsWritten.str();
1102dff0c46cSDimitry Andric   UmbrellaDirs[UmbrellaDir] = Mod;
1103dff0c46cSDimitry Andric }
1104dff0c46cSDimitry Andric 
addUnresolvedHeader(Module * Mod,Module::UnresolvedHeaderDirective Header,bool & NeedsFramework)11056d97bb29SDimitry Andric void ModuleMap::addUnresolvedHeader(Module *Mod,
11064ba319b5SDimitry Andric                                     Module::UnresolvedHeaderDirective Header,
11074ba319b5SDimitry Andric                                     bool &NeedsFramework) {
11086d97bb29SDimitry Andric   // If there is a builtin counterpart to this file, add it now so it can
11096d97bb29SDimitry Andric   // wrap the system header.
11106d97bb29SDimitry Andric   if (resolveAsBuiltinHeader(Mod, Header)) {
11116d97bb29SDimitry Andric     // If we have both a builtin and system version of the file, the
11126d97bb29SDimitry Andric     // builtin version may want to inject macros into the system header, so
11136d97bb29SDimitry Andric     // force the system header to be treated as a textual header in this
11146d97bb29SDimitry Andric     // case.
11156d97bb29SDimitry Andric     Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
11166d97bb29SDimitry Andric         headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
11176d97bb29SDimitry Andric     Header.HasBuiltinHeader = true;
1118139f7f9bSDimitry Andric   }
11196d97bb29SDimitry Andric 
11206d97bb29SDimitry Andric   // If possible, don't stat the header until we need to. This requires the
11216d97bb29SDimitry Andric   // user to have provided us with some stat information about the file.
11226d97bb29SDimitry Andric   // FIXME: Add support for lazily stat'ing umbrella headers and excluded
11236d97bb29SDimitry Andric   // headers.
11246d97bb29SDimitry Andric   if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
11256d97bb29SDimitry Andric       Header.Kind != Module::HK_Excluded) {
11266d97bb29SDimitry Andric     // We expect more variation in mtime than size, so if we're given both,
11276d97bb29SDimitry Andric     // use the mtime as the key.
11286d97bb29SDimitry Andric     if (Header.ModTime)
11296d97bb29SDimitry Andric       LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
11306d97bb29SDimitry Andric     else
11316d97bb29SDimitry Andric       LazyHeadersBySize[*Header.Size].push_back(Mod);
11326d97bb29SDimitry Andric     Mod->UnresolvedHeaders.push_back(Header);
11336d97bb29SDimitry Andric     return;
11346d97bb29SDimitry Andric   }
11356d97bb29SDimitry Andric 
11366d97bb29SDimitry Andric   // We don't have stat information or can't defer looking this file up.
11376d97bb29SDimitry Andric   // Perform the lookup now.
11384ba319b5SDimitry Andric   resolveHeader(Mod, Header, NeedsFramework);
11396d97bb29SDimitry Andric }
11406d97bb29SDimitry Andric 
resolveHeaderDirectives(const FileEntry * File) const11416d97bb29SDimitry Andric void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
11426d97bb29SDimitry Andric   auto BySize = LazyHeadersBySize.find(File->getSize());
11436d97bb29SDimitry Andric   if (BySize != LazyHeadersBySize.end()) {
11446d97bb29SDimitry Andric     for (auto *M : BySize->second)
11456d97bb29SDimitry Andric       resolveHeaderDirectives(M);
11466d97bb29SDimitry Andric     LazyHeadersBySize.erase(BySize);
11476d97bb29SDimitry Andric   }
11486d97bb29SDimitry Andric 
11496d97bb29SDimitry Andric   auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
11506d97bb29SDimitry Andric   if (ByModTime != LazyHeadersByModTime.end()) {
11516d97bb29SDimitry Andric     for (auto *M : ByModTime->second)
11526d97bb29SDimitry Andric       resolveHeaderDirectives(M);
11536d97bb29SDimitry Andric     LazyHeadersByModTime.erase(ByModTime);
11546d97bb29SDimitry Andric   }
11556d97bb29SDimitry Andric }
11566d97bb29SDimitry Andric 
resolveHeaderDirectives(Module * Mod) const11576d97bb29SDimitry Andric void ModuleMap::resolveHeaderDirectives(Module *Mod) const {
11584ba319b5SDimitry Andric   bool NeedsFramework = false;
11596d97bb29SDimitry Andric   for (auto &Header : Mod->UnresolvedHeaders)
11606d97bb29SDimitry Andric     // This operation is logically const; we're just changing how we represent
11616d97bb29SDimitry Andric     // the header information for this file.
11624ba319b5SDimitry Andric     const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework);
11636d97bb29SDimitry Andric   Mod->UnresolvedHeaders.clear();
116439d628a0SDimitry Andric }
116539d628a0SDimitry Andric 
addHeader(Module * Mod,Module::Header Header,ModuleHeaderRole Role,bool Imported)116639d628a0SDimitry Andric void ModuleMap::addHeader(Module *Mod, Module::Header Header,
11670623d748SDimitry Andric                           ModuleHeaderRole Role, bool Imported) {
11680623d748SDimitry Andric   KnownHeader KH(Mod, Role);
11690623d748SDimitry Andric 
11700623d748SDimitry Andric   // Only add each header to the headers list once.
11710623d748SDimitry Andric   // FIXME: Should we diagnose if a header is listed twice in the
11720623d748SDimitry Andric   // same module definition?
11730623d748SDimitry Andric   auto &HeaderList = Headers[Header.Entry];
11740623d748SDimitry Andric   for (auto H : HeaderList)
11750623d748SDimitry Andric     if (H == KH)
11760623d748SDimitry Andric       return;
11770623d748SDimitry Andric 
11780623d748SDimitry Andric   HeaderList.push_back(KH);
117944290647SDimitry Andric   Mod->Headers[headerRoleToKind(Role)].push_back(Header);
11800623d748SDimitry Andric 
1181e7145dcbSDimitry Andric   bool isCompilingModuleHeader =
118244290647SDimitry Andric       LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
11830623d748SDimitry Andric   if (!Imported || isCompilingModuleHeader) {
11840623d748SDimitry Andric     // When we import HeaderFileInfo, the external source is expected to
11850623d748SDimitry Andric     // set the isModuleHeader flag itself.
118639d628a0SDimitry Andric     HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
118739d628a0SDimitry Andric                                     isCompilingModuleHeader);
118839d628a0SDimitry Andric   }
1189e7145dcbSDimitry Andric 
1190e7145dcbSDimitry Andric   // Notify callbacks that we just added a new header.
1191e7145dcbSDimitry Andric   for (const auto &Cb : Callbacks)
1192e7145dcbSDimitry Andric     Cb->moduleMapAddHeader(Header.Entry->getName());
119339d628a0SDimitry Andric }
119439d628a0SDimitry Andric 
excludeHeader(Module * Mod,Module::Header Header)119539d628a0SDimitry Andric void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
119639d628a0SDimitry Andric   // Add this as a known header so we won't implicitly add it to any
119739d628a0SDimitry Andric   // umbrella directory module.
119839d628a0SDimitry Andric   // FIXME: Should we only exclude it from umbrella modules within the
119939d628a0SDimitry Andric   // specified module?
120039d628a0SDimitry Andric   (void) Headers[Header.Entry];
120139d628a0SDimitry Andric 
120239d628a0SDimitry Andric   Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
1203dff0c46cSDimitry Andric }
1204dff0c46cSDimitry Andric 
1205dff0c46cSDimitry Andric const FileEntry *
getContainingModuleMapFile(const Module * Module) const120639d628a0SDimitry Andric ModuleMap::getContainingModuleMapFile(const Module *Module) const {
1207f785676fSDimitry Andric   if (Module->DefinitionLoc.isInvalid())
120859d1ed5bSDimitry Andric     return nullptr;
1209dff0c46cSDimitry Andric 
1210f785676fSDimitry Andric   return SourceMgr.getFileEntryForID(
1211f785676fSDimitry Andric            SourceMgr.getFileID(Module->DefinitionLoc));
1212dff0c46cSDimitry Andric }
1213dff0c46cSDimitry Andric 
getModuleMapFileForUniquing(const Module * M) const121439d628a0SDimitry Andric const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
121539d628a0SDimitry Andric   if (M->IsInferred) {
121639d628a0SDimitry Andric     assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
121739d628a0SDimitry Andric     return InferredModuleAllowedBy.find(M)->second;
121839d628a0SDimitry Andric   }
121939d628a0SDimitry Andric   return getContainingModuleMapFile(M);
122039d628a0SDimitry Andric }
122139d628a0SDimitry Andric 
setInferredModuleAllowedBy(Module * M,const FileEntry * ModMap)122239d628a0SDimitry Andric void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
122339d628a0SDimitry Andric   assert(M->IsInferred && "module not inferred");
122439d628a0SDimitry Andric   InferredModuleAllowedBy[M] = ModMap;
122539d628a0SDimitry Andric }
122639d628a0SDimitry Andric 
dump()1227e7145dcbSDimitry Andric LLVM_DUMP_METHOD void ModuleMap::dump() {
1228dff0c46cSDimitry Andric   llvm::errs() << "Modules:";
1229dff0c46cSDimitry Andric   for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1230dff0c46cSDimitry Andric                                         MEnd = Modules.end();
1231dff0c46cSDimitry Andric        M != MEnd; ++M)
1232dff0c46cSDimitry Andric     M->getValue()->print(llvm::errs(), 2);
1233dff0c46cSDimitry Andric 
1234dff0c46cSDimitry Andric   llvm::errs() << "Headers:";
12353861d79fSDimitry Andric   for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1236dff0c46cSDimitry Andric        H != HEnd; ++H) {
1237f785676fSDimitry Andric     llvm::errs() << "  \"" << H->first->getName() << "\" -> ";
1238f785676fSDimitry Andric     for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
1239f785676fSDimitry Andric                                                       E = H->second.end();
1240f785676fSDimitry Andric          I != E; ++I) {
1241f785676fSDimitry Andric       if (I != H->second.begin())
1242f785676fSDimitry Andric         llvm::errs() << ",";
1243f785676fSDimitry Andric       llvm::errs() << I->getModule()->getFullModuleName();
1244f785676fSDimitry Andric     }
1245f785676fSDimitry Andric     llvm::errs() << "\n";
1246dff0c46cSDimitry Andric   }
1247dff0c46cSDimitry Andric }
1248dff0c46cSDimitry Andric 
resolveExports(Module * Mod,bool Complain)1249dff0c46cSDimitry Andric bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
125033956c43SDimitry Andric   auto Unresolved = std::move(Mod->UnresolvedExports);
125133956c43SDimitry Andric   Mod->UnresolvedExports.clear();
125233956c43SDimitry Andric   for (auto &UE : Unresolved) {
125333956c43SDimitry Andric     Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
1254dff0c46cSDimitry Andric     if (Export.getPointer() || Export.getInt())
1255dff0c46cSDimitry Andric       Mod->Exports.push_back(Export);
1256dff0c46cSDimitry Andric     else
125733956c43SDimitry Andric       Mod->UnresolvedExports.push_back(UE);
1258dff0c46cSDimitry Andric   }
125933956c43SDimitry Andric   return !Mod->UnresolvedExports.empty();
1260dff0c46cSDimitry Andric }
1261dff0c46cSDimitry Andric 
resolveUses(Module * Mod,bool Complain)1262f785676fSDimitry Andric bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
126333956c43SDimitry Andric   auto Unresolved = std::move(Mod->UnresolvedDirectUses);
126433956c43SDimitry Andric   Mod->UnresolvedDirectUses.clear();
126533956c43SDimitry Andric   for (auto &UDU : Unresolved) {
126633956c43SDimitry Andric     Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
1267f785676fSDimitry Andric     if (DirectUse)
1268f785676fSDimitry Andric       Mod->DirectUses.push_back(DirectUse);
1269f785676fSDimitry Andric     else
127033956c43SDimitry Andric       Mod->UnresolvedDirectUses.push_back(UDU);
1271f785676fSDimitry Andric   }
127233956c43SDimitry Andric   return !Mod->UnresolvedDirectUses.empty();
1273f785676fSDimitry Andric }
1274f785676fSDimitry Andric 
resolveConflicts(Module * Mod,bool Complain)1275139f7f9bSDimitry Andric bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
127633956c43SDimitry Andric   auto Unresolved = std::move(Mod->UnresolvedConflicts);
127733956c43SDimitry Andric   Mod->UnresolvedConflicts.clear();
127833956c43SDimitry Andric   for (auto &UC : Unresolved) {
127933956c43SDimitry Andric     if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1280139f7f9bSDimitry Andric       Module::Conflict Conflict;
1281139f7f9bSDimitry Andric       Conflict.Other = OtherMod;
128233956c43SDimitry Andric       Conflict.Message = UC.Message;
1283139f7f9bSDimitry Andric       Mod->Conflicts.push_back(Conflict);
128433956c43SDimitry Andric     } else
128533956c43SDimitry Andric       Mod->UnresolvedConflicts.push_back(UC);
1286139f7f9bSDimitry Andric   }
128733956c43SDimitry Andric   return !Mod->UnresolvedConflicts.empty();
1288139f7f9bSDimitry Andric }
1289139f7f9bSDimitry Andric 
1290dff0c46cSDimitry Andric //----------------------------------------------------------------------------//
1291dff0c46cSDimitry Andric // Module map file parser
1292dff0c46cSDimitry Andric //----------------------------------------------------------------------------//
1293dff0c46cSDimitry Andric 
1294dff0c46cSDimitry Andric namespace clang {
12959a199699SDimitry Andric 
12964ba319b5SDimitry Andric   /// A token in a module map file.
1297dff0c46cSDimitry Andric   struct MMToken {
1298dff0c46cSDimitry Andric     enum TokenKind {
1299dff0c46cSDimitry Andric       Comma,
1300139f7f9bSDimitry Andric       ConfigMacros,
1301139f7f9bSDimitry Andric       Conflict,
1302dff0c46cSDimitry Andric       EndOfFile,
1303dff0c46cSDimitry Andric       HeaderKeyword,
1304dff0c46cSDimitry Andric       Identifier,
1305f785676fSDimitry Andric       Exclaim,
13063861d79fSDimitry Andric       ExcludeKeyword,
1307dff0c46cSDimitry Andric       ExplicitKeyword,
1308dff0c46cSDimitry Andric       ExportKeyword,
13099a199699SDimitry Andric       ExportAsKeyword,
1310f785676fSDimitry Andric       ExternKeyword,
1311dff0c46cSDimitry Andric       FrameworkKeyword,
1312139f7f9bSDimitry Andric       LinkKeyword,
1313dff0c46cSDimitry Andric       ModuleKeyword,
1314dff0c46cSDimitry Andric       Period,
1315f785676fSDimitry Andric       PrivateKeyword,
1316dff0c46cSDimitry Andric       UmbrellaKeyword,
1317f785676fSDimitry Andric       UseKeyword,
1318dff0c46cSDimitry Andric       RequiresKeyword,
1319dff0c46cSDimitry Andric       Star,
1320dff0c46cSDimitry Andric       StringLiteral,
13216d97bb29SDimitry Andric       IntegerLiteral,
132239d628a0SDimitry Andric       TextualKeyword,
1323dff0c46cSDimitry Andric       LBrace,
1324dff0c46cSDimitry Andric       RBrace,
1325dff0c46cSDimitry Andric       LSquare,
1326dff0c46cSDimitry Andric       RSquare
1327dff0c46cSDimitry Andric     } Kind;
1328dff0c46cSDimitry Andric 
1329dff0c46cSDimitry Andric     unsigned Location;
1330dff0c46cSDimitry Andric     unsigned StringLength;
13316d97bb29SDimitry Andric     union {
13326d97bb29SDimitry Andric       // If Kind != IntegerLiteral.
1333dff0c46cSDimitry Andric       const char *StringData;
13349a199699SDimitry Andric 
13356d97bb29SDimitry Andric       // If Kind == IntegerLiteral.
13366d97bb29SDimitry Andric       uint64_t IntegerValue;
13376d97bb29SDimitry Andric     };
1338dff0c46cSDimitry Andric 
clearclang::MMToken1339dff0c46cSDimitry Andric     void clear() {
1340dff0c46cSDimitry Andric       Kind = EndOfFile;
1341dff0c46cSDimitry Andric       Location = 0;
1342dff0c46cSDimitry Andric       StringLength = 0;
134359d1ed5bSDimitry Andric       StringData = nullptr;
1344dff0c46cSDimitry Andric     }
1345dff0c46cSDimitry Andric 
isclang::MMToken1346dff0c46cSDimitry Andric     bool is(TokenKind K) const { return Kind == K; }
1347dff0c46cSDimitry Andric 
getLocationclang::MMToken1348dff0c46cSDimitry Andric     SourceLocation getLocation() const {
1349dff0c46cSDimitry Andric       return SourceLocation::getFromRawEncoding(Location);
1350dff0c46cSDimitry Andric     }
1351dff0c46cSDimitry Andric 
getIntegerclang::MMToken13526d97bb29SDimitry Andric     uint64_t getInteger() const {
13536d97bb29SDimitry Andric       return Kind == IntegerLiteral ? IntegerValue : 0;
13546d97bb29SDimitry Andric     }
13556d97bb29SDimitry Andric 
getStringclang::MMToken1356dff0c46cSDimitry Andric     StringRef getString() const {
13576d97bb29SDimitry Andric       return Kind == IntegerLiteral ? StringRef()
13586d97bb29SDimitry Andric                                     : StringRef(StringData, StringLength);
1359dff0c46cSDimitry Andric     }
1360dff0c46cSDimitry Andric   };
1361dff0c46cSDimitry Andric 
1362dff0c46cSDimitry Andric   class ModuleMapParser {
1363dff0c46cSDimitry Andric     Lexer &L;
1364dff0c46cSDimitry Andric     SourceManager &SourceMgr;
13653861d79fSDimitry Andric 
13664ba319b5SDimitry Andric     /// Default target information, used only for string literal
13673861d79fSDimitry Andric     /// parsing.
13683861d79fSDimitry Andric     const TargetInfo *Target;
13693861d79fSDimitry Andric 
1370dff0c46cSDimitry Andric     DiagnosticsEngine &Diags;
1371dff0c46cSDimitry Andric     ModuleMap &Map;
1372dff0c46cSDimitry Andric 
13734ba319b5SDimitry Andric     /// The current module map file.
137459d1ed5bSDimitry Andric     const FileEntry *ModuleMapFile;
137559d1ed5bSDimitry Andric 
13764ba319b5SDimitry Andric     /// Source location of most recent parsed module declaration
13774ba319b5SDimitry Andric     SourceLocation CurrModuleDeclLoc;
13784ba319b5SDimitry Andric 
13794ba319b5SDimitry Andric     /// The directory that file names in this module map file should
138039d628a0SDimitry Andric     /// be resolved relative to.
1381dff0c46cSDimitry Andric     const DirectoryEntry *Directory;
1382dff0c46cSDimitry Andric 
13834ba319b5SDimitry Andric     /// Whether this module map is in a system header directory.
1384f785676fSDimitry Andric     bool IsSystem;
1385f785676fSDimitry Andric 
13864ba319b5SDimitry Andric     /// Whether an error occurred.
13879a199699SDimitry Andric     bool HadError = false;
1388dff0c46cSDimitry Andric 
13894ba319b5SDimitry Andric     /// Stores string data for the various string literals referenced
1390dff0c46cSDimitry Andric     /// during parsing.
1391dff0c46cSDimitry Andric     llvm::BumpPtrAllocator StringData;
1392dff0c46cSDimitry Andric 
13934ba319b5SDimitry Andric     /// The current token.
1394dff0c46cSDimitry Andric     MMToken Tok;
1395dff0c46cSDimitry Andric 
13964ba319b5SDimitry Andric     /// The active module.
13979a199699SDimitry Andric     Module *ActiveModule = nullptr;
1398dff0c46cSDimitry Andric 
13994ba319b5SDimitry Andric     /// Whether a module uses the 'requires excluded' hack to mark its
14000623d748SDimitry Andric     /// contents as 'textual'.
14010623d748SDimitry Andric     ///
14020623d748SDimitry Andric     /// On older Darwin SDK versions, 'requires excluded' is used to mark the
14030623d748SDimitry Andric     /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
14040623d748SDimitry Andric     /// non-modular headers.  For backwards compatibility, we continue to
14050623d748SDimitry Andric     /// support this idiom for just these modules, and map the headers to
14060623d748SDimitry Andric     /// 'textual' to match the original intent.
14070623d748SDimitry Andric     llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
14080623d748SDimitry Andric 
14094ba319b5SDimitry Andric     /// Consume the current token and return its location.
1410dff0c46cSDimitry Andric     SourceLocation consumeToken();
1411dff0c46cSDimitry Andric 
14124ba319b5SDimitry Andric     /// Skip tokens until we reach the a token with the given kind
1413dff0c46cSDimitry Andric     /// (or the end of the file).
1414dff0c46cSDimitry Andric     void skipUntil(MMToken::TokenKind K);
1415dff0c46cSDimitry Andric 
14169a199699SDimitry Andric     using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
14179a199699SDimitry Andric 
1418dff0c46cSDimitry Andric     bool parseModuleId(ModuleId &Id);
1419dff0c46cSDimitry Andric     void parseModuleDecl();
1420f785676fSDimitry Andric     void parseExternModuleDecl();
1421dff0c46cSDimitry Andric     void parseRequiresDecl();
14229a199699SDimitry Andric     void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
1423dff0c46cSDimitry Andric     void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
1424dff0c46cSDimitry Andric     void parseExportDecl();
14259a199699SDimitry Andric     void parseExportAsDecl();
1426f785676fSDimitry Andric     void parseUseDecl();
1427139f7f9bSDimitry Andric     void parseLinkDecl();
1428139f7f9bSDimitry Andric     void parseConfigMacros();
1429139f7f9bSDimitry Andric     void parseConflict();
14303861d79fSDimitry Andric     void parseInferredModuleDecl(bool Framework, bool Explicit);
143139d628a0SDimitry Andric 
14324ba319b5SDimitry Andric     /// Private modules are canonicalized as Foo_Private. Clang provides extra
14334ba319b5SDimitry Andric     /// module map search logic to find the appropriate private module when PCH
14344ba319b5SDimitry Andric     /// is used with implicit module maps. Warn when private modules are written
14354ba319b5SDimitry Andric     /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
14364ba319b5SDimitry Andric     void diagnosePrivateModules(SourceLocation ExplicitLoc,
14374ba319b5SDimitry Andric                                 SourceLocation FrameworkLoc);
14384ba319b5SDimitry Andric 
14399a199699SDimitry Andric     using Attributes = ModuleMap::Attributes;
14409a199699SDimitry Andric 
14413861d79fSDimitry Andric     bool parseOptionalAttributes(Attributes &Attrs);
1442dff0c46cSDimitry Andric 
1443dff0c46cSDimitry Andric   public:
ModuleMapParser(Lexer & L,SourceManager & SourceMgr,const TargetInfo * Target,DiagnosticsEngine & Diags,ModuleMap & Map,const FileEntry * ModuleMapFile,const DirectoryEntry * Directory,bool IsSystem)1444dff0c46cSDimitry Andric     explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
14454ba319b5SDimitry Andric                              const TargetInfo *Target, DiagnosticsEngine &Diags,
14464ba319b5SDimitry Andric                              ModuleMap &Map, const FileEntry *ModuleMapFile,
14474ba319b5SDimitry Andric                              const DirectoryEntry *Directory, bool IsSystem)
14483861d79fSDimitry Andric         : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
144959d1ed5bSDimitry Andric           ModuleMapFile(ModuleMapFile), Directory(Directory),
14509a199699SDimitry Andric           IsSystem(IsSystem) {
1451dff0c46cSDimitry Andric       Tok.clear();
1452dff0c46cSDimitry Andric       consumeToken();
1453dff0c46cSDimitry Andric     }
1454dff0c46cSDimitry Andric 
1455dff0c46cSDimitry Andric     bool parseModuleMapFile();
14560f5676f4SDimitry Andric 
terminatedByDirective()14570f5676f4SDimitry Andric     bool terminatedByDirective() { return false; }
getLocation()14580f5676f4SDimitry Andric     SourceLocation getLocation() { return Tok.getLocation(); }
1459dff0c46cSDimitry Andric   };
14609a199699SDimitry Andric 
14619a199699SDimitry Andric } // namespace clang
1462dff0c46cSDimitry Andric 
consumeToken()1463dff0c46cSDimitry Andric SourceLocation ModuleMapParser::consumeToken() {
1464dff0c46cSDimitry Andric   SourceLocation Result = Tok.getLocation();
1465dff0c46cSDimitry Andric 
14660f5676f4SDimitry Andric retry:
14670f5676f4SDimitry Andric   Tok.clear();
1468dff0c46cSDimitry Andric   Token LToken;
1469dff0c46cSDimitry Andric   L.LexFromRawLexer(LToken);
1470dff0c46cSDimitry Andric   Tok.Location = LToken.getLocation().getRawEncoding();
1471dff0c46cSDimitry Andric   switch (LToken.getKind()) {
147259d1ed5bSDimitry Andric   case tok::raw_identifier: {
147359d1ed5bSDimitry Andric     StringRef RI = LToken.getRawIdentifier();
147459d1ed5bSDimitry Andric     Tok.StringData = RI.data();
147559d1ed5bSDimitry Andric     Tok.StringLength = RI.size();
147659d1ed5bSDimitry Andric     Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
1477139f7f9bSDimitry Andric                  .Case("config_macros", MMToken::ConfigMacros)
1478139f7f9bSDimitry Andric                  .Case("conflict", MMToken::Conflict)
14793861d79fSDimitry Andric                  .Case("exclude", MMToken::ExcludeKeyword)
1480dff0c46cSDimitry Andric                  .Case("explicit", MMToken::ExplicitKeyword)
1481dff0c46cSDimitry Andric                  .Case("export", MMToken::ExportKeyword)
14829a199699SDimitry Andric                  .Case("export_as", MMToken::ExportAsKeyword)
1483f785676fSDimitry Andric                  .Case("extern", MMToken::ExternKeyword)
1484dff0c46cSDimitry Andric                  .Case("framework", MMToken::FrameworkKeyword)
1485139f7f9bSDimitry Andric                  .Case("header", MMToken::HeaderKeyword)
1486139f7f9bSDimitry Andric                  .Case("link", MMToken::LinkKeyword)
1487dff0c46cSDimitry Andric                  .Case("module", MMToken::ModuleKeyword)
1488f785676fSDimitry Andric                  .Case("private", MMToken::PrivateKeyword)
1489dff0c46cSDimitry Andric                  .Case("requires", MMToken::RequiresKeyword)
149039d628a0SDimitry Andric                  .Case("textual", MMToken::TextualKeyword)
1491dff0c46cSDimitry Andric                  .Case("umbrella", MMToken::UmbrellaKeyword)
1492f785676fSDimitry Andric                  .Case("use", MMToken::UseKeyword)
1493dff0c46cSDimitry Andric                  .Default(MMToken::Identifier);
1494dff0c46cSDimitry Andric     break;
149559d1ed5bSDimitry Andric   }
1496dff0c46cSDimitry Andric 
1497dff0c46cSDimitry Andric   case tok::comma:
1498dff0c46cSDimitry Andric     Tok.Kind = MMToken::Comma;
1499dff0c46cSDimitry Andric     break;
1500dff0c46cSDimitry Andric 
1501dff0c46cSDimitry Andric   case tok::eof:
1502dff0c46cSDimitry Andric     Tok.Kind = MMToken::EndOfFile;
1503dff0c46cSDimitry Andric     break;
1504dff0c46cSDimitry Andric 
1505dff0c46cSDimitry Andric   case tok::l_brace:
1506dff0c46cSDimitry Andric     Tok.Kind = MMToken::LBrace;
1507dff0c46cSDimitry Andric     break;
1508dff0c46cSDimitry Andric 
1509dff0c46cSDimitry Andric   case tok::l_square:
1510dff0c46cSDimitry Andric     Tok.Kind = MMToken::LSquare;
1511dff0c46cSDimitry Andric     break;
1512dff0c46cSDimitry Andric 
1513dff0c46cSDimitry Andric   case tok::period:
1514dff0c46cSDimitry Andric     Tok.Kind = MMToken::Period;
1515dff0c46cSDimitry Andric     break;
1516dff0c46cSDimitry Andric 
1517dff0c46cSDimitry Andric   case tok::r_brace:
1518dff0c46cSDimitry Andric     Tok.Kind = MMToken::RBrace;
1519dff0c46cSDimitry Andric     break;
1520dff0c46cSDimitry Andric 
1521dff0c46cSDimitry Andric   case tok::r_square:
1522dff0c46cSDimitry Andric     Tok.Kind = MMToken::RSquare;
1523dff0c46cSDimitry Andric     break;
1524dff0c46cSDimitry Andric 
1525dff0c46cSDimitry Andric   case tok::star:
1526dff0c46cSDimitry Andric     Tok.Kind = MMToken::Star;
1527dff0c46cSDimitry Andric     break;
1528dff0c46cSDimitry Andric 
1529f785676fSDimitry Andric   case tok::exclaim:
1530f785676fSDimitry Andric     Tok.Kind = MMToken::Exclaim;
1531f785676fSDimitry Andric     break;
1532f785676fSDimitry Andric 
1533dff0c46cSDimitry Andric   case tok::string_literal: {
1534dff0c46cSDimitry Andric     if (LToken.hasUDSuffix()) {
1535dff0c46cSDimitry Andric       Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
1536dff0c46cSDimitry Andric       HadError = true;
1537dff0c46cSDimitry Andric       goto retry;
1538dff0c46cSDimitry Andric     }
1539dff0c46cSDimitry Andric 
1540dff0c46cSDimitry Andric     // Parse the string literal.
1541dff0c46cSDimitry Andric     LangOptions LangOpts;
154259d1ed5bSDimitry Andric     StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
1543dff0c46cSDimitry Andric     if (StringLiteral.hadError)
1544dff0c46cSDimitry Andric       goto retry;
1545dff0c46cSDimitry Andric 
1546dff0c46cSDimitry Andric     // Copy the string literal into our string data allocator.
1547dff0c46cSDimitry Andric     unsigned Length = StringLiteral.GetStringLength();
1548dff0c46cSDimitry Andric     char *Saved = StringData.Allocate<char>(Length + 1);
1549dff0c46cSDimitry Andric     memcpy(Saved, StringLiteral.GetString().data(), Length);
1550dff0c46cSDimitry Andric     Saved[Length] = 0;
1551dff0c46cSDimitry Andric 
1552dff0c46cSDimitry Andric     // Form the token.
1553dff0c46cSDimitry Andric     Tok.Kind = MMToken::StringLiteral;
1554dff0c46cSDimitry Andric     Tok.StringData = Saved;
1555dff0c46cSDimitry Andric     Tok.StringLength = Length;
1556dff0c46cSDimitry Andric     break;
1557dff0c46cSDimitry Andric   }
1558dff0c46cSDimitry Andric 
15596d97bb29SDimitry Andric   case tok::numeric_constant: {
15606d97bb29SDimitry Andric     // We don't support any suffixes or other complications.
15616d97bb29SDimitry Andric     SmallString<32> SpellingBuffer;
15626d97bb29SDimitry Andric     SpellingBuffer.resize(LToken.getLength() + 1);
15636d97bb29SDimitry Andric     const char *Start = SpellingBuffer.data();
15646d97bb29SDimitry Andric     unsigned Length =
15656d97bb29SDimitry Andric         Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts());
15666d97bb29SDimitry Andric     uint64_t Value;
15676d97bb29SDimitry Andric     if (StringRef(Start, Length).getAsInteger(0, Value)) {
15686d97bb29SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
15696d97bb29SDimitry Andric       HadError = true;
15706d97bb29SDimitry Andric       goto retry;
15716d97bb29SDimitry Andric     }
15726d97bb29SDimitry Andric 
15736d97bb29SDimitry Andric     Tok.Kind = MMToken::IntegerLiteral;
15746d97bb29SDimitry Andric     Tok.IntegerValue = Value;
15756d97bb29SDimitry Andric     break;
15766d97bb29SDimitry Andric   }
15776d97bb29SDimitry Andric 
1578dff0c46cSDimitry Andric   case tok::comment:
1579dff0c46cSDimitry Andric     goto retry;
1580dff0c46cSDimitry Andric 
15810f5676f4SDimitry Andric   case tok::hash:
15820f5676f4SDimitry Andric     // A module map can be terminated prematurely by
15830f5676f4SDimitry Andric     //   #pragma clang module contents
15840f5676f4SDimitry Andric     // When building the module, we'll treat the rest of the file as the
15850f5676f4SDimitry Andric     // contents of the module.
15860f5676f4SDimitry Andric     {
15870f5676f4SDimitry Andric       auto NextIsIdent = [&](StringRef Str) -> bool {
15880f5676f4SDimitry Andric         L.LexFromRawLexer(LToken);
15890f5676f4SDimitry Andric         return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
15900f5676f4SDimitry Andric                LToken.getRawIdentifier() == Str;
15910f5676f4SDimitry Andric       };
15920f5676f4SDimitry Andric       if (NextIsIdent("pragma") && NextIsIdent("clang") &&
15930f5676f4SDimitry Andric           NextIsIdent("module") && NextIsIdent("contents")) {
15940f5676f4SDimitry Andric         Tok.Kind = MMToken::EndOfFile;
15950f5676f4SDimitry Andric         break;
15960f5676f4SDimitry Andric       }
15970f5676f4SDimitry Andric     }
15980f5676f4SDimitry Andric     LLVM_FALLTHROUGH;
15990f5676f4SDimitry Andric 
1600dff0c46cSDimitry Andric   default:
16010f5676f4SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1602dff0c46cSDimitry Andric     HadError = true;
1603dff0c46cSDimitry Andric     goto retry;
1604dff0c46cSDimitry Andric   }
1605dff0c46cSDimitry Andric 
1606dff0c46cSDimitry Andric   return Result;
1607dff0c46cSDimitry Andric }
1608dff0c46cSDimitry Andric 
skipUntil(MMToken::TokenKind K)1609dff0c46cSDimitry Andric void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
1610dff0c46cSDimitry Andric   unsigned braceDepth = 0;
1611dff0c46cSDimitry Andric   unsigned squareDepth = 0;
1612dff0c46cSDimitry Andric   do {
1613dff0c46cSDimitry Andric     switch (Tok.Kind) {
1614dff0c46cSDimitry Andric     case MMToken::EndOfFile:
1615dff0c46cSDimitry Andric       return;
1616dff0c46cSDimitry Andric 
1617dff0c46cSDimitry Andric     case MMToken::LBrace:
1618dff0c46cSDimitry Andric       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1619dff0c46cSDimitry Andric         return;
1620dff0c46cSDimitry Andric 
1621dff0c46cSDimitry Andric       ++braceDepth;
1622dff0c46cSDimitry Andric       break;
1623dff0c46cSDimitry Andric 
1624dff0c46cSDimitry Andric     case MMToken::LSquare:
1625dff0c46cSDimitry Andric       if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1626dff0c46cSDimitry Andric         return;
1627dff0c46cSDimitry Andric 
1628dff0c46cSDimitry Andric       ++squareDepth;
1629dff0c46cSDimitry Andric       break;
1630dff0c46cSDimitry Andric 
1631dff0c46cSDimitry Andric     case MMToken::RBrace:
1632dff0c46cSDimitry Andric       if (braceDepth > 0)
1633dff0c46cSDimitry Andric         --braceDepth;
1634dff0c46cSDimitry Andric       else if (Tok.is(K))
1635dff0c46cSDimitry Andric         return;
1636dff0c46cSDimitry Andric       break;
1637dff0c46cSDimitry Andric 
1638dff0c46cSDimitry Andric     case MMToken::RSquare:
1639dff0c46cSDimitry Andric       if (squareDepth > 0)
1640dff0c46cSDimitry Andric         --squareDepth;
1641dff0c46cSDimitry Andric       else if (Tok.is(K))
1642dff0c46cSDimitry Andric         return;
1643dff0c46cSDimitry Andric       break;
1644dff0c46cSDimitry Andric 
1645dff0c46cSDimitry Andric     default:
1646dff0c46cSDimitry Andric       if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
1647dff0c46cSDimitry Andric         return;
1648dff0c46cSDimitry Andric       break;
1649dff0c46cSDimitry Andric     }
1650dff0c46cSDimitry Andric 
1651dff0c46cSDimitry Andric    consumeToken();
1652dff0c46cSDimitry Andric   } while (true);
1653dff0c46cSDimitry Andric }
1654dff0c46cSDimitry Andric 
16554ba319b5SDimitry Andric /// Parse a module-id.
1656dff0c46cSDimitry Andric ///
1657dff0c46cSDimitry Andric ///   module-id:
1658dff0c46cSDimitry Andric ///     identifier
1659dff0c46cSDimitry Andric ///     identifier '.' module-id
1660dff0c46cSDimitry Andric ///
1661dff0c46cSDimitry Andric /// \returns true if an error occurred, false otherwise.
parseModuleId(ModuleId & Id)1662dff0c46cSDimitry Andric bool ModuleMapParser::parseModuleId(ModuleId &Id) {
1663dff0c46cSDimitry Andric   Id.clear();
1664dff0c46cSDimitry Andric   do {
166559d1ed5bSDimitry Andric     if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1666dff0c46cSDimitry Andric       Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
1667dff0c46cSDimitry Andric       consumeToken();
1668dff0c46cSDimitry Andric     } else {
1669dff0c46cSDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1670dff0c46cSDimitry Andric       return true;
1671dff0c46cSDimitry Andric     }
1672dff0c46cSDimitry Andric 
1673dff0c46cSDimitry Andric     if (!Tok.is(MMToken::Period))
1674dff0c46cSDimitry Andric       break;
1675dff0c46cSDimitry Andric 
1676dff0c46cSDimitry Andric     consumeToken();
1677dff0c46cSDimitry Andric   } while (true);
1678dff0c46cSDimitry Andric 
1679dff0c46cSDimitry Andric   return false;
1680dff0c46cSDimitry Andric }
1681dff0c46cSDimitry Andric 
1682dff0c46cSDimitry Andric namespace {
16839a199699SDimitry Andric 
16844ba319b5SDimitry Andric   /// Enumerates the known attributes.
1685dff0c46cSDimitry Andric   enum AttributeKind {
16864ba319b5SDimitry Andric     /// An unknown attribute.
1687dff0c46cSDimitry Andric     AT_unknown,
16889a199699SDimitry Andric 
16894ba319b5SDimitry Andric     /// The 'system' attribute.
1690139f7f9bSDimitry Andric     AT_system,
16919a199699SDimitry Andric 
16924ba319b5SDimitry Andric     /// The 'extern_c' attribute.
169359d1ed5bSDimitry Andric     AT_extern_c,
16949a199699SDimitry Andric 
16954ba319b5SDimitry Andric     /// The 'exhaustive' attribute.
169644290647SDimitry Andric     AT_exhaustive,
16979a199699SDimitry Andric 
16984ba319b5SDimitry Andric     /// The 'no_undeclared_includes' attribute.
169944290647SDimitry Andric     AT_no_undeclared_includes
1700dff0c46cSDimitry Andric   };
17019a199699SDimitry Andric 
17029a199699SDimitry Andric } // namespace
1703dff0c46cSDimitry Andric 
170413ddaa84SDimitry Andric /// Private modules are canonicalized as Foo_Private. Clang provides extra
170513ddaa84SDimitry Andric /// module map search logic to find the appropriate private module when PCH
170613ddaa84SDimitry Andric /// is used with implicit module maps. Warn when private modules are written
170713ddaa84SDimitry Andric /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
diagnosePrivateModules(SourceLocation ExplicitLoc,SourceLocation FrameworkLoc)17084ba319b5SDimitry Andric void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
17094ba319b5SDimitry Andric                                              SourceLocation FrameworkLoc) {
171013ddaa84SDimitry Andric   auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
17114ba319b5SDimitry Andric                              const Module *M, SourceRange ReplLoc) {
171213ddaa84SDimitry Andric     auto D = Diags.Report(ActiveModule->DefinitionLoc,
171313ddaa84SDimitry Andric                           diag::note_mmap_rename_top_level_private_module);
171413ddaa84SDimitry Andric     D << BadName << M->Name;
17154ba319b5SDimitry Andric     D << FixItHint::CreateReplacement(ReplLoc, Canonical);
171613ddaa84SDimitry Andric   };
171713ddaa84SDimitry Andric 
171813ddaa84SDimitry Andric   for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
171913ddaa84SDimitry Andric     auto const *M = E->getValue();
172013ddaa84SDimitry Andric     if (M->Directory != ActiveModule->Directory)
172113ddaa84SDimitry Andric       continue;
172213ddaa84SDimitry Andric 
172313ddaa84SDimitry Andric     SmallString<128> FullName(ActiveModule->getFullModuleName());
172413ddaa84SDimitry Andric     if (!FullName.startswith(M->Name) && !FullName.endswith("Private"))
172513ddaa84SDimitry Andric       continue;
17264ba319b5SDimitry Andric     SmallString<128> FixedPrivModDecl;
172713ddaa84SDimitry Andric     SmallString<128> Canonical(M->Name);
172813ddaa84SDimitry Andric     Canonical.append("_Private");
172913ddaa84SDimitry Andric 
173013ddaa84SDimitry Andric     // Foo.Private -> Foo_Private
173113ddaa84SDimitry Andric     if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
173213ddaa84SDimitry Andric         M->Name == ActiveModule->Parent->Name) {
173313ddaa84SDimitry Andric       Diags.Report(ActiveModule->DefinitionLoc,
173413ddaa84SDimitry Andric                    diag::warn_mmap_mismatched_private_submodule)
173513ddaa84SDimitry Andric           << FullName;
17364ba319b5SDimitry Andric 
17374ba319b5SDimitry Andric       SourceLocation FixItInitBegin = CurrModuleDeclLoc;
17384ba319b5SDimitry Andric       if (FrameworkLoc.isValid())
17394ba319b5SDimitry Andric         FixItInitBegin = FrameworkLoc;
17404ba319b5SDimitry Andric       if (ExplicitLoc.isValid())
17414ba319b5SDimitry Andric         FixItInitBegin = ExplicitLoc;
17424ba319b5SDimitry Andric 
17434ba319b5SDimitry Andric       if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
17444ba319b5SDimitry Andric         FixedPrivModDecl.append("framework ");
17454ba319b5SDimitry Andric       FixedPrivModDecl.append("module ");
17464ba319b5SDimitry Andric       FixedPrivModDecl.append(Canonical);
17474ba319b5SDimitry Andric 
17484ba319b5SDimitry Andric       GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
17494ba319b5SDimitry Andric                       SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
175013ddaa84SDimitry Andric       continue;
175113ddaa84SDimitry Andric     }
175213ddaa84SDimitry Andric 
175313ddaa84SDimitry Andric     // FooPrivate and whatnots -> Foo_Private
175413ddaa84SDimitry Andric     if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
175513ddaa84SDimitry Andric         ActiveModule->Name != Canonical) {
175613ddaa84SDimitry Andric       Diags.Report(ActiveModule->DefinitionLoc,
175713ddaa84SDimitry Andric                    diag::warn_mmap_mismatched_private_module_name)
175813ddaa84SDimitry Andric           << ActiveModule->Name;
17594ba319b5SDimitry Andric       GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
17604ba319b5SDimitry Andric                       SourceRange(ActiveModule->DefinitionLoc));
176113ddaa84SDimitry Andric     }
176213ddaa84SDimitry Andric   }
176313ddaa84SDimitry Andric }
176413ddaa84SDimitry Andric 
17654ba319b5SDimitry Andric /// Parse a module declaration.
1766dff0c46cSDimitry Andric ///
1767dff0c46cSDimitry Andric ///   module-declaration:
1768f785676fSDimitry Andric ///     'extern' 'module' module-id string-literal
1769dff0c46cSDimitry Andric ///     'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1770dff0c46cSDimitry Andric ///       { module-member* }
1771dff0c46cSDimitry Andric ///
1772dff0c46cSDimitry Andric ///   module-member:
1773dff0c46cSDimitry Andric ///     requires-declaration
1774dff0c46cSDimitry Andric ///     header-declaration
1775dff0c46cSDimitry Andric ///     submodule-declaration
1776dff0c46cSDimitry Andric ///     export-declaration
17779a199699SDimitry Andric ///     export-as-declaration
1778139f7f9bSDimitry Andric ///     link-declaration
1779dff0c46cSDimitry Andric ///
1780dff0c46cSDimitry Andric ///   submodule-declaration:
1781dff0c46cSDimitry Andric ///     module-declaration
1782dff0c46cSDimitry Andric ///     inferred-submodule-declaration
parseModuleDecl()1783dff0c46cSDimitry Andric void ModuleMapParser::parseModuleDecl() {
1784dff0c46cSDimitry Andric   assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
1785f785676fSDimitry Andric          Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
1786f785676fSDimitry Andric   if (Tok.is(MMToken::ExternKeyword)) {
1787f785676fSDimitry Andric     parseExternModuleDecl();
1788f785676fSDimitry Andric     return;
1789f785676fSDimitry Andric   }
1790f785676fSDimitry Andric 
1791dff0c46cSDimitry Andric   // Parse 'explicit' or 'framework' keyword, if present.
1792dff0c46cSDimitry Andric   SourceLocation ExplicitLoc;
17934ba319b5SDimitry Andric   SourceLocation FrameworkLoc;
1794dff0c46cSDimitry Andric   bool Explicit = false;
1795dff0c46cSDimitry Andric   bool Framework = false;
1796dff0c46cSDimitry Andric 
1797dff0c46cSDimitry Andric   // Parse 'explicit' keyword, if present.
1798dff0c46cSDimitry Andric   if (Tok.is(MMToken::ExplicitKeyword)) {
1799dff0c46cSDimitry Andric     ExplicitLoc = consumeToken();
1800dff0c46cSDimitry Andric     Explicit = true;
1801dff0c46cSDimitry Andric   }
1802dff0c46cSDimitry Andric 
1803dff0c46cSDimitry Andric   // Parse 'framework' keyword, if present.
1804dff0c46cSDimitry Andric   if (Tok.is(MMToken::FrameworkKeyword)) {
18054ba319b5SDimitry Andric     FrameworkLoc = consumeToken();
1806dff0c46cSDimitry Andric     Framework = true;
1807dff0c46cSDimitry Andric   }
1808dff0c46cSDimitry Andric 
1809dff0c46cSDimitry Andric   // Parse 'module' keyword.
1810dff0c46cSDimitry Andric   if (!Tok.is(MMToken::ModuleKeyword)) {
1811dff0c46cSDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1812dff0c46cSDimitry Andric     consumeToken();
1813dff0c46cSDimitry Andric     HadError = true;
1814dff0c46cSDimitry Andric     return;
1815dff0c46cSDimitry Andric   }
18164ba319b5SDimitry Andric   CurrModuleDeclLoc = consumeToken(); // 'module' keyword
1817dff0c46cSDimitry Andric 
1818dff0c46cSDimitry Andric   // If we have a wildcard for the module name, this is an inferred submodule.
1819dff0c46cSDimitry Andric   // Parse it.
1820dff0c46cSDimitry Andric   if (Tok.is(MMToken::Star))
18213861d79fSDimitry Andric     return parseInferredModuleDecl(Framework, Explicit);
1822dff0c46cSDimitry Andric 
1823dff0c46cSDimitry Andric   // Parse the module name.
1824dff0c46cSDimitry Andric   ModuleId Id;
1825dff0c46cSDimitry Andric   if (parseModuleId(Id)) {
1826dff0c46cSDimitry Andric     HadError = true;
1827dff0c46cSDimitry Andric     return;
1828dff0c46cSDimitry Andric   }
1829dff0c46cSDimitry Andric 
1830dff0c46cSDimitry Andric   if (ActiveModule) {
1831dff0c46cSDimitry Andric     if (Id.size() > 1) {
1832dff0c46cSDimitry Andric       Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1833dff0c46cSDimitry Andric         << SourceRange(Id.front().second, Id.back().second);
1834dff0c46cSDimitry Andric 
1835dff0c46cSDimitry Andric       HadError = true;
1836dff0c46cSDimitry Andric       return;
1837dff0c46cSDimitry Andric     }
1838dff0c46cSDimitry Andric   } else if (Id.size() == 1 && Explicit) {
1839dff0c46cSDimitry Andric     // Top-level modules can't be explicit.
1840dff0c46cSDimitry Andric     Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1841dff0c46cSDimitry Andric     Explicit = false;
1842dff0c46cSDimitry Andric     ExplicitLoc = SourceLocation();
1843dff0c46cSDimitry Andric     HadError = true;
1844dff0c46cSDimitry Andric   }
1845dff0c46cSDimitry Andric 
1846dff0c46cSDimitry Andric   Module *PreviousActiveModule = ActiveModule;
1847dff0c46cSDimitry Andric   if (Id.size() > 1) {
1848dff0c46cSDimitry Andric     // This module map defines a submodule. Go find the module of which it
1849dff0c46cSDimitry Andric     // is a submodule.
185059d1ed5bSDimitry Andric     ActiveModule = nullptr;
185139d628a0SDimitry Andric     const Module *TopLevelModule = nullptr;
1852dff0c46cSDimitry Andric     for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1853dff0c46cSDimitry Andric       if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
185439d628a0SDimitry Andric         if (I == 0)
185539d628a0SDimitry Andric           TopLevelModule = Next;
1856dff0c46cSDimitry Andric         ActiveModule = Next;
1857dff0c46cSDimitry Andric         continue;
1858dff0c46cSDimitry Andric       }
1859dff0c46cSDimitry Andric 
1860dff0c46cSDimitry Andric       if (ActiveModule) {
1861dff0c46cSDimitry Andric         Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
186259d1ed5bSDimitry Andric           << Id[I].first
186359d1ed5bSDimitry Andric           << ActiveModule->getTopLevelModule()->getFullModuleName();
1864dff0c46cSDimitry Andric       } else {
1865dff0c46cSDimitry Andric         Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1866dff0c46cSDimitry Andric       }
1867dff0c46cSDimitry Andric       HadError = true;
1868dff0c46cSDimitry Andric       return;
1869dff0c46cSDimitry Andric     }
187039d628a0SDimitry Andric 
187139d628a0SDimitry Andric     if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
187239d628a0SDimitry Andric       assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
187339d628a0SDimitry Andric              "submodule defined in same file as 'module *' that allowed its "
187439d628a0SDimitry Andric              "top-level module");
187539d628a0SDimitry Andric       Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
187639d628a0SDimitry Andric     }
1877dff0c46cSDimitry Andric   }
1878dff0c46cSDimitry Andric 
1879dff0c46cSDimitry Andric   StringRef ModuleName = Id.back().first;
1880dff0c46cSDimitry Andric   SourceLocation ModuleNameLoc = Id.back().second;
1881dff0c46cSDimitry Andric 
1882dff0c46cSDimitry Andric   // Parse the optional attribute list.
18833861d79fSDimitry Andric   Attributes Attrs;
1884e7145dcbSDimitry Andric   if (parseOptionalAttributes(Attrs))
1885e7145dcbSDimitry Andric     return;
1886e7145dcbSDimitry Andric 
1887dff0c46cSDimitry Andric   // Parse the opening brace.
1888dff0c46cSDimitry Andric   if (!Tok.is(MMToken::LBrace)) {
1889dff0c46cSDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1890dff0c46cSDimitry Andric       << ModuleName;
1891dff0c46cSDimitry Andric     HadError = true;
1892dff0c46cSDimitry Andric     return;
1893dff0c46cSDimitry Andric   }
1894dff0c46cSDimitry Andric   SourceLocation LBraceLoc = consumeToken();
1895dff0c46cSDimitry Andric 
1896dff0c46cSDimitry Andric   // Determine whether this (sub)module has already been defined.
18974ba319b5SDimitry Andric   Module *ShadowingModule = nullptr;
1898dff0c46cSDimitry Andric   if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
18995517e702SDimitry Andric     // We might see a (re)definition of a module that we already have a
19005517e702SDimitry Andric     // definition for in two cases:
19015517e702SDimitry Andric     //  - If we loaded one definition from an AST file and we've just found a
19025517e702SDimitry Andric     //    corresponding definition in a module map file, or
19035517e702SDimitry Andric     bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
19045517e702SDimitry Andric     //  - If we're building a (preprocessed) module and we've just loaded the
19055517e702SDimitry Andric     //    module map file from which it was created.
19065517e702SDimitry Andric     bool ParsedAsMainInput =
19075517e702SDimitry Andric         Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
19085517e702SDimitry Andric         Map.LangOpts.CurrentModule == ModuleName &&
19095517e702SDimitry Andric         SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
19105517e702SDimitry Andric             SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
19115517e702SDimitry Andric     if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
1912dff0c46cSDimitry Andric       // Skip the module definition.
1913dff0c46cSDimitry Andric       skipUntil(MMToken::RBrace);
1914dff0c46cSDimitry Andric       if (Tok.is(MMToken::RBrace))
1915dff0c46cSDimitry Andric         consumeToken();
1916dff0c46cSDimitry Andric       else {
1917dff0c46cSDimitry Andric         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1918dff0c46cSDimitry Andric         Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1919dff0c46cSDimitry Andric         HadError = true;
1920dff0c46cSDimitry Andric       }
1921dff0c46cSDimitry Andric       return;
1922dff0c46cSDimitry Andric     }
1923dff0c46cSDimitry Andric 
19244ba319b5SDimitry Andric     if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
19254ba319b5SDimitry Andric       ShadowingModule = Existing;
19264ba319b5SDimitry Andric     } else {
19274ba319b5SDimitry Andric       // This is not a shawdowed module decl, it is an illegal redefinition.
1928dff0c46cSDimitry Andric       Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1929dff0c46cSDimitry Andric           << ModuleName;
1930dff0c46cSDimitry Andric       Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1931dff0c46cSDimitry Andric 
1932dff0c46cSDimitry Andric       // Skip the module definition.
1933dff0c46cSDimitry Andric       skipUntil(MMToken::RBrace);
1934dff0c46cSDimitry Andric       if (Tok.is(MMToken::RBrace))
1935dff0c46cSDimitry Andric         consumeToken();
1936dff0c46cSDimitry Andric 
1937dff0c46cSDimitry Andric       HadError = true;
1938dff0c46cSDimitry Andric       return;
1939dff0c46cSDimitry Andric     }
19404ba319b5SDimitry Andric   }
1941dff0c46cSDimitry Andric 
1942dff0c46cSDimitry Andric   // Start defining this module.
19434ba319b5SDimitry Andric   if (ShadowingModule) {
19444ba319b5SDimitry Andric     ActiveModule =
19454ba319b5SDimitry Andric         Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
19464ba319b5SDimitry Andric   } else {
19474ba319b5SDimitry Andric     ActiveModule =
19484ba319b5SDimitry Andric         Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
19494ba319b5SDimitry Andric             .first;
19504ba319b5SDimitry Andric   }
19514ba319b5SDimitry Andric 
1952dff0c46cSDimitry Andric   ActiveModule->DefinitionLoc = ModuleNameLoc;
1953f785676fSDimitry Andric   if (Attrs.IsSystem || IsSystem)
1954dff0c46cSDimitry Andric     ActiveModule->IsSystem = true;
195559d1ed5bSDimitry Andric   if (Attrs.IsExternC)
195659d1ed5bSDimitry Andric     ActiveModule->IsExternC = true;
195744290647SDimitry Andric   if (Attrs.NoUndeclaredIncludes ||
195844290647SDimitry Andric       (!ActiveModule->Parent && ModuleName == "Darwin"))
195944290647SDimitry Andric     ActiveModule->NoUndeclaredIncludes = true;
196039d628a0SDimitry Andric   ActiveModule->Directory = Directory;
1961dff0c46cSDimitry Andric 
19624ba319b5SDimitry Andric   StringRef MapFileName(ModuleMapFile->getName());
19634ba319b5SDimitry Andric   if (MapFileName.endswith("module.private.modulemap") ||
19644ba319b5SDimitry Andric       MapFileName.endswith("module_private.map")) {
19654ba319b5SDimitry Andric     ActiveModule->ModuleMapIsPrivate = true;
19664ba319b5SDimitry Andric   }
196713ddaa84SDimitry Andric 
196813ddaa84SDimitry Andric   // Private modules named as FooPrivate, Foo.Private or similar are likely a
196913ddaa84SDimitry Andric   // user error; provide warnings, notes and fixits to direct users to use
197013ddaa84SDimitry Andric   // Foo_Private instead.
197113ddaa84SDimitry Andric   SourceLocation StartLoc =
197213ddaa84SDimitry Andric       SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
197313ddaa84SDimitry Andric   if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
197413ddaa84SDimitry Andric       !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
197513ddaa84SDimitry Andric                        StartLoc) &&
197613ddaa84SDimitry Andric       !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
197713ddaa84SDimitry Andric                        StartLoc) &&
19784ba319b5SDimitry Andric       ActiveModule->ModuleMapIsPrivate)
19794ba319b5SDimitry Andric     diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
198044290647SDimitry Andric 
1981dff0c46cSDimitry Andric   bool Done = false;
1982dff0c46cSDimitry Andric   do {
1983dff0c46cSDimitry Andric     switch (Tok.Kind) {
1984dff0c46cSDimitry Andric     case MMToken::EndOfFile:
1985dff0c46cSDimitry Andric     case MMToken::RBrace:
1986dff0c46cSDimitry Andric       Done = true;
1987dff0c46cSDimitry Andric       break;
1988dff0c46cSDimitry Andric 
1989139f7f9bSDimitry Andric     case MMToken::ConfigMacros:
1990139f7f9bSDimitry Andric       parseConfigMacros();
1991139f7f9bSDimitry Andric       break;
1992139f7f9bSDimitry Andric 
1993139f7f9bSDimitry Andric     case MMToken::Conflict:
1994139f7f9bSDimitry Andric       parseConflict();
1995139f7f9bSDimitry Andric       break;
1996139f7f9bSDimitry Andric 
1997dff0c46cSDimitry Andric     case MMToken::ExplicitKeyword:
1998f785676fSDimitry Andric     case MMToken::ExternKeyword:
1999dff0c46cSDimitry Andric     case MMToken::FrameworkKeyword:
2000dff0c46cSDimitry Andric     case MMToken::ModuleKeyword:
2001dff0c46cSDimitry Andric       parseModuleDecl();
2002dff0c46cSDimitry Andric       break;
2003dff0c46cSDimitry Andric 
2004dff0c46cSDimitry Andric     case MMToken::ExportKeyword:
2005dff0c46cSDimitry Andric       parseExportDecl();
2006dff0c46cSDimitry Andric       break;
2007dff0c46cSDimitry Andric 
20089a199699SDimitry Andric     case MMToken::ExportAsKeyword:
20099a199699SDimitry Andric       parseExportAsDecl();
20109a199699SDimitry Andric       break;
20119a199699SDimitry Andric 
2012f785676fSDimitry Andric     case MMToken::UseKeyword:
2013f785676fSDimitry Andric       parseUseDecl();
2014f785676fSDimitry Andric       break;
2015f785676fSDimitry Andric 
2016dff0c46cSDimitry Andric     case MMToken::RequiresKeyword:
2017dff0c46cSDimitry Andric       parseRequiresDecl();
2018dff0c46cSDimitry Andric       break;
2019dff0c46cSDimitry Andric 
202039d628a0SDimitry Andric     case MMToken::TextualKeyword:
202139d628a0SDimitry Andric       parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
202239d628a0SDimitry Andric       break;
202339d628a0SDimitry Andric 
2024dff0c46cSDimitry Andric     case MMToken::UmbrellaKeyword: {
2025dff0c46cSDimitry Andric       SourceLocation UmbrellaLoc = consumeToken();
2026dff0c46cSDimitry Andric       if (Tok.is(MMToken::HeaderKeyword))
2027f785676fSDimitry Andric         parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
2028dff0c46cSDimitry Andric       else
2029dff0c46cSDimitry Andric         parseUmbrellaDirDecl(UmbrellaLoc);
2030dff0c46cSDimitry Andric       break;
2031dff0c46cSDimitry Andric     }
2032dff0c46cSDimitry Andric 
203339d628a0SDimitry Andric     case MMToken::ExcludeKeyword:
203439d628a0SDimitry Andric       parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
20353861d79fSDimitry Andric       break;
20363861d79fSDimitry Andric 
203739d628a0SDimitry Andric     case MMToken::PrivateKeyword:
203839d628a0SDimitry Andric       parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
2039f785676fSDimitry Andric       break;
2040f785676fSDimitry Andric 
2041dff0c46cSDimitry Andric     case MMToken::HeaderKeyword:
204239d628a0SDimitry Andric       parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
2043dff0c46cSDimitry Andric       break;
2044dff0c46cSDimitry Andric 
2045139f7f9bSDimitry Andric     case MMToken::LinkKeyword:
2046139f7f9bSDimitry Andric       parseLinkDecl();
2047139f7f9bSDimitry Andric       break;
2048139f7f9bSDimitry Andric 
2049dff0c46cSDimitry Andric     default:
2050dff0c46cSDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
2051dff0c46cSDimitry Andric       consumeToken();
2052dff0c46cSDimitry Andric       break;
2053dff0c46cSDimitry Andric     }
2054dff0c46cSDimitry Andric   } while (!Done);
2055dff0c46cSDimitry Andric 
2056dff0c46cSDimitry Andric   if (Tok.is(MMToken::RBrace))
2057dff0c46cSDimitry Andric     consumeToken();
2058dff0c46cSDimitry Andric   else {
2059dff0c46cSDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2060dff0c46cSDimitry Andric     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2061dff0c46cSDimitry Andric     HadError = true;
2062dff0c46cSDimitry Andric   }
2063dff0c46cSDimitry Andric 
2064139f7f9bSDimitry Andric   // If the active module is a top-level framework, and there are no link
2065139f7f9bSDimitry Andric   // libraries, automatically link against the framework.
2066139f7f9bSDimitry Andric   if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
2067139f7f9bSDimitry Andric       ActiveModule->LinkLibraries.empty()) {
2068139f7f9bSDimitry Andric     inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
2069139f7f9bSDimitry Andric   }
2070139f7f9bSDimitry Andric 
207159d1ed5bSDimitry Andric   // If the module meets all requirements but is still unavailable, mark the
207259d1ed5bSDimitry Andric   // whole tree as unavailable to prevent it from building.
207359d1ed5bSDimitry Andric   if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement &&
207459d1ed5bSDimitry Andric       ActiveModule->Parent) {
207559d1ed5bSDimitry Andric     ActiveModule->getTopLevelModule()->markUnavailable();
207659d1ed5bSDimitry Andric     ActiveModule->getTopLevelModule()->MissingHeaders.append(
207759d1ed5bSDimitry Andric       ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
207859d1ed5bSDimitry Andric   }
207959d1ed5bSDimitry Andric 
2080dff0c46cSDimitry Andric   // We're done parsing this module. Pop back to the previous module.
2081dff0c46cSDimitry Andric   ActiveModule = PreviousActiveModule;
2082dff0c46cSDimitry Andric }
2083dff0c46cSDimitry Andric 
20844ba319b5SDimitry Andric /// Parse an extern module declaration.
2085f785676fSDimitry Andric ///
2086f785676fSDimitry Andric ///   extern module-declaration:
2087f785676fSDimitry Andric ///     'extern' 'module' module-id string-literal
parseExternModuleDecl()2088f785676fSDimitry Andric void ModuleMapParser::parseExternModuleDecl() {
2089f785676fSDimitry Andric   assert(Tok.is(MMToken::ExternKeyword));
2090875ed548SDimitry Andric   SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
2091f785676fSDimitry Andric 
2092f785676fSDimitry Andric   // Parse 'module' keyword.
2093f785676fSDimitry Andric   if (!Tok.is(MMToken::ModuleKeyword)) {
2094f785676fSDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
2095f785676fSDimitry Andric     consumeToken();
2096f785676fSDimitry Andric     HadError = true;
2097f785676fSDimitry Andric     return;
2098f785676fSDimitry Andric   }
2099f785676fSDimitry Andric   consumeToken(); // 'module' keyword
2100f785676fSDimitry Andric 
2101f785676fSDimitry Andric   // Parse the module name.
2102f785676fSDimitry Andric   ModuleId Id;
2103f785676fSDimitry Andric   if (parseModuleId(Id)) {
2104f785676fSDimitry Andric     HadError = true;
2105f785676fSDimitry Andric     return;
2106f785676fSDimitry Andric   }
2107f785676fSDimitry Andric 
2108f785676fSDimitry Andric   // Parse the referenced module map file name.
2109f785676fSDimitry Andric   if (!Tok.is(MMToken::StringLiteral)) {
2110f785676fSDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
2111f785676fSDimitry Andric     HadError = true;
2112f785676fSDimitry Andric     return;
2113f785676fSDimitry Andric   }
2114f785676fSDimitry Andric   std::string FileName = Tok.getString();
2115f785676fSDimitry Andric   consumeToken(); // filename
2116f785676fSDimitry Andric 
2117f785676fSDimitry Andric   StringRef FileNameRef = FileName;
2118f785676fSDimitry Andric   SmallString<128> ModuleMapFileName;
2119f785676fSDimitry Andric   if (llvm::sys::path::is_relative(FileNameRef)) {
2120f785676fSDimitry Andric     ModuleMapFileName += Directory->getName();
2121f785676fSDimitry Andric     llvm::sys::path::append(ModuleMapFileName, FileName);
212233956c43SDimitry Andric     FileNameRef = ModuleMapFileName;
2123f785676fSDimitry Andric   }
2124f785676fSDimitry Andric   if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef))
212539d628a0SDimitry Andric     Map.parseModuleMapFile(
212639d628a0SDimitry Andric         File, /*IsSystem=*/false,
212739d628a0SDimitry Andric         Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
212839d628a0SDimitry Andric             ? Directory
21290f5676f4SDimitry Andric             : File->getDir(),
21300f5676f4SDimitry Andric         FileID(), nullptr, ExternLoc);
2131f785676fSDimitry Andric }
2132f785676fSDimitry Andric 
21330623d748SDimitry Andric /// Whether to add the requirement \p Feature to the module \p M.
21340623d748SDimitry Andric ///
21350623d748SDimitry Andric /// This preserves backwards compatibility for two hacks in the Darwin system
21360623d748SDimitry Andric /// module map files:
21370623d748SDimitry Andric ///
21380623d748SDimitry Andric /// 1. The use of 'requires excluded' to make headers non-modular, which
21390623d748SDimitry Andric ///    should really be mapped to 'textual' now that we have this feature.  We
21400623d748SDimitry Andric ///    drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
21410623d748SDimitry Andric ///    true.  Later, this bit will be used to map all the headers inside this
21420623d748SDimitry Andric ///    module to 'textual'.
21430623d748SDimitry Andric ///
21440623d748SDimitry Andric ///    This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
21450623d748SDimitry Andric ///
21460623d748SDimitry Andric /// 2. Removes a bogus cplusplus requirement from IOKit.avc.  This requirement
21470623d748SDimitry Andric ///    was never correct and causes issues now that we check it, so drop it.
shouldAddRequirement(Module * M,StringRef Feature,bool & IsRequiresExcludedHack)21480623d748SDimitry Andric static bool shouldAddRequirement(Module *M, StringRef Feature,
21490623d748SDimitry Andric                                  bool &IsRequiresExcludedHack) {
215044290647SDimitry Andric   if (Feature == "excluded" &&
215144290647SDimitry Andric       (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
215244290647SDimitry Andric        M->fullModuleNameIs({"Tcl", "Private"}))) {
21530623d748SDimitry Andric     IsRequiresExcludedHack = true;
21540623d748SDimitry Andric     return false;
215544290647SDimitry Andric   } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
21560623d748SDimitry Andric     return false;
21570623d748SDimitry Andric   }
21580623d748SDimitry Andric 
21590623d748SDimitry Andric   return true;
21600623d748SDimitry Andric }
21610623d748SDimitry Andric 
21624ba319b5SDimitry Andric /// Parse a requires declaration.
2163dff0c46cSDimitry Andric ///
2164dff0c46cSDimitry Andric ///   requires-declaration:
2165dff0c46cSDimitry Andric ///     'requires' feature-list
2166dff0c46cSDimitry Andric ///
2167dff0c46cSDimitry Andric ///   feature-list:
2168f785676fSDimitry Andric ///     feature ',' feature-list
2169f785676fSDimitry Andric ///     feature
2170f785676fSDimitry Andric ///
2171f785676fSDimitry Andric ///   feature:
2172f785676fSDimitry Andric ///     '!'[opt] identifier
parseRequiresDecl()2173dff0c46cSDimitry Andric void ModuleMapParser::parseRequiresDecl() {
2174dff0c46cSDimitry Andric   assert(Tok.is(MMToken::RequiresKeyword));
2175dff0c46cSDimitry Andric 
2176dff0c46cSDimitry Andric   // Parse 'requires' keyword.
2177dff0c46cSDimitry Andric   consumeToken();
2178dff0c46cSDimitry Andric 
2179dff0c46cSDimitry Andric   // Parse the feature-list.
2180dff0c46cSDimitry Andric   do {
2181f785676fSDimitry Andric     bool RequiredState = true;
2182f785676fSDimitry Andric     if (Tok.is(MMToken::Exclaim)) {
2183f785676fSDimitry Andric       RequiredState = false;
2184f785676fSDimitry Andric       consumeToken();
2185f785676fSDimitry Andric     }
2186f785676fSDimitry Andric 
2187dff0c46cSDimitry Andric     if (!Tok.is(MMToken::Identifier)) {
2188dff0c46cSDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
2189dff0c46cSDimitry Andric       HadError = true;
2190dff0c46cSDimitry Andric       return;
2191dff0c46cSDimitry Andric     }
2192dff0c46cSDimitry Andric 
2193dff0c46cSDimitry Andric     // Consume the feature name.
2194dff0c46cSDimitry Andric     std::string Feature = Tok.getString();
2195dff0c46cSDimitry Andric     consumeToken();
2196dff0c46cSDimitry Andric 
21970623d748SDimitry Andric     bool IsRequiresExcludedHack = false;
21980623d748SDimitry Andric     bool ShouldAddRequirement =
21990623d748SDimitry Andric         shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
22000623d748SDimitry Andric 
22010623d748SDimitry Andric     if (IsRequiresExcludedHack)
22020623d748SDimitry Andric       UsesRequiresExcludedHack.insert(ActiveModule);
22030623d748SDimitry Andric 
22040623d748SDimitry Andric     if (ShouldAddRequirement) {
2205dff0c46cSDimitry Andric       // Add this feature.
22060623d748SDimitry Andric       ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
22070623d748SDimitry Andric                                    *Map.Target);
22080623d748SDimitry Andric     }
2209dff0c46cSDimitry Andric 
2210dff0c46cSDimitry Andric     if (!Tok.is(MMToken::Comma))
2211dff0c46cSDimitry Andric       break;
2212dff0c46cSDimitry Andric 
2213dff0c46cSDimitry Andric     // Consume the comma.
2214dff0c46cSDimitry Andric     consumeToken();
2215dff0c46cSDimitry Andric   } while (true);
2216dff0c46cSDimitry Andric }
2217dff0c46cSDimitry Andric 
22184ba319b5SDimitry Andric /// Parse a header declaration.
2219dff0c46cSDimitry Andric ///
2220dff0c46cSDimitry Andric ///   header-declaration:
222139d628a0SDimitry Andric ///     'textual'[opt] 'header' string-literal
222239d628a0SDimitry Andric ///     'private' 'textual'[opt] 'header' string-literal
222339d628a0SDimitry Andric ///     'exclude' 'header' string-literal
222439d628a0SDimitry Andric ///     'umbrella' 'header' string-literal
222539d628a0SDimitry Andric ///
222639d628a0SDimitry Andric /// FIXME: Support 'private textual header'.
parseHeaderDecl(MMToken::TokenKind LeadingToken,SourceLocation LeadingLoc)2227f785676fSDimitry Andric void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
2228f785676fSDimitry Andric                                       SourceLocation LeadingLoc) {
222939d628a0SDimitry Andric   // We've already consumed the first token.
223039d628a0SDimitry Andric   ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
223139d628a0SDimitry Andric   if (LeadingToken == MMToken::PrivateKeyword) {
223239d628a0SDimitry Andric     Role = ModuleMap::PrivateHeader;
223339d628a0SDimitry Andric     // 'private' may optionally be followed by 'textual'.
223439d628a0SDimitry Andric     if (Tok.is(MMToken::TextualKeyword)) {
223539d628a0SDimitry Andric       LeadingToken = Tok.Kind;
2236dff0c46cSDimitry Andric       consumeToken();
223739d628a0SDimitry Andric     }
223839d628a0SDimitry Andric   }
22390623d748SDimitry Andric 
224039d628a0SDimitry Andric   if (LeadingToken == MMToken::TextualKeyword)
224139d628a0SDimitry Andric     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
224239d628a0SDimitry Andric 
22430623d748SDimitry Andric   if (UsesRequiresExcludedHack.count(ActiveModule)) {
22440623d748SDimitry Andric     // Mark this header 'textual' (see doc comment for
22450623d748SDimitry Andric     // Module::UsesRequiresExcludedHack).
22460623d748SDimitry Andric     Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
22470623d748SDimitry Andric   }
22480623d748SDimitry Andric 
224939d628a0SDimitry Andric   if (LeadingToken != MMToken::HeaderKeyword) {
225039d628a0SDimitry Andric     if (!Tok.is(MMToken::HeaderKeyword)) {
225139d628a0SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
225239d628a0SDimitry Andric           << (LeadingToken == MMToken::PrivateKeyword ? "private" :
225339d628a0SDimitry Andric               LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
225439d628a0SDimitry Andric               LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
225539d628a0SDimitry Andric       return;
225639d628a0SDimitry Andric     }
225739d628a0SDimitry Andric     consumeToken();
225839d628a0SDimitry Andric   }
2259dff0c46cSDimitry Andric 
2260dff0c46cSDimitry Andric   // Parse the header name.
2261dff0c46cSDimitry Andric   if (!Tok.is(MMToken::StringLiteral)) {
2262dff0c46cSDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2263dff0c46cSDimitry Andric       << "header";
2264dff0c46cSDimitry Andric     HadError = true;
2265dff0c46cSDimitry Andric     return;
2266dff0c46cSDimitry Andric   }
226739d628a0SDimitry Andric   Module::UnresolvedHeaderDirective Header;
226859d1ed5bSDimitry Andric   Header.FileName = Tok.getString();
226959d1ed5bSDimitry Andric   Header.FileNameLoc = consumeToken();
2270302affcbSDimitry Andric   Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
22716d97bb29SDimitry Andric   Header.Kind =
22726d97bb29SDimitry Andric       (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded
22736d97bb29SDimitry Andric                                                : Map.headerRoleToKind(Role));
2274dff0c46cSDimitry Andric 
2275dff0c46cSDimitry Andric   // Check whether we already have an umbrella.
2276302affcbSDimitry Andric   if (Header.IsUmbrella && ActiveModule->Umbrella) {
227759d1ed5bSDimitry Andric     Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2278dff0c46cSDimitry Andric       << ActiveModule->getFullModuleName();
2279dff0c46cSDimitry Andric     HadError = true;
2280dff0c46cSDimitry Andric     return;
2281dff0c46cSDimitry Andric   }
2282dff0c46cSDimitry Andric 
22836d97bb29SDimitry Andric   // If we were given stat information, parse it so we can skip looking for
22846d97bb29SDimitry Andric   // the file.
22856d97bb29SDimitry Andric   if (Tok.is(MMToken::LBrace)) {
22866d97bb29SDimitry Andric     SourceLocation LBraceLoc = consumeToken();
2287dff0c46cSDimitry Andric 
22886d97bb29SDimitry Andric     while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
22896d97bb29SDimitry Andric       enum Attribute { Size, ModTime, Unknown };
22906d97bb29SDimitry Andric       StringRef Str = Tok.getString();
22916d97bb29SDimitry Andric       SourceLocation Loc = consumeToken();
22926d97bb29SDimitry Andric       switch (llvm::StringSwitch<Attribute>(Str)
22936d97bb29SDimitry Andric                   .Case("size", Size)
22946d97bb29SDimitry Andric                   .Case("mtime", ModTime)
22956d97bb29SDimitry Andric                   .Default(Unknown)) {
22966d97bb29SDimitry Andric       case Size:
22976d97bb29SDimitry Andric         if (Header.Size)
22986d97bb29SDimitry Andric           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
22996d97bb29SDimitry Andric         if (!Tok.is(MMToken::IntegerLiteral)) {
23006d97bb29SDimitry Andric           Diags.Report(Tok.getLocation(),
23016d97bb29SDimitry Andric                        diag::err_mmap_invalid_header_attribute_value) << Str;
23026d97bb29SDimitry Andric           skipUntil(MMToken::RBrace);
23036d97bb29SDimitry Andric           break;
23046d97bb29SDimitry Andric         }
23056d97bb29SDimitry Andric         Header.Size = Tok.getInteger();
23066d97bb29SDimitry Andric         consumeToken();
23076d97bb29SDimitry Andric         break;
23086d97bb29SDimitry Andric 
23096d97bb29SDimitry Andric       case ModTime:
23106d97bb29SDimitry Andric         if (Header.ModTime)
23116d97bb29SDimitry Andric           Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
23126d97bb29SDimitry Andric         if (!Tok.is(MMToken::IntegerLiteral)) {
23136d97bb29SDimitry Andric           Diags.Report(Tok.getLocation(),
23146d97bb29SDimitry Andric                        diag::err_mmap_invalid_header_attribute_value) << Str;
23156d97bb29SDimitry Andric           skipUntil(MMToken::RBrace);
23166d97bb29SDimitry Andric           break;
23176d97bb29SDimitry Andric         }
23186d97bb29SDimitry Andric         Header.ModTime = Tok.getInteger();
23196d97bb29SDimitry Andric         consumeToken();
23206d97bb29SDimitry Andric         break;
23216d97bb29SDimitry Andric 
23226d97bb29SDimitry Andric       case Unknown:
23236d97bb29SDimitry Andric         Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
23246d97bb29SDimitry Andric         skipUntil(MMToken::RBrace);
23256d97bb29SDimitry Andric         break;
23266d97bb29SDimitry Andric       }
2327dff0c46cSDimitry Andric     }
2328dff0c46cSDimitry Andric 
23296d97bb29SDimitry Andric     if (Tok.is(MMToken::RBrace))
23306d97bb29SDimitry Andric       consumeToken();
23316d97bb29SDimitry Andric     else {
23326d97bb29SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
23336d97bb29SDimitry Andric       Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2334dff0c46cSDimitry Andric       HadError = true;
2335dff0c46cSDimitry Andric     }
233639d628a0SDimitry Andric   }
233739d628a0SDimitry Andric 
23384ba319b5SDimitry Andric   bool NeedsFramework = false;
23394ba319b5SDimitry Andric   Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
23404ba319b5SDimitry Andric 
23414ba319b5SDimitry Andric   if (NeedsFramework && ActiveModule)
23424ba319b5SDimitry Andric     Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
23434ba319b5SDimitry Andric       << ActiveModule->getFullModuleName()
23444ba319b5SDimitry Andric       << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
2345dff0c46cSDimitry Andric }
2346dff0c46cSDimitry Andric 
compareModuleHeaders(const Module::Header * A,const Module::Header * B)23470623d748SDimitry Andric static int compareModuleHeaders(const Module::Header *A,
23480623d748SDimitry Andric                                 const Module::Header *B) {
23490623d748SDimitry Andric   return A->NameAsWritten.compare(B->NameAsWritten);
23500623d748SDimitry Andric }
23510623d748SDimitry Andric 
23524ba319b5SDimitry Andric /// Parse an umbrella directory declaration.
2353dff0c46cSDimitry Andric ///
2354dff0c46cSDimitry Andric ///   umbrella-dir-declaration:
2355dff0c46cSDimitry Andric ///     umbrella string-literal
parseUmbrellaDirDecl(SourceLocation UmbrellaLoc)2356dff0c46cSDimitry Andric void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
2357dff0c46cSDimitry Andric   // Parse the directory name.
2358dff0c46cSDimitry Andric   if (!Tok.is(MMToken::StringLiteral)) {
2359dff0c46cSDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2360dff0c46cSDimitry Andric       << "umbrella";
2361dff0c46cSDimitry Andric     HadError = true;
2362dff0c46cSDimitry Andric     return;
2363dff0c46cSDimitry Andric   }
2364dff0c46cSDimitry Andric 
2365dff0c46cSDimitry Andric   std::string DirName = Tok.getString();
2366dff0c46cSDimitry Andric   SourceLocation DirNameLoc = consumeToken();
2367dff0c46cSDimitry Andric 
2368dff0c46cSDimitry Andric   // Check whether we already have an umbrella.
2369dff0c46cSDimitry Andric   if (ActiveModule->Umbrella) {
2370dff0c46cSDimitry Andric     Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
2371dff0c46cSDimitry Andric       << ActiveModule->getFullModuleName();
2372dff0c46cSDimitry Andric     HadError = true;
2373dff0c46cSDimitry Andric     return;
2374dff0c46cSDimitry Andric   }
2375dff0c46cSDimitry Andric 
2376dff0c46cSDimitry Andric   // Look for this file.
237759d1ed5bSDimitry Andric   const DirectoryEntry *Dir = nullptr;
2378dff0c46cSDimitry Andric   if (llvm::sys::path::is_absolute(DirName))
2379dff0c46cSDimitry Andric     Dir = SourceMgr.getFileManager().getDirectory(DirName);
2380dff0c46cSDimitry Andric   else {
2381dff0c46cSDimitry Andric     SmallString<128> PathName;
2382dff0c46cSDimitry Andric     PathName = Directory->getName();
2383dff0c46cSDimitry Andric     llvm::sys::path::append(PathName, DirName);
2384dff0c46cSDimitry Andric     Dir = SourceMgr.getFileManager().getDirectory(PathName);
2385dff0c46cSDimitry Andric   }
2386dff0c46cSDimitry Andric 
2387dff0c46cSDimitry Andric   if (!Dir) {
23886bc11b14SDimitry Andric     Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
2389dff0c46cSDimitry Andric       << DirName;
2390dff0c46cSDimitry Andric     return;
2391dff0c46cSDimitry Andric   }
2392dff0c46cSDimitry Andric 
23930623d748SDimitry Andric   if (UsesRequiresExcludedHack.count(ActiveModule)) {
23940623d748SDimitry Andric     // Mark this header 'textual' (see doc comment for
23950623d748SDimitry Andric     // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
23960623d748SDimitry Andric     // directory is relatively expensive, in practice this only applies to the
23970623d748SDimitry Andric     // uncommonly used Tcl module on Darwin platforms.
23980623d748SDimitry Andric     std::error_code EC;
23990623d748SDimitry Andric     SmallVector<Module::Header, 6> Headers;
2400*b5893f02SDimitry Andric     llvm::vfs::FileSystem &FS =
2401*b5893f02SDimitry Andric         *SourceMgr.getFileManager().getVirtualFileSystem();
2402*b5893f02SDimitry Andric     for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
24030623d748SDimitry Andric          I != E && !EC; I.increment(EC)) {
2404*b5893f02SDimitry Andric       if (const FileEntry *FE = SourceMgr.getFileManager().getFile(I->path())) {
24050623d748SDimitry Andric 
2406*b5893f02SDimitry Andric         Module::Header Header = {I->path(), FE};
24070623d748SDimitry Andric         Headers.push_back(std::move(Header));
24080623d748SDimitry Andric       }
24090623d748SDimitry Andric     }
24100623d748SDimitry Andric 
24110623d748SDimitry Andric     // Sort header paths so that the pcm doesn't depend on iteration order.
24120623d748SDimitry Andric     llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
24130623d748SDimitry Andric 
24140623d748SDimitry Andric     for (auto &Header : Headers)
24150623d748SDimitry Andric       Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
24160623d748SDimitry Andric     return;
24170623d748SDimitry Andric   }
24180623d748SDimitry Andric 
2419dff0c46cSDimitry Andric   if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
2420dff0c46cSDimitry Andric     Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
2421dff0c46cSDimitry Andric       << OwningModule->getFullModuleName();
2422dff0c46cSDimitry Andric     HadError = true;
2423dff0c46cSDimitry Andric     return;
2424dff0c46cSDimitry Andric   }
2425dff0c46cSDimitry Andric 
2426dff0c46cSDimitry Andric   // Record this umbrella directory.
242733956c43SDimitry Andric   Map.setUmbrellaDir(ActiveModule, Dir, DirName);
2428dff0c46cSDimitry Andric }
2429dff0c46cSDimitry Andric 
24304ba319b5SDimitry Andric /// Parse a module export declaration.
2431dff0c46cSDimitry Andric ///
2432dff0c46cSDimitry Andric ///   export-declaration:
2433dff0c46cSDimitry Andric ///     'export' wildcard-module-id
2434dff0c46cSDimitry Andric ///
2435dff0c46cSDimitry Andric ///   wildcard-module-id:
2436dff0c46cSDimitry Andric ///     identifier
2437dff0c46cSDimitry Andric ///     '*'
2438dff0c46cSDimitry Andric ///     identifier '.' wildcard-module-id
parseExportDecl()2439dff0c46cSDimitry Andric void ModuleMapParser::parseExportDecl() {
2440dff0c46cSDimitry Andric   assert(Tok.is(MMToken::ExportKeyword));
2441dff0c46cSDimitry Andric   SourceLocation ExportLoc = consumeToken();
2442dff0c46cSDimitry Andric 
2443dff0c46cSDimitry Andric   // Parse the module-id with an optional wildcard at the end.
2444dff0c46cSDimitry Andric   ModuleId ParsedModuleId;
2445dff0c46cSDimitry Andric   bool Wildcard = false;
2446dff0c46cSDimitry Andric   do {
244739d628a0SDimitry Andric     // FIXME: Support string-literal module names here.
2448dff0c46cSDimitry Andric     if (Tok.is(MMToken::Identifier)) {
2449dff0c46cSDimitry Andric       ParsedModuleId.push_back(std::make_pair(Tok.getString(),
2450dff0c46cSDimitry Andric                                               Tok.getLocation()));
2451dff0c46cSDimitry Andric       consumeToken();
2452dff0c46cSDimitry Andric 
2453dff0c46cSDimitry Andric       if (Tok.is(MMToken::Period)) {
2454dff0c46cSDimitry Andric         consumeToken();
2455dff0c46cSDimitry Andric         continue;
2456dff0c46cSDimitry Andric       }
2457dff0c46cSDimitry Andric 
2458dff0c46cSDimitry Andric       break;
2459dff0c46cSDimitry Andric     }
2460dff0c46cSDimitry Andric 
2461dff0c46cSDimitry Andric     if(Tok.is(MMToken::Star)) {
2462dff0c46cSDimitry Andric       Wildcard = true;
2463dff0c46cSDimitry Andric       consumeToken();
2464dff0c46cSDimitry Andric       break;
2465dff0c46cSDimitry Andric     }
2466dff0c46cSDimitry Andric 
2467f785676fSDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
2468dff0c46cSDimitry Andric     HadError = true;
2469dff0c46cSDimitry Andric     return;
2470dff0c46cSDimitry Andric   } while (true);
2471dff0c46cSDimitry Andric 
2472dff0c46cSDimitry Andric   Module::UnresolvedExportDecl Unresolved = {
2473dff0c46cSDimitry Andric     ExportLoc, ParsedModuleId, Wildcard
2474dff0c46cSDimitry Andric   };
2475dff0c46cSDimitry Andric   ActiveModule->UnresolvedExports.push_back(Unresolved);
2476dff0c46cSDimitry Andric }
2477dff0c46cSDimitry Andric 
24784ba319b5SDimitry Andric /// Parse a module export_as declaration.
24799a199699SDimitry Andric ///
24809a199699SDimitry Andric ///   export-as-declaration:
24819a199699SDimitry Andric ///     'export_as' identifier
parseExportAsDecl()24829a199699SDimitry Andric void ModuleMapParser::parseExportAsDecl() {
24839a199699SDimitry Andric   assert(Tok.is(MMToken::ExportAsKeyword));
24849a199699SDimitry Andric   consumeToken();
24859a199699SDimitry Andric 
24869a199699SDimitry Andric   if (!Tok.is(MMToken::Identifier)) {
24879a199699SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
24889a199699SDimitry Andric     HadError = true;
24899a199699SDimitry Andric     return;
24909a199699SDimitry Andric   }
24919a199699SDimitry Andric 
24929a199699SDimitry Andric   if (ActiveModule->Parent) {
24939a199699SDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
24949a199699SDimitry Andric     consumeToken();
24959a199699SDimitry Andric     return;
24969a199699SDimitry Andric   }
24979a199699SDimitry Andric 
24989a199699SDimitry Andric   if (!ActiveModule->ExportAsModule.empty()) {
24999a199699SDimitry Andric     if (ActiveModule->ExportAsModule == Tok.getString()) {
25009a199699SDimitry Andric       Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
25019a199699SDimitry Andric         << ActiveModule->Name << Tok.getString();
25029a199699SDimitry Andric     } else {
25039a199699SDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
25049a199699SDimitry Andric         << ActiveModule->Name << ActiveModule->ExportAsModule
25059a199699SDimitry Andric         << Tok.getString();
25069a199699SDimitry Andric     }
25079a199699SDimitry Andric   }
25089a199699SDimitry Andric 
25099a199699SDimitry Andric   ActiveModule->ExportAsModule = Tok.getString();
25104ba319b5SDimitry Andric   Map.addLinkAsDependency(ActiveModule);
25114ba319b5SDimitry Andric 
25129a199699SDimitry Andric   consumeToken();
25139a199699SDimitry Andric }
25149a199699SDimitry Andric 
25154ba319b5SDimitry Andric /// Parse a module use declaration.
2516f785676fSDimitry Andric ///
251733956c43SDimitry Andric ///   use-declaration:
251833956c43SDimitry Andric ///     'use' wildcard-module-id
parseUseDecl()2519f785676fSDimitry Andric void ModuleMapParser::parseUseDecl() {
2520f785676fSDimitry Andric   assert(Tok.is(MMToken::UseKeyword));
252133956c43SDimitry Andric   auto KWLoc = consumeToken();
2522f785676fSDimitry Andric   // Parse the module-id.
2523f785676fSDimitry Andric   ModuleId ParsedModuleId;
252459d1ed5bSDimitry Andric   parseModuleId(ParsedModuleId);
2525f785676fSDimitry Andric 
252633956c43SDimitry Andric   if (ActiveModule->Parent)
252733956c43SDimitry Andric     Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
252833956c43SDimitry Andric   else
2529f785676fSDimitry Andric     ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
2530f785676fSDimitry Andric }
2531f785676fSDimitry Andric 
25324ba319b5SDimitry Andric /// Parse a link declaration.
2533139f7f9bSDimitry Andric ///
2534139f7f9bSDimitry Andric ///   module-declaration:
2535139f7f9bSDimitry Andric ///     'link' 'framework'[opt] string-literal
parseLinkDecl()2536139f7f9bSDimitry Andric void ModuleMapParser::parseLinkDecl() {
2537139f7f9bSDimitry Andric   assert(Tok.is(MMToken::LinkKeyword));
2538139f7f9bSDimitry Andric   SourceLocation LinkLoc = consumeToken();
2539139f7f9bSDimitry Andric 
2540139f7f9bSDimitry Andric   // Parse the optional 'framework' keyword.
2541139f7f9bSDimitry Andric   bool IsFramework = false;
2542139f7f9bSDimitry Andric   if (Tok.is(MMToken::FrameworkKeyword)) {
2543139f7f9bSDimitry Andric     consumeToken();
2544139f7f9bSDimitry Andric     IsFramework = true;
2545139f7f9bSDimitry Andric   }
2546139f7f9bSDimitry Andric 
2547139f7f9bSDimitry Andric   // Parse the library name
2548139f7f9bSDimitry Andric   if (!Tok.is(MMToken::StringLiteral)) {
2549139f7f9bSDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
2550139f7f9bSDimitry Andric       << IsFramework << SourceRange(LinkLoc);
2551139f7f9bSDimitry Andric     HadError = true;
2552139f7f9bSDimitry Andric     return;
2553139f7f9bSDimitry Andric   }
2554139f7f9bSDimitry Andric 
2555139f7f9bSDimitry Andric   std::string LibraryName = Tok.getString();
2556139f7f9bSDimitry Andric   consumeToken();
2557139f7f9bSDimitry Andric   ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
2558139f7f9bSDimitry Andric                                                             IsFramework));
2559139f7f9bSDimitry Andric }
2560139f7f9bSDimitry Andric 
25614ba319b5SDimitry Andric /// Parse a configuration macro declaration.
2562139f7f9bSDimitry Andric ///
2563139f7f9bSDimitry Andric ///   module-declaration:
2564139f7f9bSDimitry Andric ///     'config_macros' attributes[opt] config-macro-list?
2565139f7f9bSDimitry Andric ///
2566139f7f9bSDimitry Andric ///   config-macro-list:
2567139f7f9bSDimitry Andric ///     identifier (',' identifier)?
parseConfigMacros()2568139f7f9bSDimitry Andric void ModuleMapParser::parseConfigMacros() {
2569139f7f9bSDimitry Andric   assert(Tok.is(MMToken::ConfigMacros));
2570139f7f9bSDimitry Andric   SourceLocation ConfigMacrosLoc = consumeToken();
2571139f7f9bSDimitry Andric 
2572139f7f9bSDimitry Andric   // Only top-level modules can have configuration macros.
2573139f7f9bSDimitry Andric   if (ActiveModule->Parent) {
2574139f7f9bSDimitry Andric     Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
2575139f7f9bSDimitry Andric   }
2576139f7f9bSDimitry Andric 
2577139f7f9bSDimitry Andric   // Parse the optional attributes.
2578139f7f9bSDimitry Andric   Attributes Attrs;
2579e7145dcbSDimitry Andric   if (parseOptionalAttributes(Attrs))
2580e7145dcbSDimitry Andric     return;
2581e7145dcbSDimitry Andric 
2582139f7f9bSDimitry Andric   if (Attrs.IsExhaustive && !ActiveModule->Parent) {
2583139f7f9bSDimitry Andric     ActiveModule->ConfigMacrosExhaustive = true;
2584139f7f9bSDimitry Andric   }
2585139f7f9bSDimitry Andric 
2586139f7f9bSDimitry Andric   // If we don't have an identifier, we're done.
258739d628a0SDimitry Andric   // FIXME: Support macros with the same name as a keyword here.
2588139f7f9bSDimitry Andric   if (!Tok.is(MMToken::Identifier))
2589139f7f9bSDimitry Andric     return;
2590139f7f9bSDimitry Andric 
2591139f7f9bSDimitry Andric   // Consume the first identifier.
2592139f7f9bSDimitry Andric   if (!ActiveModule->Parent) {
2593139f7f9bSDimitry Andric     ActiveModule->ConfigMacros.push_back(Tok.getString().str());
2594139f7f9bSDimitry Andric   }
2595139f7f9bSDimitry Andric   consumeToken();
2596139f7f9bSDimitry Andric 
2597139f7f9bSDimitry Andric   do {
2598139f7f9bSDimitry Andric     // If there's a comma, consume it.
2599139f7f9bSDimitry Andric     if (!Tok.is(MMToken::Comma))
2600139f7f9bSDimitry Andric       break;
2601139f7f9bSDimitry Andric     consumeToken();
2602139f7f9bSDimitry Andric 
2603139f7f9bSDimitry Andric     // We expect to see a macro name here.
260439d628a0SDimitry Andric     // FIXME: Support macros with the same name as a keyword here.
2605139f7f9bSDimitry Andric     if (!Tok.is(MMToken::Identifier)) {
2606139f7f9bSDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
2607139f7f9bSDimitry Andric       break;
2608139f7f9bSDimitry Andric     }
2609139f7f9bSDimitry Andric 
2610139f7f9bSDimitry Andric     // Consume the macro name.
2611139f7f9bSDimitry Andric     if (!ActiveModule->Parent) {
2612139f7f9bSDimitry Andric       ActiveModule->ConfigMacros.push_back(Tok.getString().str());
2613139f7f9bSDimitry Andric     }
2614139f7f9bSDimitry Andric     consumeToken();
2615139f7f9bSDimitry Andric   } while (true);
2616139f7f9bSDimitry Andric }
2617139f7f9bSDimitry Andric 
26184ba319b5SDimitry Andric /// Format a module-id into a string.
formatModuleId(const ModuleId & Id)2619139f7f9bSDimitry Andric static std::string formatModuleId(const ModuleId &Id) {
2620139f7f9bSDimitry Andric   std::string result;
2621139f7f9bSDimitry Andric   {
2622139f7f9bSDimitry Andric     llvm::raw_string_ostream OS(result);
2623139f7f9bSDimitry Andric 
2624139f7f9bSDimitry Andric     for (unsigned I = 0, N = Id.size(); I != N; ++I) {
2625139f7f9bSDimitry Andric       if (I)
2626139f7f9bSDimitry Andric         OS << ".";
2627139f7f9bSDimitry Andric       OS << Id[I].first;
2628139f7f9bSDimitry Andric     }
2629139f7f9bSDimitry Andric   }
2630139f7f9bSDimitry Andric 
2631139f7f9bSDimitry Andric   return result;
2632139f7f9bSDimitry Andric }
2633139f7f9bSDimitry Andric 
26344ba319b5SDimitry Andric /// Parse a conflict declaration.
2635139f7f9bSDimitry Andric ///
2636139f7f9bSDimitry Andric ///   module-declaration:
2637139f7f9bSDimitry Andric ///     'conflict' module-id ',' string-literal
parseConflict()2638139f7f9bSDimitry Andric void ModuleMapParser::parseConflict() {
2639139f7f9bSDimitry Andric   assert(Tok.is(MMToken::Conflict));
2640139f7f9bSDimitry Andric   SourceLocation ConflictLoc = consumeToken();
2641139f7f9bSDimitry Andric   Module::UnresolvedConflict Conflict;
2642139f7f9bSDimitry Andric 
2643139f7f9bSDimitry Andric   // Parse the module-id.
2644139f7f9bSDimitry Andric   if (parseModuleId(Conflict.Id))
2645139f7f9bSDimitry Andric     return;
2646139f7f9bSDimitry Andric 
2647139f7f9bSDimitry Andric   // Parse the ','.
2648139f7f9bSDimitry Andric   if (!Tok.is(MMToken::Comma)) {
2649139f7f9bSDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
2650139f7f9bSDimitry Andric       << SourceRange(ConflictLoc);
2651139f7f9bSDimitry Andric     return;
2652139f7f9bSDimitry Andric   }
2653139f7f9bSDimitry Andric   consumeToken();
2654139f7f9bSDimitry Andric 
2655139f7f9bSDimitry Andric   // Parse the message.
2656139f7f9bSDimitry Andric   if (!Tok.is(MMToken::StringLiteral)) {
2657139f7f9bSDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
2658139f7f9bSDimitry Andric       << formatModuleId(Conflict.Id);
2659139f7f9bSDimitry Andric     return;
2660139f7f9bSDimitry Andric   }
2661139f7f9bSDimitry Andric   Conflict.Message = Tok.getString().str();
2662139f7f9bSDimitry Andric   consumeToken();
2663139f7f9bSDimitry Andric 
2664139f7f9bSDimitry Andric   // Add this unresolved conflict.
2665139f7f9bSDimitry Andric   ActiveModule->UnresolvedConflicts.push_back(Conflict);
2666139f7f9bSDimitry Andric }
2667139f7f9bSDimitry Andric 
26684ba319b5SDimitry Andric /// Parse an inferred module declaration (wildcard modules).
26693861d79fSDimitry Andric ///
26703861d79fSDimitry Andric ///   module-declaration:
26713861d79fSDimitry Andric ///     'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
26723861d79fSDimitry Andric ///       { inferred-module-member* }
26733861d79fSDimitry Andric ///
26743861d79fSDimitry Andric ///   inferred-module-member:
26753861d79fSDimitry Andric ///     'export' '*'
26763861d79fSDimitry Andric ///     'exclude' identifier
parseInferredModuleDecl(bool Framework,bool Explicit)26773861d79fSDimitry Andric void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
2678dff0c46cSDimitry Andric   assert(Tok.is(MMToken::Star));
2679dff0c46cSDimitry Andric   SourceLocation StarLoc = consumeToken();
2680dff0c46cSDimitry Andric   bool Failed = false;
2681dff0c46cSDimitry Andric 
2682dff0c46cSDimitry Andric   // Inferred modules must be submodules.
26833861d79fSDimitry Andric   if (!ActiveModule && !Framework) {
2684dff0c46cSDimitry Andric     Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
2685dff0c46cSDimitry Andric     Failed = true;
2686dff0c46cSDimitry Andric   }
2687dff0c46cSDimitry Andric 
26883861d79fSDimitry Andric   if (ActiveModule) {
2689dff0c46cSDimitry Andric     // Inferred modules must have umbrella directories.
269059d1ed5bSDimitry Andric     if (!Failed && ActiveModule->IsAvailable &&
269159d1ed5bSDimitry Andric         !ActiveModule->getUmbrellaDir()) {
2692dff0c46cSDimitry Andric       Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
2693dff0c46cSDimitry Andric       Failed = true;
2694dff0c46cSDimitry Andric     }
2695dff0c46cSDimitry Andric 
2696dff0c46cSDimitry Andric     // Check for redefinition of an inferred module.
2697dff0c46cSDimitry Andric     if (!Failed && ActiveModule->InferSubmodules) {
2698dff0c46cSDimitry Andric       Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2699dff0c46cSDimitry Andric       if (ActiveModule->InferredSubmoduleLoc.isValid())
2700dff0c46cSDimitry Andric         Diags.Report(ActiveModule->InferredSubmoduleLoc,
2701dff0c46cSDimitry Andric                      diag::note_mmap_prev_definition);
2702dff0c46cSDimitry Andric       Failed = true;
2703dff0c46cSDimitry Andric     }
2704dff0c46cSDimitry Andric 
27053861d79fSDimitry Andric     // Check for the 'framework' keyword, which is not permitted here.
27063861d79fSDimitry Andric     if (Framework) {
27073861d79fSDimitry Andric       Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
27083861d79fSDimitry Andric       Framework = false;
27093861d79fSDimitry Andric     }
27103861d79fSDimitry Andric   } else if (Explicit) {
27113861d79fSDimitry Andric     Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
27123861d79fSDimitry Andric     Explicit = false;
27133861d79fSDimitry Andric   }
27143861d79fSDimitry Andric 
2715dff0c46cSDimitry Andric   // If there were any problems with this inferred submodule, skip its body.
2716dff0c46cSDimitry Andric   if (Failed) {
2717dff0c46cSDimitry Andric     if (Tok.is(MMToken::LBrace)) {
2718dff0c46cSDimitry Andric       consumeToken();
2719dff0c46cSDimitry Andric       skipUntil(MMToken::RBrace);
2720dff0c46cSDimitry Andric       if (Tok.is(MMToken::RBrace))
2721dff0c46cSDimitry Andric         consumeToken();
2722dff0c46cSDimitry Andric     }
2723dff0c46cSDimitry Andric     HadError = true;
2724dff0c46cSDimitry Andric     return;
2725dff0c46cSDimitry Andric   }
2726dff0c46cSDimitry Andric 
27273861d79fSDimitry Andric   // Parse optional attributes.
27283861d79fSDimitry Andric   Attributes Attrs;
2729e7145dcbSDimitry Andric   if (parseOptionalAttributes(Attrs))
2730e7145dcbSDimitry Andric     return;
27313861d79fSDimitry Andric 
27323861d79fSDimitry Andric   if (ActiveModule) {
2733dff0c46cSDimitry Andric     // Note that we have an inferred submodule.
2734dff0c46cSDimitry Andric     ActiveModule->InferSubmodules = true;
2735dff0c46cSDimitry Andric     ActiveModule->InferredSubmoduleLoc = StarLoc;
2736dff0c46cSDimitry Andric     ActiveModule->InferExplicitSubmodules = Explicit;
27373861d79fSDimitry Andric   } else {
27383861d79fSDimitry Andric     // We'll be inferring framework modules for this directory.
27393861d79fSDimitry Andric     Map.InferredDirectories[Directory].InferModules = true;
274039d628a0SDimitry Andric     Map.InferredDirectories[Directory].Attrs = Attrs;
274159d1ed5bSDimitry Andric     Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
274259d1ed5bSDimitry Andric     // FIXME: Handle the 'framework' keyword.
27433861d79fSDimitry Andric   }
2744dff0c46cSDimitry Andric 
2745dff0c46cSDimitry Andric   // Parse the opening brace.
2746dff0c46cSDimitry Andric   if (!Tok.is(MMToken::LBrace)) {
2747dff0c46cSDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
2748dff0c46cSDimitry Andric     HadError = true;
2749dff0c46cSDimitry Andric     return;
2750dff0c46cSDimitry Andric   }
2751dff0c46cSDimitry Andric   SourceLocation LBraceLoc = consumeToken();
2752dff0c46cSDimitry Andric 
2753dff0c46cSDimitry Andric   // Parse the body of the inferred submodule.
2754dff0c46cSDimitry Andric   bool Done = false;
2755dff0c46cSDimitry Andric   do {
2756dff0c46cSDimitry Andric     switch (Tok.Kind) {
2757dff0c46cSDimitry Andric     case MMToken::EndOfFile:
2758dff0c46cSDimitry Andric     case MMToken::RBrace:
2759dff0c46cSDimitry Andric       Done = true;
2760dff0c46cSDimitry Andric       break;
2761dff0c46cSDimitry Andric 
27629a199699SDimitry Andric     case MMToken::ExcludeKeyword:
27633861d79fSDimitry Andric       if (ActiveModule) {
27643861d79fSDimitry Andric         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
276559d1ed5bSDimitry Andric           << (ActiveModule != nullptr);
27663861d79fSDimitry Andric         consumeToken();
27673861d79fSDimitry Andric         break;
27683861d79fSDimitry Andric       }
27693861d79fSDimitry Andric 
27703861d79fSDimitry Andric       consumeToken();
277139d628a0SDimitry Andric       // FIXME: Support string-literal module names here.
27723861d79fSDimitry Andric       if (!Tok.is(MMToken::Identifier)) {
27733861d79fSDimitry Andric         Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
27743861d79fSDimitry Andric         break;
27753861d79fSDimitry Andric       }
27763861d79fSDimitry Andric 
27773861d79fSDimitry Andric       Map.InferredDirectories[Directory].ExcludedModules
27783861d79fSDimitry Andric         .push_back(Tok.getString());
27793861d79fSDimitry Andric       consumeToken();
27803861d79fSDimitry Andric       break;
27813861d79fSDimitry Andric 
27823861d79fSDimitry Andric     case MMToken::ExportKeyword:
27833861d79fSDimitry Andric       if (!ActiveModule) {
27843861d79fSDimitry Andric         Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
278559d1ed5bSDimitry Andric           << (ActiveModule != nullptr);
27863861d79fSDimitry Andric         consumeToken();
27873861d79fSDimitry Andric         break;
27883861d79fSDimitry Andric       }
27893861d79fSDimitry Andric 
2790dff0c46cSDimitry Andric       consumeToken();
2791dff0c46cSDimitry Andric       if (Tok.is(MMToken::Star))
2792dff0c46cSDimitry Andric         ActiveModule->InferExportWildcard = true;
2793dff0c46cSDimitry Andric       else
2794dff0c46cSDimitry Andric         Diags.Report(Tok.getLocation(),
2795dff0c46cSDimitry Andric                      diag::err_mmap_expected_export_wildcard);
2796dff0c46cSDimitry Andric       consumeToken();
2797dff0c46cSDimitry Andric       break;
2798dff0c46cSDimitry Andric 
2799dff0c46cSDimitry Andric     case MMToken::ExplicitKeyword:
2800dff0c46cSDimitry Andric     case MMToken::ModuleKeyword:
2801dff0c46cSDimitry Andric     case MMToken::HeaderKeyword:
2802f785676fSDimitry Andric     case MMToken::PrivateKeyword:
2803dff0c46cSDimitry Andric     case MMToken::UmbrellaKeyword:
2804dff0c46cSDimitry Andric     default:
28053861d79fSDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
280659d1ed5bSDimitry Andric           << (ActiveModule != nullptr);
2807dff0c46cSDimitry Andric       consumeToken();
2808dff0c46cSDimitry Andric       break;
2809dff0c46cSDimitry Andric     }
2810dff0c46cSDimitry Andric   } while (!Done);
2811dff0c46cSDimitry Andric 
2812dff0c46cSDimitry Andric   if (Tok.is(MMToken::RBrace))
2813dff0c46cSDimitry Andric     consumeToken();
2814dff0c46cSDimitry Andric   else {
2815dff0c46cSDimitry Andric     Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2816dff0c46cSDimitry Andric     Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2817dff0c46cSDimitry Andric     HadError = true;
2818dff0c46cSDimitry Andric   }
2819dff0c46cSDimitry Andric }
2820dff0c46cSDimitry Andric 
28214ba319b5SDimitry Andric /// Parse optional attributes.
28223861d79fSDimitry Andric ///
28233861d79fSDimitry Andric ///   attributes:
28243861d79fSDimitry Andric ///     attribute attributes
28253861d79fSDimitry Andric ///     attribute
28263861d79fSDimitry Andric ///
28273861d79fSDimitry Andric ///   attribute:
28283861d79fSDimitry Andric ///     [ identifier ]
28293861d79fSDimitry Andric ///
28303861d79fSDimitry Andric /// \param Attrs Will be filled in with the parsed attributes.
28313861d79fSDimitry Andric ///
28323861d79fSDimitry Andric /// \returns true if an error occurred, false otherwise.
parseOptionalAttributes(Attributes & Attrs)28333861d79fSDimitry Andric bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
28343861d79fSDimitry Andric   bool HadError = false;
28353861d79fSDimitry Andric 
28363861d79fSDimitry Andric   while (Tok.is(MMToken::LSquare)) {
28373861d79fSDimitry Andric     // Consume the '['.
28383861d79fSDimitry Andric     SourceLocation LSquareLoc = consumeToken();
28393861d79fSDimitry Andric 
28403861d79fSDimitry Andric     // Check whether we have an attribute name here.
28413861d79fSDimitry Andric     if (!Tok.is(MMToken::Identifier)) {
28423861d79fSDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
28433861d79fSDimitry Andric       skipUntil(MMToken::RSquare);
28443861d79fSDimitry Andric       if (Tok.is(MMToken::RSquare))
28453861d79fSDimitry Andric         consumeToken();
28463861d79fSDimitry Andric       HadError = true;
28473861d79fSDimitry Andric     }
28483861d79fSDimitry Andric 
28493861d79fSDimitry Andric     // Decode the attribute name.
28503861d79fSDimitry Andric     AttributeKind Attribute
28513861d79fSDimitry Andric       = llvm::StringSwitch<AttributeKind>(Tok.getString())
2852139f7f9bSDimitry Andric           .Case("exhaustive", AT_exhaustive)
285359d1ed5bSDimitry Andric           .Case("extern_c", AT_extern_c)
285444290647SDimitry Andric           .Case("no_undeclared_includes", AT_no_undeclared_includes)
28553861d79fSDimitry Andric           .Case("system", AT_system)
28563861d79fSDimitry Andric           .Default(AT_unknown);
28573861d79fSDimitry Andric     switch (Attribute) {
28583861d79fSDimitry Andric     case AT_unknown:
28593861d79fSDimitry Andric       Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
28603861d79fSDimitry Andric         << Tok.getString();
28613861d79fSDimitry Andric       break;
28623861d79fSDimitry Andric 
28633861d79fSDimitry Andric     case AT_system:
28643861d79fSDimitry Andric       Attrs.IsSystem = true;
28653861d79fSDimitry Andric       break;
2866139f7f9bSDimitry Andric 
286759d1ed5bSDimitry Andric     case AT_extern_c:
286859d1ed5bSDimitry Andric       Attrs.IsExternC = true;
286959d1ed5bSDimitry Andric       break;
287059d1ed5bSDimitry Andric 
2871139f7f9bSDimitry Andric     case AT_exhaustive:
2872139f7f9bSDimitry Andric       Attrs.IsExhaustive = true;
2873139f7f9bSDimitry Andric       break;
287444290647SDimitry Andric 
287544290647SDimitry Andric     case AT_no_undeclared_includes:
287644290647SDimitry Andric       Attrs.NoUndeclaredIncludes = true;
287744290647SDimitry Andric       break;
28783861d79fSDimitry Andric     }
28793861d79fSDimitry Andric     consumeToken();
28803861d79fSDimitry Andric 
28813861d79fSDimitry Andric     // Consume the ']'.
28823861d79fSDimitry Andric     if (!Tok.is(MMToken::RSquare)) {
28833861d79fSDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
28843861d79fSDimitry Andric       Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
28853861d79fSDimitry Andric       skipUntil(MMToken::RSquare);
28863861d79fSDimitry Andric       HadError = true;
28873861d79fSDimitry Andric     }
28883861d79fSDimitry Andric 
28893861d79fSDimitry Andric     if (Tok.is(MMToken::RSquare))
28903861d79fSDimitry Andric       consumeToken();
28913861d79fSDimitry Andric   }
28923861d79fSDimitry Andric 
28933861d79fSDimitry Andric   return HadError;
28943861d79fSDimitry Andric }
28953861d79fSDimitry Andric 
28964ba319b5SDimitry Andric /// Parse a module map file.
2897dff0c46cSDimitry Andric ///
2898dff0c46cSDimitry Andric ///   module-map-file:
2899dff0c46cSDimitry Andric ///     module-declaration*
parseModuleMapFile()2900dff0c46cSDimitry Andric bool ModuleMapParser::parseModuleMapFile() {
2901dff0c46cSDimitry Andric   do {
2902dff0c46cSDimitry Andric     switch (Tok.Kind) {
2903dff0c46cSDimitry Andric     case MMToken::EndOfFile:
2904dff0c46cSDimitry Andric       return HadError;
2905dff0c46cSDimitry Andric 
2906dff0c46cSDimitry Andric     case MMToken::ExplicitKeyword:
2907f785676fSDimitry Andric     case MMToken::ExternKeyword:
2908dff0c46cSDimitry Andric     case MMToken::ModuleKeyword:
2909dff0c46cSDimitry Andric     case MMToken::FrameworkKeyword:
2910dff0c46cSDimitry Andric       parseModuleDecl();
2911dff0c46cSDimitry Andric       break;
2912dff0c46cSDimitry Andric 
2913dff0c46cSDimitry Andric     case MMToken::Comma:
2914139f7f9bSDimitry Andric     case MMToken::ConfigMacros:
2915139f7f9bSDimitry Andric     case MMToken::Conflict:
2916f785676fSDimitry Andric     case MMToken::Exclaim:
29173861d79fSDimitry Andric     case MMToken::ExcludeKeyword:
2918dff0c46cSDimitry Andric     case MMToken::ExportKeyword:
29199a199699SDimitry Andric     case MMToken::ExportAsKeyword:
2920dff0c46cSDimitry Andric     case MMToken::HeaderKeyword:
2921dff0c46cSDimitry Andric     case MMToken::Identifier:
2922dff0c46cSDimitry Andric     case MMToken::LBrace:
2923139f7f9bSDimitry Andric     case MMToken::LinkKeyword:
2924dff0c46cSDimitry Andric     case MMToken::LSquare:
2925dff0c46cSDimitry Andric     case MMToken::Period:
2926f785676fSDimitry Andric     case MMToken::PrivateKeyword:
2927dff0c46cSDimitry Andric     case MMToken::RBrace:
2928dff0c46cSDimitry Andric     case MMToken::RSquare:
2929dff0c46cSDimitry Andric     case MMToken::RequiresKeyword:
2930dff0c46cSDimitry Andric     case MMToken::Star:
2931dff0c46cSDimitry Andric     case MMToken::StringLiteral:
29326d97bb29SDimitry Andric     case MMToken::IntegerLiteral:
293339d628a0SDimitry Andric     case MMToken::TextualKeyword:
2934dff0c46cSDimitry Andric     case MMToken::UmbrellaKeyword:
2935f785676fSDimitry Andric     case MMToken::UseKeyword:
2936dff0c46cSDimitry Andric       Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
2937dff0c46cSDimitry Andric       HadError = true;
2938dff0c46cSDimitry Andric       consumeToken();
2939dff0c46cSDimitry Andric       break;
2940dff0c46cSDimitry Andric     }
2941dff0c46cSDimitry Andric   } while (true);
2942dff0c46cSDimitry Andric }
2943dff0c46cSDimitry Andric 
parseModuleMapFile(const FileEntry * File,bool IsSystem,const DirectoryEntry * Dir,FileID ID,unsigned * Offset,SourceLocation ExternModuleLoc)294439d628a0SDimitry Andric bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
29450f5676f4SDimitry Andric                                    const DirectoryEntry *Dir, FileID ID,
29460f5676f4SDimitry Andric                                    unsigned *Offset,
2947875ed548SDimitry Andric                                    SourceLocation ExternModuleLoc) {
29480f5676f4SDimitry Andric   assert(Target && "Missing target information");
2949139f7f9bSDimitry Andric   llvm::DenseMap<const FileEntry *, bool>::iterator Known
2950139f7f9bSDimitry Andric     = ParsedModuleMap.find(File);
2951139f7f9bSDimitry Andric   if (Known != ParsedModuleMap.end())
2952139f7f9bSDimitry Andric     return Known->second;
2953139f7f9bSDimitry Andric 
29540f5676f4SDimitry Andric   // If the module map file wasn't already entered, do so now.
29550f5676f4SDimitry Andric   if (ID.isInvalid()) {
2956a580b014SDimitry Andric     auto FileCharacter =
2957a580b014SDimitry Andric         IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
29580f5676f4SDimitry Andric     ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
29590f5676f4SDimitry Andric   }
29600f5676f4SDimitry Andric 
29610f5676f4SDimitry Andric   assert(Target && "Missing target information");
2962f785676fSDimitry Andric   const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID);
2963dff0c46cSDimitry Andric   if (!Buffer)
2964139f7f9bSDimitry Andric     return ParsedModuleMap[File] = true;
29650f5676f4SDimitry Andric   assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
29660f5676f4SDimitry Andric          "invalid buffer offset");
2967dff0c46cSDimitry Andric 
2968dff0c46cSDimitry Andric   // Parse this module map file.
29690f5676f4SDimitry Andric   Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
29700f5676f4SDimitry Andric           Buffer->getBufferStart(),
29710f5676f4SDimitry Andric           Buffer->getBufferStart() + (Offset ? *Offset : 0),
29720f5676f4SDimitry Andric           Buffer->getBufferEnd());
29730623d748SDimitry Andric   SourceLocation Start = L.getSourceLocation();
297459d1ed5bSDimitry Andric   ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
2975302affcbSDimitry Andric                          IsSystem);
2976dff0c46cSDimitry Andric   bool Result = Parser.parseModuleMapFile();
2977139f7f9bSDimitry Andric   ParsedModuleMap[File] = Result;
29780623d748SDimitry Andric 
29790f5676f4SDimitry Andric   if (Offset) {
29800f5676f4SDimitry Andric     auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
29810f5676f4SDimitry Andric     assert(Loc.first == ID && "stopped in a different file?");
29820f5676f4SDimitry Andric     *Offset = Loc.second;
29830f5676f4SDimitry Andric   }
29840f5676f4SDimitry Andric 
29850623d748SDimitry Andric   // Notify callbacks that we parsed it.
29860623d748SDimitry Andric   for (const auto &Cb : Callbacks)
29870623d748SDimitry Andric     Cb->moduleMapFileRead(Start, *File, IsSystem);
29884ba319b5SDimitry Andric 
2989dff0c46cSDimitry Andric   return Result;
2990dff0c46cSDimitry Andric }
2991