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 ⤅
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