1afd1b1c9SEugene Zelenko //===- ModuleMap.cpp - Describe the layout of modules ---------------------===//
2718292f2SDouglas Gregor //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6718292f2SDouglas Gregor //
7718292f2SDouglas Gregor //===----------------------------------------------------------------------===//
8718292f2SDouglas Gregor //
9718292f2SDouglas Gregor // This file defines the ModuleMap implementation, which describes the layout
10718292f2SDouglas Gregor // of a module as it relates to headers.
11718292f2SDouglas Gregor //
12718292f2SDouglas Gregor //===----------------------------------------------------------------------===//
13afd1b1c9SEugene Zelenko
14718292f2SDouglas Gregor #include "clang/Lex/ModuleMap.h"
15a7d03840SJordan Rose #include "clang/Basic/CharInfo.h"
16718292f2SDouglas Gregor #include "clang/Basic/Diagnostic.h"
17718292f2SDouglas Gregor #include "clang/Basic/FileManager.h"
18afd1b1c9SEugene Zelenko #include "clang/Basic/LLVM.h"
19afd1b1c9SEugene Zelenko #include "clang/Basic/LangOptions.h"
20afd1b1c9SEugene Zelenko #include "clang/Basic/Module.h"
21afd1b1c9SEugene Zelenko #include "clang/Basic/SourceLocation.h"
22afd1b1c9SEugene Zelenko #include "clang/Basic/SourceManager.h"
23718292f2SDouglas Gregor #include "clang/Basic/TargetInfo.h"
24b146baabSArgyrios Kyrtzidis #include "clang/Lex/HeaderSearch.h"
259acb99e3SRichard Smith #include "clang/Lex/HeaderSearchOptions.h"
263a02247dSChandler Carruth #include "clang/Lex/LexDiagnostic.h"
273a02247dSChandler Carruth #include "clang/Lex/Lexer.h"
283a02247dSChandler Carruth #include "clang/Lex/LiteralSupport.h"
29afd1b1c9SEugene Zelenko #include "clang/Lex/Token.h"
30afd1b1c9SEugene Zelenko #include "llvm/ADT/DenseMap.h"
31afd1b1c9SEugene Zelenko #include "llvm/ADT/None.h"
32afd1b1c9SEugene Zelenko #include "llvm/ADT/STLExtras.h"
33afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallPtrSet.h"
34afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallString.h"
35afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallVector.h"
36afd1b1c9SEugene Zelenko #include "llvm/ADT/StringMap.h"
373a02247dSChandler Carruth #include "llvm/ADT/StringRef.h"
383a02247dSChandler Carruth #include "llvm/ADT/StringSwitch.h"
39718292f2SDouglas Gregor #include "llvm/Support/Allocator.h"
40afd1b1c9SEugene Zelenko #include "llvm/Support/Compiler.h"
41afd1b1c9SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
42afd1b1c9SEugene Zelenko #include "llvm/Support/MemoryBuffer.h"
43552c169eSRafael Espindola #include "llvm/Support/Path.h"
44fc51490bSJonas Devlieghere #include "llvm/Support/VirtualFileSystem.h"
45718292f2SDouglas Gregor #include "llvm/Support/raw_ostream.h"
46afd1b1c9SEugene Zelenko #include <algorithm>
47afd1b1c9SEugene Zelenko #include <cassert>
48afd1b1c9SEugene Zelenko #include <cstdint>
49afd1b1c9SEugene Zelenko #include <cstring>
50afd1b1c9SEugene Zelenko #include <string>
51afd1b1c9SEugene Zelenko #include <system_error>
52afd1b1c9SEugene Zelenko #include <utility>
53afd1b1c9SEugene Zelenko
54718292f2SDouglas Gregor using namespace clang;
55718292f2SDouglas Gregor
anchor()56b3e902f4SRichard Trieu void ModuleMapCallbacks::anchor() {}
57b3e902f4SRichard Trieu
resolveLinkAsDependencies(Module * Mod)58a3b5f71eSBruno Cardoso Lopes void ModuleMap::resolveLinkAsDependencies(Module *Mod) {
59a3b5f71eSBruno Cardoso Lopes auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name);
60a3b5f71eSBruno Cardoso Lopes if (PendingLinkAs != PendingLinkAsModule.end()) {
61a3b5f71eSBruno Cardoso Lopes for (auto &Name : PendingLinkAs->second) {
62a3b5f71eSBruno Cardoso Lopes auto *M = findModule(Name.getKey());
63a3b5f71eSBruno Cardoso Lopes if (M)
64a3b5f71eSBruno Cardoso Lopes M->UseExportAsModuleLinkName = true;
65a3b5f71eSBruno Cardoso Lopes }
66a3b5f71eSBruno Cardoso Lopes }
67a3b5f71eSBruno Cardoso Lopes }
68a3b5f71eSBruno Cardoso Lopes
addLinkAsDependency(Module * Mod)69a3b5f71eSBruno Cardoso Lopes void ModuleMap::addLinkAsDependency(Module *Mod) {
70a3b5f71eSBruno Cardoso Lopes if (findModule(Mod->ExportAsModule))
71a3b5f71eSBruno Cardoso Lopes Mod->UseExportAsModuleLinkName = true;
72a3b5f71eSBruno Cardoso Lopes else
73a3b5f71eSBruno Cardoso Lopes PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name);
74a3b5f71eSBruno Cardoso Lopes }
75a3b5f71eSBruno Cardoso Lopes
headerRoleToKind(ModuleHeaderRole Role)76040e1266SRichard Smith Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
77040e1266SRichard Smith switch ((int)Role) {
78040e1266SRichard Smith default: llvm_unreachable("unknown header role");
79040e1266SRichard Smith case NormalHeader:
80040e1266SRichard Smith return Module::HK_Normal;
81040e1266SRichard Smith case PrivateHeader:
82040e1266SRichard Smith return Module::HK_Private;
83040e1266SRichard Smith case TextualHeader:
84040e1266SRichard Smith return Module::HK_Textual;
85040e1266SRichard Smith case PrivateHeader | TextualHeader:
86040e1266SRichard Smith return Module::HK_PrivateTextual;
87040e1266SRichard Smith }
88040e1266SRichard Smith }
89040e1266SRichard Smith
90040e1266SRichard Smith ModuleMap::ModuleHeaderRole
headerKindToRole(Module::HeaderKind Kind)91040e1266SRichard Smith ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
92040e1266SRichard Smith switch ((int)Kind) {
93040e1266SRichard Smith case Module::HK_Normal:
94040e1266SRichard Smith return NormalHeader;
95040e1266SRichard Smith case Module::HK_Private:
96040e1266SRichard Smith return PrivateHeader;
97040e1266SRichard Smith case Module::HK_Textual:
98040e1266SRichard Smith return TextualHeader;
99040e1266SRichard Smith case Module::HK_PrivateTextual:
100040e1266SRichard Smith return ModuleHeaderRole(PrivateHeader | TextualHeader);
101040e1266SRichard Smith case Module::HK_Excluded:
102040e1266SRichard Smith llvm_unreachable("unexpected header kind");
103040e1266SRichard Smith }
104040e1266SRichard Smith llvm_unreachable("unknown header kind");
105040e1266SRichard Smith }
106040e1266SRichard Smith
1072b82c2a5SDouglas Gregor Module::ExportDecl
resolveExport(Module * Mod,const Module::UnresolvedExportDecl & Unresolved,bool Complain) const1082b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod,
1092b82c2a5SDouglas Gregor const Module::UnresolvedExportDecl &Unresolved,
110e4412640SArgyrios Kyrtzidis bool Complain) const {
111f5eedd05SDouglas Gregor // We may have just a wildcard.
112f5eedd05SDouglas Gregor if (Unresolved.Id.empty()) {
113f5eedd05SDouglas Gregor assert(Unresolved.Wildcard && "Invalid unresolved export");
114d2d442caSCraig Topper return Module::ExportDecl(nullptr, true);
115f5eedd05SDouglas Gregor }
116f5eedd05SDouglas Gregor
117fb912657SDouglas Gregor // Resolve the module-id.
118fb912657SDouglas Gregor Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
119fb912657SDouglas Gregor if (!Context)
120afd1b1c9SEugene Zelenko return {};
121fb912657SDouglas Gregor
122fb912657SDouglas Gregor return Module::ExportDecl(Context, Unresolved.Wildcard);
123fb912657SDouglas Gregor }
124fb912657SDouglas Gregor
resolveModuleId(const ModuleId & Id,Module * Mod,bool Complain) const125fb912657SDouglas Gregor Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
126fb912657SDouglas Gregor bool Complain) const {
1272b82c2a5SDouglas Gregor // Find the starting module.
128fb912657SDouglas Gregor Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
1292b82c2a5SDouglas Gregor if (!Context) {
1302b82c2a5SDouglas Gregor if (Complain)
1310761a8a0SDaniel Jasper Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
132fb912657SDouglas Gregor << Id[0].first << Mod->getFullModuleName();
1332b82c2a5SDouglas Gregor
134d2d442caSCraig Topper return nullptr;
1352b82c2a5SDouglas Gregor }
1362b82c2a5SDouglas Gregor
1372b82c2a5SDouglas Gregor // Dig into the module path.
138fb912657SDouglas Gregor for (unsigned I = 1, N = Id.size(); I != N; ++I) {
139fb912657SDouglas Gregor Module *Sub = lookupModuleQualified(Id[I].first, Context);
1402b82c2a5SDouglas Gregor if (!Sub) {
1412b82c2a5SDouglas Gregor if (Complain)
1420761a8a0SDaniel Jasper Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
143fb912657SDouglas Gregor << Id[I].first << Context->getFullModuleName()
144fb912657SDouglas Gregor << SourceRange(Id[0].second, Id[I-1].second);
1452b82c2a5SDouglas Gregor
146d2d442caSCraig Topper return nullptr;
1472b82c2a5SDouglas Gregor }
1482b82c2a5SDouglas Gregor
1492b82c2a5SDouglas Gregor Context = Sub;
1502b82c2a5SDouglas Gregor }
1512b82c2a5SDouglas Gregor
152fb912657SDouglas Gregor return Context;
1532b82c2a5SDouglas Gregor }
1542b82c2a5SDouglas Gregor
1559fc8faf9SAdrian Prantl /// Append to \p Paths the set of paths needed to get to the
1561d60987fSRichard Smith /// subframework in which the given module lives.
appendSubframeworkPaths(Module * Mod,SmallVectorImpl<char> & Path)1571d60987fSRichard Smith static void appendSubframeworkPaths(Module *Mod,
1581d60987fSRichard Smith SmallVectorImpl<char> &Path) {
1591d60987fSRichard Smith // Collect the framework names from the given module to the top-level module.
1601d60987fSRichard Smith SmallVector<StringRef, 2> Paths;
1611d60987fSRichard Smith for (; Mod; Mod = Mod->Parent) {
1621d60987fSRichard Smith if (Mod->IsFramework)
1631d60987fSRichard Smith Paths.push_back(Mod->Name);
1641d60987fSRichard Smith }
1651d60987fSRichard Smith
1661d60987fSRichard Smith if (Paths.empty())
1671d60987fSRichard Smith return;
1681d60987fSRichard Smith
1691d60987fSRichard Smith // Add Frameworks/Name.framework for each subframework.
1708adb6d6dSBenjamin Kramer for (StringRef Framework : llvm::drop_begin(llvm::reverse(Paths)))
1718adb6d6dSBenjamin Kramer llvm::sys::path::append(Path, "Frameworks", Framework + ".framework");
1721d60987fSRichard Smith }
1731d60987fSRichard Smith
findHeader(Module * M,const Module::UnresolvedHeaderDirective & Header,SmallVectorImpl<char> & RelativePathName,bool & NeedsFramework)174f85db7f7SDuncan P. N. Exon Smith Optional<FileEntryRef> ModuleMap::findHeader(
1759f6020bcSBruno Cardoso Lopes Module *M, const Module::UnresolvedHeaderDirective &Header,
1769f6020bcSBruno Cardoso Lopes SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) {
1779f6020bcSBruno Cardoso Lopes // Search for the header file within the module's home directory.
1789f6020bcSBruno Cardoso Lopes auto *Directory = M->Directory;
1799f6020bcSBruno Cardoso Lopes SmallString<128> FullPathName(Directory->getName());
1809f6020bcSBruno Cardoso Lopes
181f85db7f7SDuncan P. N. Exon Smith auto GetFile = [&](StringRef Filename) -> Optional<FileEntryRef> {
182f85db7f7SDuncan P. N. Exon Smith auto File =
183f85db7f7SDuncan P. N. Exon Smith expectedToOptional(SourceMgr.getFileManager().getFileRef(Filename));
184f85db7f7SDuncan P. N. Exon Smith if (!File || (Header.Size && File->getSize() != *Header.Size) ||
185f85db7f7SDuncan P. N. Exon Smith (Header.ModTime && File->getModificationTime() != *Header.ModTime))
186f85db7f7SDuncan P. N. Exon Smith return None;
1878d323d15SHarlan Haskins return *File;
188040e1266SRichard Smith };
189040e1266SRichard Smith
190f85db7f7SDuncan P. N. Exon Smith auto GetFrameworkFile = [&]() -> Optional<FileEntryRef> {
1911d60987fSRichard Smith unsigned FullPathLength = FullPathName.size();
1921d60987fSRichard Smith appendSubframeworkPaths(M, RelativePathName);
1931d60987fSRichard Smith unsigned RelativePathLength = RelativePathName.size();
1941d60987fSRichard Smith
1951d60987fSRichard Smith // Check whether this file is in the public headers.
1961d60987fSRichard Smith llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
1971d60987fSRichard Smith llvm::sys::path::append(FullPathName, RelativePathName);
198f85db7f7SDuncan P. N. Exon Smith if (auto File = GetFile(FullPathName))
1991d60987fSRichard Smith return File;
2001d60987fSRichard Smith
2011d60987fSRichard Smith // Check whether this file is in the private headers.
2021d60987fSRichard Smith // Ideally, private modules in the form 'FrameworkName.Private' should
2031d60987fSRichard Smith // be defined as 'module FrameworkName.Private', and not as
2041d60987fSRichard Smith // 'framework module FrameworkName.Private', since a 'Private.Framework'
2051d60987fSRichard Smith // does not usually exist. However, since both are currently widely used
2061d60987fSRichard Smith // for private modules, make sure we find the right path in both cases.
2071d60987fSRichard Smith if (M->IsFramework && M->Name == "Private")
2081d60987fSRichard Smith RelativePathName.clear();
2091d60987fSRichard Smith else
2101d60987fSRichard Smith RelativePathName.resize(RelativePathLength);
2111d60987fSRichard Smith FullPathName.resize(FullPathLength);
2121d60987fSRichard Smith llvm::sys::path::append(RelativePathName, "PrivateHeaders",
2131d60987fSRichard Smith Header.FileName);
2141d60987fSRichard Smith llvm::sys::path::append(FullPathName, RelativePathName);
215040e1266SRichard Smith return GetFile(FullPathName);
2169f6020bcSBruno Cardoso Lopes };
2179f6020bcSBruno Cardoso Lopes
2189f6020bcSBruno Cardoso Lopes if (llvm::sys::path::is_absolute(Header.FileName)) {
2199f6020bcSBruno Cardoso Lopes RelativePathName.clear();
2209f6020bcSBruno Cardoso Lopes RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
2219f6020bcSBruno Cardoso Lopes return GetFile(Header.FileName);
2221d60987fSRichard Smith }
2231d60987fSRichard Smith
2249f6020bcSBruno Cardoso Lopes if (M->isPartOfFramework())
2259f6020bcSBruno Cardoso Lopes return GetFrameworkFile();
2269f6020bcSBruno Cardoso Lopes
2271d60987fSRichard Smith // Lookup for normal headers.
2281d60987fSRichard Smith llvm::sys::path::append(RelativePathName, Header.FileName);
2291d60987fSRichard Smith llvm::sys::path::append(FullPathName, RelativePathName);
230f85db7f7SDuncan P. N. Exon Smith auto NormalHdrFile = GetFile(FullPathName);
2319f6020bcSBruno Cardoso Lopes
2320b4c2ee3SSimon Pilgrim if (!NormalHdrFile && Directory->getName().endswith(".framework")) {
2339f6020bcSBruno Cardoso Lopes // The lack of 'framework' keyword in a module declaration it's a simple
2349f6020bcSBruno Cardoso Lopes // mistake we can diagnose when the header exists within the proper
2359f6020bcSBruno Cardoso Lopes // framework style path.
2369f6020bcSBruno Cardoso Lopes FullPathName.assign(Directory->getName());
2379f6020bcSBruno Cardoso Lopes RelativePathName.clear();
238d101b5d7SErich Keane if (GetFrameworkFile()) {
2399f6020bcSBruno Cardoso Lopes Diags.Report(Header.FileNameLoc,
2409f6020bcSBruno Cardoso Lopes diag::warn_mmap_incomplete_framework_module_declaration)
2419f6020bcSBruno Cardoso Lopes << Header.FileName << M->getFullModuleName();
2429f6020bcSBruno Cardoso Lopes NeedsFramework = true;
2439f6020bcSBruno Cardoso Lopes }
244f85db7f7SDuncan P. N. Exon Smith return None;
2459f6020bcSBruno Cardoso Lopes }
2469f6020bcSBruno Cardoso Lopes
2479f6020bcSBruno Cardoso Lopes return NormalHdrFile;
2481d60987fSRichard Smith }
2491d60987fSRichard Smith
resolveHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header,bool & NeedsFramework)250040e1266SRichard Smith void ModuleMap::resolveHeader(Module *Mod,
2519f6020bcSBruno Cardoso Lopes const Module::UnresolvedHeaderDirective &Header,
2529f6020bcSBruno Cardoso Lopes bool &NeedsFramework) {
253040e1266SRichard Smith SmallString<128> RelativePathName;
254f85db7f7SDuncan P. N. Exon Smith if (Optional<FileEntryRef> File =
2559f6020bcSBruno Cardoso Lopes findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
256040e1266SRichard Smith if (Header.IsUmbrella) {
257f85db7f7SDuncan P. N. Exon Smith const DirectoryEntry *UmbrellaDir = &File->getDir().getDirEntry();
258040e1266SRichard Smith if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
259040e1266SRichard Smith Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
260040e1266SRichard Smith << UmbrellaMod->getFullModuleName();
261040e1266SRichard Smith else
262040e1266SRichard Smith // Record this umbrella header.
263d3676d4bSMichael Spencer setUmbrellaHeader(Mod, *File, Header.FileName, RelativePathName.str());
264040e1266SRichard Smith } else {
265d3676d4bSMichael Spencer Module::Header H = {Header.FileName, std::string(RelativePathName.str()),
266d3676d4bSMichael Spencer *File};
267040e1266SRichard Smith if (Header.Kind == Module::HK_Excluded)
268040e1266SRichard Smith excludeHeader(Mod, H);
269040e1266SRichard Smith else
270040e1266SRichard Smith addHeader(Mod, H, headerKindToRole(Header.Kind));
271040e1266SRichard Smith }
272040e1266SRichard Smith } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
273040e1266SRichard Smith // There's a builtin header but no corresponding on-disk header. Assume
274040e1266SRichard Smith // this was supposed to modularize the builtin header alone.
275040e1266SRichard Smith } else if (Header.Kind == Module::HK_Excluded) {
276040e1266SRichard Smith // Ignore missing excluded header files. They're optional anyway.
277040e1266SRichard Smith } else {
278040e1266SRichard Smith // If we find a module that has a missing header, we mark this module as
279040e1266SRichard Smith // unavailable and store the header directive for displaying diagnostics.
280040e1266SRichard Smith Mod->MissingHeaders.push_back(Header);
281040e1266SRichard Smith // A missing header with stat information doesn't make the module
282040e1266SRichard Smith // unavailable; this keeps our behavior consistent as headers are lazily
283040e1266SRichard Smith // resolved. (Such a module still can't be built though, except from
284040e1266SRichard Smith // preprocessed source.)
285040e1266SRichard Smith if (!Header.Size && !Header.ModTime)
286fc76b4adSRichard Smith Mod->markUnavailable(/*Unimportable=*/false);
287040e1266SRichard Smith }
288040e1266SRichard Smith }
289040e1266SRichard Smith
resolveAsBuiltinHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header)290040e1266SRichard Smith bool ModuleMap::resolveAsBuiltinHeader(
291040e1266SRichard Smith Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
292040e1266SRichard Smith if (Header.Kind == Module::HK_Excluded ||
293040e1266SRichard Smith llvm::sys::path::is_absolute(Header.FileName) ||
294040e1266SRichard Smith Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
295040e1266SRichard Smith !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
296040e1266SRichard Smith !isBuiltinHeader(Header.FileName))
297040e1266SRichard Smith return false;
2981d60987fSRichard Smith
2991d60987fSRichard Smith // This is a system module with a top-level header. This header
3001d60987fSRichard Smith // may have a counterpart (or replacement) in the set of headers
3011d60987fSRichard Smith // supplied by Clang. Find that builtin header.
302040e1266SRichard Smith SmallString<128> Path;
303040e1266SRichard Smith llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
30464d8c781SDuncan P. N. Exon Smith auto File = SourceMgr.getFileManager().getFile(Path);
305040e1266SRichard Smith if (!File)
306040e1266SRichard Smith return false;
307040e1266SRichard Smith
308040e1266SRichard Smith auto Role = headerKindToRole(Header.Kind);
309d3676d4bSMichael Spencer Module::Header H = {Header.FileName, std::string(Path.str()), *File};
310040e1266SRichard Smith addHeader(Mod, H, Role);
311040e1266SRichard Smith return true;
3121d60987fSRichard Smith }
3131d60987fSRichard Smith
ModuleMap(SourceManager & SourceMgr,DiagnosticsEngine & Diags,const LangOptions & LangOpts,const TargetInfo * Target,HeaderSearch & HeaderInfo)3140761a8a0SDaniel Jasper ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
315b146baabSArgyrios Kyrtzidis const LangOptions &LangOpts, const TargetInfo *Target,
316b146baabSArgyrios Kyrtzidis HeaderSearch &HeaderInfo)
3170761a8a0SDaniel Jasper : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
318056bf77fSRichard Smith HeaderInfo(HeaderInfo) {
3190414b857SRichard Smith MMapLangOpts.LineComment = true;
3200414b857SRichard Smith }
321718292f2SDouglas Gregor
~ModuleMap()322718292f2SDouglas Gregor ModuleMap::~ModuleMap() {
32321668754SDavide Italiano for (auto &M : Modules)
32421668754SDavide Italiano delete M.getValue();
3258587dfd9SBruno Cardoso Lopes for (auto *M : ShadowModules)
3268587dfd9SBruno Cardoso Lopes delete M;
327718292f2SDouglas Gregor }
328718292f2SDouglas Gregor
setTarget(const TargetInfo & Target)32989929282SDouglas Gregor void ModuleMap::setTarget(const TargetInfo &Target) {
33089929282SDouglas Gregor assert((!this->Target || this->Target == &Target) &&
33189929282SDouglas Gregor "Improper target override");
33289929282SDouglas Gregor this->Target = &Target;
33389929282SDouglas Gregor }
33489929282SDouglas Gregor
3359fc8faf9SAdrian Prantl /// "Sanitize" a filename so that it can be used as an identifier.
sanitizeFilenameAsIdentifier(StringRef Name,SmallVectorImpl<char> & Buffer)336056396aeSDouglas Gregor static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
337056396aeSDouglas Gregor SmallVectorImpl<char> &Buffer) {
338056396aeSDouglas Gregor if (Name.empty())
339056396aeSDouglas Gregor return Name;
340056396aeSDouglas Gregor
341601102d2SCorentin Jabot if (!isValidAsciiIdentifier(Name)) {
342056396aeSDouglas Gregor // If we don't already have something with the form of an identifier,
343056396aeSDouglas Gregor // create a buffer with the sanitized name.
344056396aeSDouglas Gregor Buffer.clear();
345a7d03840SJordan Rose if (isDigit(Name[0]))
346056396aeSDouglas Gregor Buffer.push_back('_');
347056396aeSDouglas Gregor Buffer.reserve(Buffer.size() + Name.size());
348056396aeSDouglas Gregor for (unsigned I = 0, N = Name.size(); I != N; ++I) {
349601102d2SCorentin Jabot if (isAsciiIdentifierContinue(Name[I]))
350056396aeSDouglas Gregor Buffer.push_back(Name[I]);
351056396aeSDouglas Gregor else
352056396aeSDouglas Gregor Buffer.push_back('_');
353056396aeSDouglas Gregor }
354056396aeSDouglas Gregor
355056396aeSDouglas Gregor Name = StringRef(Buffer.data(), Buffer.size());
356056396aeSDouglas Gregor }
357056396aeSDouglas Gregor
358056396aeSDouglas Gregor while (llvm::StringSwitch<bool>(Name)
359056396aeSDouglas Gregor #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
360056396aeSDouglas Gregor #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
361056396aeSDouglas Gregor #include "clang/Basic/TokenKinds.def"
362056396aeSDouglas Gregor .Default(false)) {
363056396aeSDouglas Gregor if (Name.data() != Buffer.data())
364056396aeSDouglas Gregor Buffer.append(Name.begin(), Name.end());
365056396aeSDouglas Gregor Buffer.push_back('_');
366056396aeSDouglas Gregor Name = StringRef(Buffer.data(), Buffer.size());
367056396aeSDouglas Gregor }
368056396aeSDouglas Gregor
369056396aeSDouglas Gregor return Name;
370056396aeSDouglas Gregor }
371056396aeSDouglas Gregor
3729fc8faf9SAdrian Prantl /// Determine whether the given file name is the name of a builtin
37334d52749SDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system
37434d52749SDouglas Gregor /// headers.
isBuiltinHeader(StringRef FileName)375ba1b5c98SBruno Cardoso Lopes bool ModuleMap::isBuiltinHeader(StringRef FileName) {
37634d52749SDouglas Gregor return llvm::StringSwitch<bool>(FileName)
37734d52749SDouglas Gregor .Case("float.h", true)
37834d52749SDouglas Gregor .Case("iso646.h", true)
37934d52749SDouglas Gregor .Case("limits.h", true)
38034d52749SDouglas Gregor .Case("stdalign.h", true)
38134d52749SDouglas Gregor .Case("stdarg.h", true)
3823c4b1290SBen Langmuir .Case("stdatomic.h", true)
38334d52749SDouglas Gregor .Case("stdbool.h", true)
38434d52749SDouglas Gregor .Case("stddef.h", true)
38534d52749SDouglas Gregor .Case("stdint.h", true)
38634d52749SDouglas Gregor .Case("tgmath.h", true)
38734d52749SDouglas Gregor .Case("unwind.h", true)
38834d52749SDouglas Gregor .Default(false);
38934d52749SDouglas Gregor }
39034d52749SDouglas Gregor
isBuiltinHeader(const FileEntry * File)3918d74de9dSMartin Boehme bool ModuleMap::isBuiltinHeader(const FileEntry *File) {
3928d74de9dSMartin Boehme return File->getDir() == BuiltinIncludeDir &&
3938d74de9dSMartin Boehme ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()));
3948d74de9dSMartin Boehme }
3958d74de9dSMartin Boehme
39692669ee4SDaniel Jasper ModuleMap::HeadersMap::iterator
findKnownHeader(const FileEntry * File)39792669ee4SDaniel Jasper ModuleMap::findKnownHeader(const FileEntry *File) {
398040e1266SRichard Smith resolveHeaderDirectives(File);
39959527666SDouglas Gregor HeadersMap::iterator Known = Headers.find(File);
40047972afdSRichard Smith if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
4018d74de9dSMartin Boehme Known == Headers.end() && ModuleMap::isBuiltinHeader(File)) {
4024eaf0a6cSDaniel Jasper HeaderInfo.loadTopLevelSystemModules();
40392669ee4SDaniel Jasper return Headers.find(File);
4044eaf0a6cSDaniel Jasper }
40592669ee4SDaniel Jasper return Known;
40692669ee4SDaniel Jasper }
40792669ee4SDaniel Jasper
4084469138eSBen Langmuir ModuleMap::KnownHeader
findHeaderInUmbrellaDirs(const FileEntry * File,SmallVectorImpl<const DirectoryEntry * > & IntermediateDirs)4094469138eSBen Langmuir ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
4104469138eSBen Langmuir SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
41147972afdSRichard Smith if (UmbrellaDirs.empty())
412afd1b1c9SEugene Zelenko return {};
41347972afdSRichard Smith
4144469138eSBen Langmuir const DirectoryEntry *Dir = File->getDir();
4154469138eSBen Langmuir assert(Dir && "file in no directory");
4164469138eSBen Langmuir
4174469138eSBen Langmuir // Note: as an egregious but useful hack we use the real path here, because
4184469138eSBen Langmuir // frameworks moving from top-level frameworks to embedded frameworks tend
4194469138eSBen Langmuir // to be symlinked from the top-level location to the embedded location,
4204469138eSBen Langmuir // and we need to resolve lookups as if we had found the embedded location.
4214469138eSBen Langmuir StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
4224469138eSBen Langmuir
4234469138eSBen Langmuir // Keep walking up the directory hierarchy, looking for a directory with
4244469138eSBen Langmuir // an umbrella header.
4254469138eSBen Langmuir do {
4264469138eSBen Langmuir auto KnownDir = UmbrellaDirs.find(Dir);
4274469138eSBen Langmuir if (KnownDir != UmbrellaDirs.end())
4284469138eSBen Langmuir return KnownHeader(KnownDir->second, NormalHeader);
4294469138eSBen Langmuir
4304469138eSBen Langmuir IntermediateDirs.push_back(Dir);
4314469138eSBen Langmuir
4324469138eSBen Langmuir // Retrieve our parent path.
4334469138eSBen Langmuir DirName = llvm::sys::path::parent_path(DirName);
4344469138eSBen Langmuir if (DirName.empty())
4354469138eSBen Langmuir break;
4364469138eSBen Langmuir
4374469138eSBen Langmuir // Resolve the parent path to a directory entry.
4388d323d15SHarlan Haskins if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName))
4398d323d15SHarlan Haskins Dir = *DirEntry;
4408d323d15SHarlan Haskins else
4418d323d15SHarlan Haskins Dir = nullptr;
4424469138eSBen Langmuir } while (Dir);
443afd1b1c9SEugene Zelenko return {};
4444469138eSBen Langmuir }
4454469138eSBen Langmuir
violatesPrivateInclude(Module * RequestingModule,const FileEntry * IncFileEnt,ModuleMap::KnownHeader Header)44692669ee4SDaniel Jasper static bool violatesPrivateInclude(Module *RequestingModule,
44792669ee4SDaniel Jasper const FileEntry *IncFileEnt,
4484eb8393cSRichard Smith ModuleMap::KnownHeader Header) {
44992669ee4SDaniel Jasper #ifndef NDEBUG
4504eb8393cSRichard Smith if (Header.getRole() & ModuleMap::PrivateHeader) {
45192669ee4SDaniel Jasper // Check for consistency between the module header role
45292669ee4SDaniel Jasper // as obtained from the lookup and as obtained from the module.
45392669ee4SDaniel Jasper // This check is not cheap, so enable it only for debugging.
4542708e520SRichard Smith bool IsPrivate = false;
4552708e520SRichard Smith SmallVectorImpl<Module::Header> *HeaderList[] = {
4564eb8393cSRichard Smith &Header.getModule()->Headers[Module::HK_Private],
4574eb8393cSRichard Smith &Header.getModule()->Headers[Module::HK_PrivateTextual]};
4582708e520SRichard Smith for (auto *Hs : HeaderList)
459*70257fabSKazu Hirata IsPrivate |= llvm::any_of(
460*70257fabSKazu Hirata *Hs, [&](const Module::Header &H) { return H.Entry == IncFileEnt; });
4614eb8393cSRichard Smith assert(IsPrivate && "inconsistent headers and roles");
46200bc95ecSRichard Smith }
46392669ee4SDaniel Jasper #endif
4644eb8393cSRichard Smith return !Header.isAccessibleFrom(RequestingModule);
46592669ee4SDaniel Jasper }
46692669ee4SDaniel Jasper
getTopLevelOrNull(Module * M)46771e1a64fSBen Langmuir static Module *getTopLevelOrNull(Module *M) {
46871e1a64fSBen Langmuir return M ? M->getTopLevelModule() : nullptr;
46971e1a64fSBen Langmuir }
47071e1a64fSBen Langmuir
diagnoseHeaderInclusion(Module * RequestingModule,bool RequestingModuleIsModuleInterface,SourceLocation FilenameLoc,StringRef Filename,FileEntryRef File)47192669ee4SDaniel Jasper void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
4728d4e90b3SRichard Smith bool RequestingModuleIsModuleInterface,
47392669ee4SDaniel Jasper SourceLocation FilenameLoc,
47499cfccdcSJan Svoboda StringRef Filename, FileEntryRef File) {
47592669ee4SDaniel Jasper // No errors for indirect modules. This may be a bit of a problem for modules
47692669ee4SDaniel Jasper // with no source files.
47771e1a64fSBen Langmuir if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
47892669ee4SDaniel Jasper return;
47992669ee4SDaniel Jasper
480040e1266SRichard Smith if (RequestingModule) {
48192669ee4SDaniel Jasper resolveUses(RequestingModule, /*Complain=*/false);
4828f4ea36bSAdam Czachorowski resolveHeaderDirectives(RequestingModule, /*File=*/llvm::None);
483040e1266SRichard Smith }
48492669ee4SDaniel Jasper
48571e1a64fSBen Langmuir bool Excluded = false;
486d2d442caSCraig Topper Module *Private = nullptr;
487d2d442caSCraig Topper Module *NotUsed = nullptr;
48871e1a64fSBen Langmuir
48971e1a64fSBen Langmuir HeadersMap::iterator Known = findKnownHeader(File);
49071e1a64fSBen Langmuir if (Known != Headers.end()) {
49171e1a64fSBen Langmuir for (const KnownHeader &Header : Known->second) {
49292669ee4SDaniel Jasper // Remember private headers for later printing of a diagnostic.
4934eb8393cSRichard Smith if (violatesPrivateInclude(RequestingModule, File, Header)) {
49471e1a64fSBen Langmuir Private = Header.getModule();
49592669ee4SDaniel Jasper continue;
49692669ee4SDaniel Jasper }
49792669ee4SDaniel Jasper
49892669ee4SDaniel Jasper // If uses need to be specified explicitly, we are only allowed to return
49992669ee4SDaniel Jasper // modules that are explicitly used by the requesting module.
50092669ee4SDaniel Jasper if (RequestingModule && LangOpts.ModulesDeclUse &&
5018f4d3ff1SRichard Smith !RequestingModule->directlyUses(Header.getModule())) {
50271e1a64fSBen Langmuir NotUsed = Header.getModule();
50392669ee4SDaniel Jasper continue;
50492669ee4SDaniel Jasper }
50592669ee4SDaniel Jasper
50692669ee4SDaniel Jasper // We have found a module that we can happily use.
50792669ee4SDaniel Jasper return;
50892669ee4SDaniel Jasper }
509feb54b6dSRichard Smith
510feb54b6dSRichard Smith Excluded = true;
51171e1a64fSBen Langmuir }
51292669ee4SDaniel Jasper
51392669ee4SDaniel Jasper // We have found a header, but it is private.
514d2d442caSCraig Topper if (Private) {
51511152dd5SRichard Smith Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
51692669ee4SDaniel Jasper << Filename;
51792669ee4SDaniel Jasper return;
51892669ee4SDaniel Jasper }
51992669ee4SDaniel Jasper
52092669ee4SDaniel Jasper // We have found a module, but we don't use it.
521d2d442caSCraig Topper if (NotUsed) {
52211152dd5SRichard Smith Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5234ea330c8SDaniel Jasper << RequestingModule->getTopLevelModule()->Name << Filename;
52492669ee4SDaniel Jasper return;
52592669ee4SDaniel Jasper }
52692669ee4SDaniel Jasper
52771e1a64fSBen Langmuir if (Excluded || isHeaderInUmbrellaDirs(File))
52871e1a64fSBen Langmuir return;
52971e1a64fSBen Langmuir
53071e1a64fSBen Langmuir // At this point, only non-modular includes remain.
53171e1a64fSBen Langmuir
5325904c41eSBenjamin Kramer if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
53311152dd5SRichard Smith Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5344ea330c8SDaniel Jasper << RequestingModule->getTopLevelModule()->Name << Filename;
535a67e4d32SManman Ren } else if (RequestingModule && RequestingModuleIsModuleInterface &&
536a67e4d32SManman Ren LangOpts.isCompilingModule()) {
537a67e4d32SManman Ren // Do not diagnose when we are not compiling a module.
53871e1a64fSBen Langmuir diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
53971e1a64fSBen Langmuir diag::warn_non_modular_include_in_framework_module :
54071e1a64fSBen Langmuir diag::warn_non_modular_include_in_module;
54170a7738fSManman Ren Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
54299cfccdcSJan Svoboda << File.getName();
54371e1a64fSBen Langmuir }
54492669ee4SDaniel Jasper }
54592669ee4SDaniel Jasper
isBetterKnownHeader(const ModuleMap::KnownHeader & New,const ModuleMap::KnownHeader & Old)546ec87a50aSRichard Smith static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
547ec87a50aSRichard Smith const ModuleMap::KnownHeader &Old) {
5488b7c0398SSean Silva // Prefer available modules.
5496bc75023SRichard Smith // FIXME: Considering whether the module is available rather than merely
5506bc75023SRichard Smith // importable is non-hermetic and can result in surprising behavior for
5516bc75023SRichard Smith // prebuilt modules. Consider only checking for importability here.
5528b7c0398SSean Silva if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
5538b7c0398SSean Silva return true;
5548b7c0398SSean Silva
555ec87a50aSRichard Smith // Prefer a public header over a private header.
556ec87a50aSRichard Smith if ((New.getRole() & ModuleMap::PrivateHeader) !=
557ec87a50aSRichard Smith (Old.getRole() & ModuleMap::PrivateHeader))
558ec87a50aSRichard Smith return !(New.getRole() & ModuleMap::PrivateHeader);
559ec87a50aSRichard Smith
560ec87a50aSRichard Smith // Prefer a non-textual header over a textual header.
561ec87a50aSRichard Smith if ((New.getRole() & ModuleMap::TextualHeader) !=
562ec87a50aSRichard Smith (Old.getRole() & ModuleMap::TextualHeader))
563ec87a50aSRichard Smith return !(New.getRole() & ModuleMap::TextualHeader);
564ec87a50aSRichard Smith
565ec87a50aSRichard Smith // Don't have a reason to choose between these. Just keep the first one.
566ec87a50aSRichard Smith return false;
567ec87a50aSRichard Smith }
568ec87a50aSRichard Smith
findModuleForHeader(const FileEntry * File,bool AllowTextual)569ed84df00SBruno Cardoso Lopes ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
570ed84df00SBruno Cardoso Lopes bool AllowTextual) {
571306d8920SRichard Smith auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
572ed84df00SBruno Cardoso Lopes if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
573afd1b1c9SEugene Zelenko return {};
574306d8920SRichard Smith return R;
575306d8920SRichard Smith };
576306d8920SRichard Smith
5774881e8b2SSean Silva HeadersMap::iterator Known = findKnownHeader(File);
5781fb5c3a6SDouglas Gregor if (Known != Headers.end()) {
579202210b3SRichard Smith ModuleMap::KnownHeader Result;
58097da9178SDaniel Jasper // Iterate over all modules that 'File' is part of to find the best fit.
5814881e8b2SSean Silva for (KnownHeader &H : Known->second) {
5827e82e019SRichard Smith // Prefer a header from the source module over all others.
5837e82e019SRichard Smith if (H.getModule()->getTopLevelModule() == SourceModule)
5842f633e7cSRichard Smith return MakeResult(H);
5854881e8b2SSean Silva if (!Result || isBetterKnownHeader(H, Result))
5864881e8b2SSean Silva Result = H;
58797da9178SDaniel Jasper }
588306d8920SRichard Smith return MakeResult(Result);
5891fb5c3a6SDouglas Gregor }
590ab0c8a84SDouglas Gregor
591386bb073SRichard Smith return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
592386bb073SRichard Smith }
593386bb073SRichard Smith
594386bb073SRichard Smith ModuleMap::KnownHeader
findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry * File)595386bb073SRichard Smith ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
596386bb073SRichard Smith assert(!Headers.count(File) && "already have a module for this header");
597386bb073SRichard Smith
598f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs;
5994469138eSBen Langmuir KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
6004469138eSBen Langmuir if (H) {
6014469138eSBen Langmuir Module *Result = H.getModule();
602930a85ccSDouglas Gregor
603930a85ccSDouglas Gregor // Search up the module stack until we find a module with an umbrella
60473141fa9SDouglas Gregor // directory.
605930a85ccSDouglas Gregor Module *UmbrellaModule = Result;
60673141fa9SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
607930a85ccSDouglas Gregor UmbrellaModule = UmbrellaModule->Parent;
608930a85ccSDouglas Gregor
609930a85ccSDouglas Gregor if (UmbrellaModule->InferSubmodules) {
6109d6448b1SBen Langmuir const FileEntry *UmbrellaModuleMap =
6119d6448b1SBen Langmuir getModuleMapFileForUniquing(UmbrellaModule);
6129d6448b1SBen Langmuir
613a89c5ac4SDouglas Gregor // Infer submodules for each of the directories we found between
614a89c5ac4SDouglas Gregor // the directory of the umbrella header and the directory where
615a89c5ac4SDouglas Gregor // the actual header is located.
6169458f82dSDouglas Gregor bool Explicit = UmbrellaModule->InferExplicitSubmodules;
6179458f82dSDouglas Gregor
6188adb6d6dSBenjamin Kramer for (const DirectoryEntry *SkippedDir : llvm::reverse(SkippedDirs)) {
619a89c5ac4SDouglas Gregor // Find or create the module that corresponds to this directory name.
620056396aeSDouglas Gregor SmallString<32> NameBuf;
621056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier(
6228adb6d6dSBenjamin Kramer llvm::sys::path::stem(SkippedDir->getName()), NameBuf);
6239d6448b1SBen Langmuir Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6249d6448b1SBen Langmuir Explicit).first;
6259d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
626ffbafa2aSBen Langmuir Result->IsInferred = true;
627a89c5ac4SDouglas Gregor
628a89c5ac4SDouglas Gregor // Associate the module and the directory.
6298adb6d6dSBenjamin Kramer UmbrellaDirs[SkippedDir] = Result;
630a89c5ac4SDouglas Gregor
631a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a
632a89c5ac4SDouglas Gregor // wildcard to the set of exports.
633930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
634d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true));
635a89c5ac4SDouglas Gregor }
636a89c5ac4SDouglas Gregor
637a89c5ac4SDouglas Gregor // Infer a submodule with the same name as this header file.
638056396aeSDouglas Gregor SmallString<32> NameBuf;
639056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier(
640056396aeSDouglas Gregor llvm::sys::path::stem(File->getName()), NameBuf);
6419d6448b1SBen Langmuir Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6429d6448b1SBen Langmuir Explicit).first;
6439d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
644ffbafa2aSBen Langmuir Result->IsInferred = true;
6453c5305c1SArgyrios Kyrtzidis Result->addTopHeader(File);
646a89c5ac4SDouglas Gregor
647a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a
648a89c5ac4SDouglas Gregor // wildcard to the set of exports.
649930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
650d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true));
651a89c5ac4SDouglas Gregor } else {
652a89c5ac4SDouglas Gregor // Record each of the directories we stepped through as being part of
653a89c5ac4SDouglas Gregor // the module we found, since the umbrella header covers them all.
654a89c5ac4SDouglas Gregor for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
655a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I]] = Result;
656a89c5ac4SDouglas Gregor }
657a89c5ac4SDouglas Gregor
658386bb073SRichard Smith KnownHeader Header(Result, NormalHeader);
659386bb073SRichard Smith Headers[File].push_back(Header);
660386bb073SRichard Smith return Header;
661a89c5ac4SDouglas Gregor }
662a89c5ac4SDouglas Gregor
663afd1b1c9SEugene Zelenko return {};
664ab0c8a84SDouglas Gregor }
665ab0c8a84SDouglas Gregor
666386bb073SRichard Smith ArrayRef<ModuleMap::KnownHeader>
findAllModulesForHeader(const FileEntry * File)6670a088eadSRichard Smith ModuleMap::findAllModulesForHeader(const FileEntry *File) {
6680a088eadSRichard Smith HeadersMap::iterator Known = findKnownHeader(File);
6690a088eadSRichard Smith if (Known != Headers.end())
6700a088eadSRichard Smith return Known->second;
6710a088eadSRichard Smith
6720a088eadSRichard Smith if (findOrCreateModuleForHeaderInUmbrellaDir(File))
6730a088eadSRichard Smith return Headers.find(File)->second;
6740a088eadSRichard Smith
6750a088eadSRichard Smith return None;
6760a088eadSRichard Smith }
6770a088eadSRichard Smith
6780a088eadSRichard Smith ArrayRef<ModuleMap::KnownHeader>
findResolvedModulesForHeader(const FileEntry * File) const6790a088eadSRichard Smith ModuleMap::findResolvedModulesForHeader(const FileEntry *File) const {
6800a088eadSRichard Smith // FIXME: Is this necessary?
681040e1266SRichard Smith resolveHeaderDirectives(File);
682386bb073SRichard Smith auto It = Headers.find(File);
683386bb073SRichard Smith if (It == Headers.end())
684386bb073SRichard Smith return None;
685386bb073SRichard Smith return It->second;
686386bb073SRichard Smith }
687386bb073SRichard Smith
isHeaderInUnavailableModule(const FileEntry * Header) const688e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
689d2d442caSCraig Topper return isHeaderUnavailableInModule(Header, nullptr);
69050996ce1SRichard Smith }
69150996ce1SRichard Smith
69262bcd925SDmitri Gribenko bool
isHeaderUnavailableInModule(const FileEntry * Header,const Module * RequestingModule) const69362bcd925SDmitri Gribenko ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
69462bcd925SDmitri Gribenko const Module *RequestingModule) const {
695040e1266SRichard Smith resolveHeaderDirectives(Header);
696e4412640SArgyrios Kyrtzidis HeadersMap::const_iterator Known = Headers.find(Header);
69797da9178SDaniel Jasper if (Known != Headers.end()) {
69897da9178SDaniel Jasper for (SmallVectorImpl<KnownHeader>::const_iterator
69997da9178SDaniel Jasper I = Known->second.begin(),
70097da9178SDaniel Jasper E = Known->second.end();
70197da9178SDaniel Jasper I != E; ++I) {
702052d95a6SBruno Cardoso Lopes
703052d95a6SBruno Cardoso Lopes if (I->isAvailable() &&
704052d95a6SBruno Cardoso Lopes (!RequestingModule ||
705052d95a6SBruno Cardoso Lopes I->getModule()->isSubModuleOf(RequestingModule))) {
706052d95a6SBruno Cardoso Lopes // When no requesting module is available, the caller is looking if a
707052d95a6SBruno Cardoso Lopes // header is part a module by only looking into the module map. This is
708052d95a6SBruno Cardoso Lopes // done by warn_uncovered_module_header checks; don't consider textual
709052d95a6SBruno Cardoso Lopes // headers part of it in this mode, otherwise we get misleading warnings
710052d95a6SBruno Cardoso Lopes // that a umbrella header is not including a textual header.
711052d95a6SBruno Cardoso Lopes if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
712052d95a6SBruno Cardoso Lopes continue;
71397da9178SDaniel Jasper return false;
71497da9178SDaniel Jasper }
715052d95a6SBruno Cardoso Lopes }
71697da9178SDaniel Jasper return true;
71797da9178SDaniel Jasper }
7181fb5c3a6SDouglas Gregor
7191fb5c3a6SDouglas Gregor const DirectoryEntry *Dir = Header->getDir();
720f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs;
7211fb5c3a6SDouglas Gregor StringRef DirName = Dir->getName();
7221fb5c3a6SDouglas Gregor
72350996ce1SRichard Smith auto IsUnavailable = [&](const Module *M) {
72450996ce1SRichard Smith return !M->isAvailable() && (!RequestingModule ||
72550996ce1SRichard Smith M->isSubModuleOf(RequestingModule));
72650996ce1SRichard Smith };
72750996ce1SRichard Smith
7281fb5c3a6SDouglas Gregor // Keep walking up the directory hierarchy, looking for a directory with
7291fb5c3a6SDouglas Gregor // an umbrella header.
7301fb5c3a6SDouglas Gregor do {
731e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
7321fb5c3a6SDouglas Gregor = UmbrellaDirs.find(Dir);
7331fb5c3a6SDouglas Gregor if (KnownDir != UmbrellaDirs.end()) {
7341fb5c3a6SDouglas Gregor Module *Found = KnownDir->second;
73550996ce1SRichard Smith if (IsUnavailable(Found))
7361fb5c3a6SDouglas Gregor return true;
7371fb5c3a6SDouglas Gregor
7381fb5c3a6SDouglas Gregor // Search up the module stack until we find a module with an umbrella
7391fb5c3a6SDouglas Gregor // directory.
7401fb5c3a6SDouglas Gregor Module *UmbrellaModule = Found;
7411fb5c3a6SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
7421fb5c3a6SDouglas Gregor UmbrellaModule = UmbrellaModule->Parent;
7431fb5c3a6SDouglas Gregor
7441fb5c3a6SDouglas Gregor if (UmbrellaModule->InferSubmodules) {
7458adb6d6dSBenjamin Kramer for (const DirectoryEntry *SkippedDir : llvm::reverse(SkippedDirs)) {
7461fb5c3a6SDouglas Gregor // Find or create the module that corresponds to this directory name.
747056396aeSDouglas Gregor SmallString<32> NameBuf;
748056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier(
7498adb6d6dSBenjamin Kramer llvm::sys::path::stem(SkippedDir->getName()), NameBuf);
7501fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found);
7511fb5c3a6SDouglas Gregor if (!Found)
7521fb5c3a6SDouglas Gregor return false;
75350996ce1SRichard Smith if (IsUnavailable(Found))
7541fb5c3a6SDouglas Gregor return true;
7551fb5c3a6SDouglas Gregor }
7561fb5c3a6SDouglas Gregor
7571fb5c3a6SDouglas Gregor // Infer a submodule with the same name as this header file.
758056396aeSDouglas Gregor SmallString<32> NameBuf;
759056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier(
760056396aeSDouglas Gregor llvm::sys::path::stem(Header->getName()),
761056396aeSDouglas Gregor NameBuf);
7621fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found);
7631fb5c3a6SDouglas Gregor if (!Found)
7641fb5c3a6SDouglas Gregor return false;
7651fb5c3a6SDouglas Gregor }
7661fb5c3a6SDouglas Gregor
76750996ce1SRichard Smith return IsUnavailable(Found);
7681fb5c3a6SDouglas Gregor }
7691fb5c3a6SDouglas Gregor
7701fb5c3a6SDouglas Gregor SkippedDirs.push_back(Dir);
7711fb5c3a6SDouglas Gregor
7721fb5c3a6SDouglas Gregor // Retrieve our parent path.
7731fb5c3a6SDouglas Gregor DirName = llvm::sys::path::parent_path(DirName);
7741fb5c3a6SDouglas Gregor if (DirName.empty())
7751fb5c3a6SDouglas Gregor break;
7761fb5c3a6SDouglas Gregor
7771fb5c3a6SDouglas Gregor // Resolve the parent path to a directory entry.
7788d323d15SHarlan Haskins if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName))
7798d323d15SHarlan Haskins Dir = *DirEntry;
7808d323d15SHarlan Haskins else
7818d323d15SHarlan Haskins Dir = nullptr;
7821fb5c3a6SDouglas Gregor } while (Dir);
7831fb5c3a6SDouglas Gregor
7841fb5c3a6SDouglas Gregor return false;
7851fb5c3a6SDouglas Gregor }
7861fb5c3a6SDouglas Gregor
findModule(StringRef Name) const787e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const {
788e4412640SArgyrios Kyrtzidis llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
78988bdfb0eSDouglas Gregor if (Known != Modules.end())
79088bdfb0eSDouglas Gregor return Known->getValue();
79188bdfb0eSDouglas Gregor
792d2d442caSCraig Topper return nullptr;
79388bdfb0eSDouglas Gregor }
79488bdfb0eSDouglas Gregor
lookupModuleUnqualified(StringRef Name,Module * Context) const795e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
796e4412640SArgyrios Kyrtzidis Module *Context) const {
7972b82c2a5SDouglas Gregor for(; Context; Context = Context->Parent) {
7982b82c2a5SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Context))
7992b82c2a5SDouglas Gregor return Sub;
8002b82c2a5SDouglas Gregor }
8012b82c2a5SDouglas Gregor
8022b82c2a5SDouglas Gregor return findModule(Name);
8032b82c2a5SDouglas Gregor }
8042b82c2a5SDouglas Gregor
lookupModuleQualified(StringRef Name,Module * Context) const805e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
8062b82c2a5SDouglas Gregor if (!Context)
8072b82c2a5SDouglas Gregor return findModule(Name);
8082b82c2a5SDouglas Gregor
809eb90e830SDouglas Gregor return Context->findSubmodule(Name);
8102b82c2a5SDouglas Gregor }
8112b82c2a5SDouglas Gregor
findOrCreateModule(StringRef Name,Module * Parent,bool IsFramework,bool IsExplicit)812c192d194SBruno Cardoso Lopes std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
813c192d194SBruno Cardoso Lopes Module *Parent,
814c192d194SBruno Cardoso Lopes bool IsFramework,
815c192d194SBruno Cardoso Lopes bool IsExplicit) {
81669021974SDouglas Gregor // Try to find an existing module with this name.
817eb90e830SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Parent))
818eb90e830SDouglas Gregor return std::make_pair(Sub, false);
81969021974SDouglas Gregor
82069021974SDouglas Gregor // Create a new module with this name.
8219ffe5a35SDavid Blaikie Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
8229ffe5a35SDavid Blaikie IsExplicit, NumCreatedModules++);
8236f722b4eSArgyrios Kyrtzidis if (!Parent) {
8247e82e019SRichard Smith if (LangOpts.CurrentModule == Name)
8257e82e019SRichard Smith SourceModule = Result;
82669021974SDouglas Gregor Modules[Name] = Result;
827c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID;
8286f722b4eSArgyrios Kyrtzidis }
82969021974SDouglas Gregor return std::make_pair(Result, true);
83069021974SDouglas Gregor }
83169021974SDouglas Gregor
createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,Module * Parent)832e587372fSChuanqi Xu Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
833e587372fSChuanqi Xu Module *Parent) {
834e587372fSChuanqi Xu auto *Result = new Module("<global>", Loc, Parent, /*IsFramework*/ false,
835e587372fSChuanqi Xu /*IsExplicit*/ true, NumCreatedModules++);
836e587372fSChuanqi Xu Result->Kind = Module::GlobalModuleFragment;
837e587372fSChuanqi Xu // If the created module isn't owned by a parent, send it to PendingSubmodules
838e587372fSChuanqi Xu // to wait for its parent.
839e587372fSChuanqi Xu if (!Result->Parent)
840e587372fSChuanqi Xu PendingSubmodules.emplace_back(Result);
841e587372fSChuanqi Xu return Result;
842dd8b5337SRichard Smith }
843dd8b5337SRichard Smith
844a5bbbfefSRichard Smith Module *
createPrivateModuleFragmentForInterfaceUnit(Module * Parent,SourceLocation Loc)845a5bbbfefSRichard Smith ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
846a5bbbfefSRichard Smith SourceLocation Loc) {
847a5bbbfefSRichard Smith auto *Result =
848a5bbbfefSRichard Smith new Module("<private>", Loc, Parent, /*IsFramework*/ false,
849a5bbbfefSRichard Smith /*IsExplicit*/ true, NumCreatedModules++);
850a5bbbfefSRichard Smith Result->Kind = Module::PrivateModuleFragment;
851a5bbbfefSRichard Smith return Result;
852a5bbbfefSRichard Smith }
853a5bbbfefSRichard Smith
createModuleForInterfaceUnit(SourceLocation Loc,StringRef Name,Module * GlobalModule)854bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
855dd8b5337SRichard Smith StringRef Name,
856dd8b5337SRichard Smith Module *GlobalModule) {
857bbcc9f04SRichard Smith assert(LangOpts.CurrentModule == Name && "module name mismatch");
858bbcc9f04SRichard Smith assert(!Modules[Name] && "redefining existing module");
859bbcc9f04SRichard Smith
860bbcc9f04SRichard Smith auto *Result =
861bbcc9f04SRichard Smith new Module(Name, Loc, nullptr, /*IsFramework*/ false,
862bbcc9f04SRichard Smith /*IsExplicit*/ false, NumCreatedModules++);
863145e15a3SRichard Smith Result->Kind = Module::ModuleInterfaceUnit;
864bbcc9f04SRichard Smith Modules[Name] = SourceModule = Result;
865bbcc9f04SRichard Smith
866dd8b5337SRichard Smith // Reparent the current global module fragment as a submodule of this module.
867d6509cf2SRichard Smith for (auto &Submodule : PendingSubmodules) {
868d6509cf2SRichard Smith Submodule->setParent(Result);
869d6509cf2SRichard Smith Submodule.release(); // now owned by parent
870d6509cf2SRichard Smith }
871d6509cf2SRichard Smith PendingSubmodules.clear();
872dd8b5337SRichard Smith
873bbcc9f04SRichard Smith // Mark the main source file as being within the newly-created module so that
874bbcc9f04SRichard Smith // declarations and macros are properly visibility-restricted to it.
875bbcc9f04SRichard Smith auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
876bbcc9f04SRichard Smith assert(MainFile && "no input file for module interface");
877bbcc9f04SRichard Smith Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader));
878bbcc9f04SRichard Smith
879bbcc9f04SRichard Smith return Result;
880bbcc9f04SRichard Smith }
881bbcc9f04SRichard Smith
createHeaderModule(StringRef Name,ArrayRef<Module::Header> Headers)882d6509cf2SRichard Smith Module *ModuleMap::createHeaderModule(StringRef Name,
883d6509cf2SRichard Smith ArrayRef<Module::Header> Headers) {
884d6509cf2SRichard Smith assert(LangOpts.CurrentModule == Name && "module name mismatch");
885d6509cf2SRichard Smith assert(!Modules[Name] && "redefining existing module");
886d6509cf2SRichard Smith
887d6509cf2SRichard Smith auto *Result =
888d6509cf2SRichard Smith new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false,
889d6509cf2SRichard Smith /*IsExplicit*/ false, NumCreatedModules++);
890d6509cf2SRichard Smith Result->Kind = Module::ModuleInterfaceUnit;
891d6509cf2SRichard Smith Modules[Name] = SourceModule = Result;
892d6509cf2SRichard Smith
893d6509cf2SRichard Smith for (const Module::Header &H : Headers) {
894d6509cf2SRichard Smith auto *M = new Module(H.NameAsWritten, SourceLocation(), Result,
895d6509cf2SRichard Smith /*IsFramework*/ false,
896d6509cf2SRichard Smith /*IsExplicit*/ true, NumCreatedModules++);
897d6509cf2SRichard Smith // Header modules are implicitly 'export *'.
898d6509cf2SRichard Smith M->Exports.push_back(Module::ExportDecl(nullptr, true));
899d6509cf2SRichard Smith addHeader(M, H, NormalHeader);
900d6509cf2SRichard Smith }
901d6509cf2SRichard Smith
902d6509cf2SRichard Smith return Result;
903d6509cf2SRichard Smith }
904d6509cf2SRichard Smith
createHeaderUnit(SourceLocation Loc,StringRef Name,Module::Header H)9056c0e60e8SIain Sandoe Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name,
9066c0e60e8SIain Sandoe Module::Header H) {
9076c0e60e8SIain Sandoe assert(LangOpts.CurrentModule == Name && "module name mismatch");
9086c0e60e8SIain Sandoe assert(!Modules[Name] && "redefining existing module");
9096c0e60e8SIain Sandoe
9106c0e60e8SIain Sandoe auto *Result = new Module(Name, Loc, nullptr, /*IsFramework*/ false,
9116c0e60e8SIain Sandoe /*IsExplicit*/ false, NumCreatedModules++);
9126c0e60e8SIain Sandoe Result->Kind = Module::ModuleHeaderUnit;
9136c0e60e8SIain Sandoe Modules[Name] = SourceModule = Result;
9146c0e60e8SIain Sandoe addHeader(Result, H, NormalHeader);
9156c0e60e8SIain Sandoe return Result;
9166c0e60e8SIain Sandoe }
9176c0e60e8SIain Sandoe
9189fc8faf9SAdrian Prantl /// For a framework module, infer the framework against which we
91911dfe6feSDouglas Gregor /// should link.
inferFrameworkLink(Module * Mod,const DirectoryEntry * FrameworkDir,FileManager & FileMgr)92011dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
92111dfe6feSDouglas Gregor FileManager &FileMgr) {
92211dfe6feSDouglas Gregor assert(Mod->IsFramework && "Can only infer linking for framework modules");
92311dfe6feSDouglas Gregor assert(!Mod->isSubFramework() &&
92411dfe6feSDouglas Gregor "Can only infer linking for top-level frameworks");
92511dfe6feSDouglas Gregor
92611dfe6feSDouglas Gregor SmallString<128> LibName;
92711dfe6feSDouglas Gregor LibName += FrameworkDir->getName();
92811dfe6feSDouglas Gregor llvm::sys::path::append(LibName, Mod->Name);
9298aaae5a9SJuergen Ributzka
9308aaae5a9SJuergen Ributzka // The library name of a framework has more than one possible extension since
9318aaae5a9SJuergen Ributzka // the introduction of the text-based dynamic library format. We need to check
9328aaae5a9SJuergen Ributzka // for both before we give up.
9338013e81dSBenjamin Kramer for (const char *extension : {"", ".tbd"}) {
9348aaae5a9SJuergen Ributzka llvm::sys::path::replace_extension(LibName, extension);
93511dfe6feSDouglas Gregor if (FileMgr.getFile(LibName)) {
93611dfe6feSDouglas Gregor Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
93711dfe6feSDouglas Gregor /*IsFramework=*/true));
9388aaae5a9SJuergen Ributzka return;
9398aaae5a9SJuergen Ributzka }
94011dfe6feSDouglas Gregor }
94111dfe6feSDouglas Gregor }
94211dfe6feSDouglas Gregor
inferFrameworkModule(const DirectoryEntry * FrameworkDir,bool IsSystem,Module * Parent)943a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
944a525400dSBen Langmuir bool IsSystem, Module *Parent) {
945c1d88ea5SBen Langmuir Attributes Attrs;
946c1d88ea5SBen Langmuir Attrs.IsSystem = IsSystem;
947a525400dSBen Langmuir return inferFrameworkModule(FrameworkDir, Attrs, Parent);
948c1d88ea5SBen Langmuir }
949c1d88ea5SBen Langmuir
inferFrameworkModule(const DirectoryEntry * FrameworkDir,Attributes Attrs,Module * Parent)950a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
951c1d88ea5SBen Langmuir Attributes Attrs, Module *Parent) {
952a525400dSBen Langmuir // Note: as an egregious but useful hack we use the real path here, because
953a525400dSBen Langmuir // we might be looking at an embedded framework that symlinks out to a
954a525400dSBen Langmuir // top-level framework, and we need to infer as if we were naming the
955a525400dSBen Langmuir // top-level framework.
956a525400dSBen Langmuir StringRef FrameworkDirName =
957a525400dSBen Langmuir SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
958a525400dSBen Langmuir
959a525400dSBen Langmuir // In case this is a case-insensitive filesystem, use the canonical
960a525400dSBen Langmuir // directory name as the ModuleName, since modules are case-sensitive.
961a525400dSBen Langmuir // FIXME: we should be able to give a fix-it hint for the correct spelling.
962a525400dSBen Langmuir SmallString<32> ModuleNameStorage;
963a525400dSBen Langmuir StringRef ModuleName = sanitizeFilenameAsIdentifier(
964a525400dSBen Langmuir llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
965c1d88ea5SBen Langmuir
96656c64013SDouglas Gregor // Check whether we've already found this module.
967e89dbc1dSDouglas Gregor if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
968e89dbc1dSDouglas Gregor return Mod;
969e89dbc1dSDouglas Gregor
9701f76c4e8SManuel Klimek FileManager &FileMgr = SourceMgr.getFileManager();
97156c64013SDouglas Gregor
9729194a91dSDouglas Gregor // If the framework has a parent path from which we're allowed to infer
9739194a91dSDouglas Gregor // a framework module, do so.
974beee15e7SBen Langmuir const FileEntry *ModuleMapFile = nullptr;
9759194a91dSDouglas Gregor if (!Parent) {
9764ddf2221SDouglas Gregor // Determine whether we're allowed to infer a module map.
9779194a91dSDouglas Gregor bool canInfer = false;
9784ddf2221SDouglas Gregor if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
9799194a91dSDouglas Gregor // Figure out the parent path.
9804ddf2221SDouglas Gregor StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
9818d323d15SHarlan Haskins if (auto ParentDir = FileMgr.getDirectory(Parent)) {
9829194a91dSDouglas Gregor // Check whether we have already looked into the parent directory
9839194a91dSDouglas Gregor // for a module map.
984e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
9858d323d15SHarlan Haskins inferred = InferredDirectories.find(*ParentDir);
9869194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) {
9879194a91dSDouglas Gregor // We haven't looked here before. Load a module map, if there is
9889194a91dSDouglas Gregor // one.
989984e1df7SBen Langmuir bool IsFrameworkDir = Parent.endswith(".framework");
9907799ef71SNico Weber if (const FileEntry *ModMapFile =
9918d323d15SHarlan Haskins HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) {
9927799ef71SNico Weber parseModuleMapFile(ModMapFile, Attrs.IsSystem, *ParentDir);
9938d323d15SHarlan Haskins inferred = InferredDirectories.find(*ParentDir);
9949194a91dSDouglas Gregor }
9959194a91dSDouglas Gregor
9969194a91dSDouglas Gregor if (inferred == InferredDirectories.end())
9979194a91dSDouglas Gregor inferred = InferredDirectories.insert(
9988d323d15SHarlan Haskins std::make_pair(*ParentDir, InferredDirectory())).first;
9999194a91dSDouglas Gregor }
10009194a91dSDouglas Gregor
10019194a91dSDouglas Gregor if (inferred->second.InferModules) {
10029194a91dSDouglas Gregor // We're allowed to infer for this directory, but make sure it's okay
10039194a91dSDouglas Gregor // to infer this particular module.
10044ddf2221SDouglas Gregor StringRef Name = llvm::sys::path::stem(FrameworkDirName);
1005e567f37dSKazu Hirata canInfer =
1006e567f37dSKazu Hirata !llvm::is_contained(inferred->second.ExcludedModules, Name);
10079194a91dSDouglas Gregor
1008c1d88ea5SBen Langmuir Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
1009c1d88ea5SBen Langmuir Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
1010c1d88ea5SBen Langmuir Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
1011ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes |=
1012ed84df00SBruno Cardoso Lopes inferred->second.Attrs.NoUndeclaredIncludes;
1013beee15e7SBen Langmuir ModuleMapFile = inferred->second.ModuleMapFile;
10149194a91dSDouglas Gregor }
10159194a91dSDouglas Gregor }
10169194a91dSDouglas Gregor }
10179194a91dSDouglas Gregor
10189194a91dSDouglas Gregor // If we're not allowed to infer a framework module, don't.
10199194a91dSDouglas Gregor if (!canInfer)
1020d2d442caSCraig Topper return nullptr;
1021beee15e7SBen Langmuir } else
10229d6448b1SBen Langmuir ModuleMapFile = getModuleMapFileForUniquing(Parent);
10239194a91dSDouglas Gregor
10249194a91dSDouglas Gregor
102556c64013SDouglas Gregor // Look for an umbrella header.
10262c1dd271SDylan Noblesmith SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
102717381a06SBenjamin Kramer llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
102864d8c781SDuncan P. N. Exon Smith auto UmbrellaHeader = FileMgr.getFile(UmbrellaName);
102956c64013SDouglas Gregor
103056c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the
103156c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good
103256c64013SDouglas Gregor // idea.
103356c64013SDouglas Gregor if (!UmbrellaHeader)
1034d2d442caSCraig Topper return nullptr;
103556c64013SDouglas Gregor
10369d6448b1SBen Langmuir Module *Result = new Module(ModuleName, SourceLocation(), Parent,
1037a7e2cc68SRichard Smith /*IsFramework=*/true, /*IsExplicit=*/false,
1038a7e2cc68SRichard Smith NumCreatedModules++);
10399d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = ModuleMapFile;
10409d6448b1SBen Langmuir Result->IsInferred = true;
10417e82e019SRichard Smith if (!Parent) {
10427e82e019SRichard Smith if (LangOpts.CurrentModule == ModuleName)
1043ba7f2f71SDaniel Jasper SourceModule = Result;
10447e82e019SRichard Smith Modules[ModuleName] = Result;
1045c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID;
1046ba7f2f71SDaniel Jasper }
1047c1d88ea5SBen Langmuir
1048c1d88ea5SBen Langmuir Result->IsSystem |= Attrs.IsSystem;
1049c1d88ea5SBen Langmuir Result->IsExternC |= Attrs.IsExternC;
1050c1d88ea5SBen Langmuir Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
1051ed84df00SBruno Cardoso Lopes Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
10522b63d15fSRichard Smith Result->Directory = FrameworkDir;
1053a686e1b0SDouglas Gregor
1054d3676d4bSMichael Spencer // Chop off the first framework bit, as that is implied.
1055d3676d4bSMichael Spencer StringRef RelativePath = UmbrellaName.str().substr(
1056d3676d4bSMichael Spencer Result->getTopLevelModule()->Directory->getName().size());
1057d3676d4bSMichael Spencer RelativePath = llvm::sys::path::relative_path(RelativePath);
1058d3676d4bSMichael Spencer
1059322f633cSDouglas Gregor // umbrella header "umbrella-header-name"
1060d3676d4bSMichael Spencer setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h", RelativePath);
1061d8bd7537SDouglas Gregor
1062d8bd7537SDouglas Gregor // export *
1063d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true));
1064d8bd7537SDouglas Gregor
1065a89c5ac4SDouglas Gregor // module * { export * }
1066a89c5ac4SDouglas Gregor Result->InferSubmodules = true;
1067a89c5ac4SDouglas Gregor Result->InferExportWildcard = true;
1068a89c5ac4SDouglas Gregor
1069e89dbc1dSDouglas Gregor // Look for subframeworks.
1070c080917eSRafael Espindola std::error_code EC;
10712c1dd271SDylan Noblesmith SmallString<128> SubframeworksDirName
1072ddaa69cbSDouglas Gregor = StringRef(FrameworkDir->getName());
1073e89dbc1dSDouglas Gregor llvm::sys::path::append(SubframeworksDirName, "Frameworks");
10742d4d8cb3SBenjamin Kramer llvm::sys::path::native(SubframeworksDirName);
1075db8a7422SDuncan P. N. Exon Smith llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
1076fc51490bSJonas Devlieghere for (llvm::vfs::directory_iterator
1077fc51490bSJonas Devlieghere Dir = FS.dir_begin(SubframeworksDirName, EC),
1078b171a59bSBruno Cardoso Lopes DirEnd;
1079e89dbc1dSDouglas Gregor Dir != DirEnd && !EC; Dir.increment(EC)) {
10800ae00567SSam McCall if (!StringRef(Dir->path()).endswith(".framework"))
1081e89dbc1dSDouglas Gregor continue;
1082f2161a70SDouglas Gregor
10838d323d15SHarlan Haskins if (auto SubframeworkDir =
10840ae00567SSam McCall FileMgr.getDirectory(Dir->path())) {
108507c22b78SDouglas Gregor // Note: as an egregious but useful hack, we use the real path here and
108607c22b78SDouglas Gregor // check whether it is actually a subdirectory of the parent directory.
108707c22b78SDouglas Gregor // This will not be the case if the 'subframework' is actually a symlink
108807c22b78SDouglas Gregor // out to a top-level framework.
10898d323d15SHarlan Haskins StringRef SubframeworkDirName =
10908d323d15SHarlan Haskins FileMgr.getCanonicalName(*SubframeworkDir);
109107c22b78SDouglas Gregor bool FoundParent = false;
109207c22b78SDouglas Gregor do {
109307c22b78SDouglas Gregor // Get the parent directory name.
109407c22b78SDouglas Gregor SubframeworkDirName
109507c22b78SDouglas Gregor = llvm::sys::path::parent_path(SubframeworkDirName);
109607c22b78SDouglas Gregor if (SubframeworkDirName.empty())
109707c22b78SDouglas Gregor break;
109807c22b78SDouglas Gregor
10998d323d15SHarlan Haskins if (auto SubDir = FileMgr.getDirectory(SubframeworkDirName)) {
11008d323d15SHarlan Haskins if (*SubDir == FrameworkDir) {
110107c22b78SDouglas Gregor FoundParent = true;
110207c22b78SDouglas Gregor break;
110307c22b78SDouglas Gregor }
11048d323d15SHarlan Haskins }
110507c22b78SDouglas Gregor } while (true);
110607c22b78SDouglas Gregor
110707c22b78SDouglas Gregor if (!FoundParent)
110807c22b78SDouglas Gregor continue;
110907c22b78SDouglas Gregor
1110e89dbc1dSDouglas Gregor // FIXME: Do we want to warn about subframeworks without umbrella headers?
11118d323d15SHarlan Haskins inferFrameworkModule(*SubframeworkDir, Attrs, Result);
1112e89dbc1dSDouglas Gregor }
1113e89dbc1dSDouglas Gregor }
1114e89dbc1dSDouglas Gregor
111511dfe6feSDouglas Gregor // If the module is a top-level framework, automatically link against the
111611dfe6feSDouglas Gregor // framework.
111711dfe6feSDouglas Gregor if (!Result->isSubFramework()) {
111811dfe6feSDouglas Gregor inferFrameworkLink(Result, FrameworkDir, FileMgr);
111911dfe6feSDouglas Gregor }
112011dfe6feSDouglas Gregor
112156c64013SDouglas Gregor return Result;
112256c64013SDouglas Gregor }
112356c64013SDouglas Gregor
createShadowedModule(StringRef Name,bool IsFramework,Module * ShadowingModule)11248587dfd9SBruno Cardoso Lopes Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
11258587dfd9SBruno Cardoso Lopes Module *ShadowingModule) {
11268587dfd9SBruno Cardoso Lopes
11278587dfd9SBruno Cardoso Lopes // Create a new module with this name.
11288587dfd9SBruno Cardoso Lopes Module *Result =
11298587dfd9SBruno Cardoso Lopes new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
11308587dfd9SBruno Cardoso Lopes /*IsExplicit=*/false, NumCreatedModules++);
11318587dfd9SBruno Cardoso Lopes Result->ShadowingModule = ShadowingModule;
1132fc76b4adSRichard Smith Result->markUnavailable(/*Unimportable*/true);
1133c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID;
11348587dfd9SBruno Cardoso Lopes ShadowModules.push_back(Result);
11358587dfd9SBruno Cardoso Lopes
11368587dfd9SBruno Cardoso Lopes return Result;
11378587dfd9SBruno Cardoso Lopes }
11388587dfd9SBruno Cardoso Lopes
setUmbrellaHeader(Module * Mod,const FileEntry * UmbrellaHeader,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)1139d3676d4bSMichael Spencer void ModuleMap::setUmbrellaHeader(
1140d3676d4bSMichael Spencer Module *Mod, const FileEntry *UmbrellaHeader, const Twine &NameAsWritten,
1141d3676d4bSMichael Spencer const Twine &PathRelativeToRootModuleDirectory) {
114297da9178SDaniel Jasper Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
114364d8c781SDuncan P. N. Exon Smith Mod->Umbrella = UmbrellaHeader;
11442b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str();
1145d3676d4bSMichael Spencer Mod->UmbrellaRelativeToRootModuleDirectory =
1146d3676d4bSMichael Spencer PathRelativeToRootModuleDirectory.str();
114764d8c781SDuncan P. N. Exon Smith UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
1148b3a0fa48SBruno Cardoso Lopes
1149b3a0fa48SBruno Cardoso Lopes // Notify callbacks that we just added a new header.
1150b3a0fa48SBruno Cardoso Lopes for (const auto &Cb : Callbacks)
1151b3a0fa48SBruno Cardoso Lopes Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
1152a89c5ac4SDouglas Gregor }
1153a89c5ac4SDouglas Gregor
setUmbrellaDir(Module * Mod,const DirectoryEntry * UmbrellaDir,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)115464d8c781SDuncan P. N. Exon Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
1155d3676d4bSMichael Spencer const Twine &NameAsWritten,
1156d3676d4bSMichael Spencer const Twine &PathRelativeToRootModuleDirectory) {
115764d8c781SDuncan P. N. Exon Smith Mod->Umbrella = UmbrellaDir;
11582b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str();
1159d3676d4bSMichael Spencer Mod->UmbrellaRelativeToRootModuleDirectory =
1160d3676d4bSMichael Spencer PathRelativeToRootModuleDirectory.str();
1161524e33e1SDouglas Gregor UmbrellaDirs[UmbrellaDir] = Mod;
1162524e33e1SDouglas Gregor }
1163524e33e1SDouglas Gregor
addUnresolvedHeader(Module * Mod,Module::UnresolvedHeaderDirective Header,bool & NeedsFramework)1164040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod,
11659f6020bcSBruno Cardoso Lopes Module::UnresolvedHeaderDirective Header,
11669f6020bcSBruno Cardoso Lopes bool &NeedsFramework) {
1167040e1266SRichard Smith // If there is a builtin counterpart to this file, add it now so it can
1168040e1266SRichard Smith // wrap the system header.
1169040e1266SRichard Smith if (resolveAsBuiltinHeader(Mod, Header)) {
1170040e1266SRichard Smith // If we have both a builtin and system version of the file, the
1171040e1266SRichard Smith // builtin version may want to inject macros into the system header, so
1172040e1266SRichard Smith // force the system header to be treated as a textual header in this
1173040e1266SRichard Smith // case.
1174040e1266SRichard Smith Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
1175040e1266SRichard Smith headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
1176040e1266SRichard Smith Header.HasBuiltinHeader = true;
11773c1a41adSRichard Smith }
1178040e1266SRichard Smith
1179040e1266SRichard Smith // If possible, don't stat the header until we need to. This requires the
1180040e1266SRichard Smith // user to have provided us with some stat information about the file.
1181040e1266SRichard Smith // FIXME: Add support for lazily stat'ing umbrella headers and excluded
1182040e1266SRichard Smith // headers.
1183040e1266SRichard Smith if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
1184040e1266SRichard Smith Header.Kind != Module::HK_Excluded) {
1185040e1266SRichard Smith // We expect more variation in mtime than size, so if we're given both,
1186040e1266SRichard Smith // use the mtime as the key.
1187040e1266SRichard Smith if (Header.ModTime)
1188040e1266SRichard Smith LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
1189040e1266SRichard Smith else
1190040e1266SRichard Smith LazyHeadersBySize[*Header.Size].push_back(Mod);
1191040e1266SRichard Smith Mod->UnresolvedHeaders.push_back(Header);
1192040e1266SRichard Smith return;
1193040e1266SRichard Smith }
1194040e1266SRichard Smith
1195040e1266SRichard Smith // We don't have stat information or can't defer looking this file up.
1196040e1266SRichard Smith // Perform the lookup now.
11979f6020bcSBruno Cardoso Lopes resolveHeader(Mod, Header, NeedsFramework);
1198040e1266SRichard Smith }
1199040e1266SRichard Smith
resolveHeaderDirectives(const FileEntry * File) const1200040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
1201040e1266SRichard Smith auto BySize = LazyHeadersBySize.find(File->getSize());
1202040e1266SRichard Smith if (BySize != LazyHeadersBySize.end()) {
1203040e1266SRichard Smith for (auto *M : BySize->second)
12048f4ea36bSAdam Czachorowski resolveHeaderDirectives(M, File);
1205040e1266SRichard Smith LazyHeadersBySize.erase(BySize);
1206040e1266SRichard Smith }
1207040e1266SRichard Smith
1208040e1266SRichard Smith auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
1209040e1266SRichard Smith if (ByModTime != LazyHeadersByModTime.end()) {
1210040e1266SRichard Smith for (auto *M : ByModTime->second)
12118f4ea36bSAdam Czachorowski resolveHeaderDirectives(M, File);
1212040e1266SRichard Smith LazyHeadersByModTime.erase(ByModTime);
1213040e1266SRichard Smith }
1214040e1266SRichard Smith }
1215040e1266SRichard Smith
resolveHeaderDirectives(Module * Mod,llvm::Optional<const FileEntry * > File) const12168f4ea36bSAdam Czachorowski void ModuleMap::resolveHeaderDirectives(
12178f4ea36bSAdam Czachorowski Module *Mod, llvm::Optional<const FileEntry *> File) const {
12189f6020bcSBruno Cardoso Lopes bool NeedsFramework = false;
12198f4ea36bSAdam Czachorowski SmallVector<Module::UnresolvedHeaderDirective, 1> NewHeaders;
1220cb2c8f69SKazu Hirata const auto Size = File ? File.value()->getSize() : 0;
1221cb2c8f69SKazu Hirata const auto ModTime = File ? File.value()->getModificationTime() : 0;
12228f4ea36bSAdam Czachorowski
12238f4ea36bSAdam Czachorowski for (auto &Header : Mod->UnresolvedHeaders) {
12248f4ea36bSAdam Czachorowski if (File && ((Header.ModTime && Header.ModTime != ModTime) ||
12258f4ea36bSAdam Czachorowski (Header.Size && Header.Size != Size)))
12268f4ea36bSAdam Czachorowski NewHeaders.push_back(Header);
12278f4ea36bSAdam Czachorowski else
1228040e1266SRichard Smith // This operation is logically const; we're just changing how we represent
1229040e1266SRichard Smith // the header information for this file.
12309f6020bcSBruno Cardoso Lopes const_cast<ModuleMap *>(this)->resolveHeader(Mod, Header, NeedsFramework);
12318f4ea36bSAdam Czachorowski }
12328f4ea36bSAdam Czachorowski Mod->UnresolvedHeaders.swap(NewHeaders);
12330e98d938SNAKAMURA Takumi }
1234202210b3SRichard Smith
addHeader(Module * Mod,Module::Header Header,ModuleHeaderRole Role,bool Imported)12353c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header,
1236d8879c85SRichard Smith ModuleHeaderRole Role, bool Imported) {
1237386bb073SRichard Smith KnownHeader KH(Mod, Role);
12383c1a41adSRichard Smith
1239386bb073SRichard Smith // Only add each header to the headers list once.
1240386bb073SRichard Smith // FIXME: Should we diagnose if a header is listed twice in the
1241386bb073SRichard Smith // same module definition?
1242386bb073SRichard Smith auto &HeaderList = Headers[Header.Entry];
12437cc8fa2dSKazu Hirata if (llvm::is_contained(HeaderList, KH))
1244386bb073SRichard Smith return;
1245386bb073SRichard Smith
1246386bb073SRichard Smith HeaderList.push_back(KH);
12471ec383c7SPiotr Padlewski Mod->Headers[headerRoleToKind(Role)].push_back(Header);
1248386bb073SRichard Smith
12497e82e019SRichard Smith bool isCompilingModuleHeader =
1250bbcc9f04SRichard Smith LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
1251d8879c85SRichard Smith if (!Imported || isCompilingModuleHeader) {
1252d8879c85SRichard Smith // When we import HeaderFileInfo, the external source is expected to
1253d8879c85SRichard Smith // set the isModuleHeader flag itself.
1254d8879c85SRichard Smith HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
1255d8879c85SRichard Smith isCompilingModuleHeader);
1256d8879c85SRichard Smith }
1257e62cfd7cSBruno Cardoso Lopes
1258e62cfd7cSBruno Cardoso Lopes // Notify callbacks that we just added a new header.
1259e62cfd7cSBruno Cardoso Lopes for (const auto &Cb : Callbacks)
1260f0841790SBruno Cardoso Lopes Cb->moduleMapAddHeader(Header.Entry->getName());
1261a89c5ac4SDouglas Gregor }
1262a89c5ac4SDouglas Gregor
excludeHeader(Module * Mod,Module::Header Header)12633c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
1264feb54b6dSRichard Smith // Add this as a known header so we won't implicitly add it to any
1265feb54b6dSRichard Smith // umbrella directory module.
1266feb54b6dSRichard Smith // FIXME: Should we only exclude it from umbrella modules within the
1267feb54b6dSRichard Smith // specified module?
12683c1a41adSRichard Smith (void) Headers[Header.Entry];
12693c1a41adSRichard Smith
12703c1a41adSRichard Smith Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
1271feb54b6dSRichard Smith }
1272feb54b6dSRichard Smith
1273514b636aSDouglas Gregor const FileEntry *
getContainingModuleMapFile(const Module * Module) const12744b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const {
12751f76c4e8SManuel Klimek if (Module->DefinitionLoc.isInvalid())
1276d2d442caSCraig Topper return nullptr;
1277514b636aSDouglas Gregor
12781f76c4e8SManuel Klimek return SourceMgr.getFileEntryForID(
12791f76c4e8SManuel Klimek SourceMgr.getFileID(Module->DefinitionLoc));
1280514b636aSDouglas Gregor }
1281514b636aSDouglas Gregor
getModuleMapFileForUniquing(const Module * M) const12824b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
12839d6448b1SBen Langmuir if (M->IsInferred) {
12849d6448b1SBen Langmuir assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
12859d6448b1SBen Langmuir return InferredModuleAllowedBy.find(M)->second;
12869d6448b1SBen Langmuir }
12879d6448b1SBen Langmuir return getContainingModuleMapFile(M);
12889d6448b1SBen Langmuir }
12899d6448b1SBen Langmuir
setInferredModuleAllowedBy(Module * M,const FileEntry * ModMap)12909d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
12919d6448b1SBen Langmuir assert(M->IsInferred && "module not inferred");
12929d6448b1SBen Langmuir InferredModuleAllowedBy[M] = ModMap;
12939d6448b1SBen Langmuir }
12949d6448b1SBen Langmuir
addAdditionalModuleMapFile(const Module * M,const FileEntry * ModuleMap)1295e08464fbSReid Kleckner void ModuleMap::addAdditionalModuleMapFile(const Module *M,
1296e08464fbSReid Kleckner const FileEntry *ModuleMap) {
1297e08464fbSReid Kleckner AdditionalModMaps[M].insert(ModuleMap);
1298e08464fbSReid Kleckner }
1299e08464fbSReid Kleckner
dump()1300cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() {
1301718292f2SDouglas Gregor llvm::errs() << "Modules:";
1302718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1303718292f2SDouglas Gregor MEnd = Modules.end();
1304718292f2SDouglas Gregor M != MEnd; ++M)
1305d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2);
1306718292f2SDouglas Gregor
1307718292f2SDouglas Gregor llvm::errs() << "Headers:";
130859527666SDouglas Gregor for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1309718292f2SDouglas Gregor H != HEnd; ++H) {
131097da9178SDaniel Jasper llvm::errs() << " \"" << H->first->getName() << "\" -> ";
131197da9178SDaniel Jasper for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
131297da9178SDaniel Jasper E = H->second.end();
131397da9178SDaniel Jasper I != E; ++I) {
131497da9178SDaniel Jasper if (I != H->second.begin())
131597da9178SDaniel Jasper llvm::errs() << ",";
131697da9178SDaniel Jasper llvm::errs() << I->getModule()->getFullModuleName();
131797da9178SDaniel Jasper }
131897da9178SDaniel Jasper llvm::errs() << "\n";
1319718292f2SDouglas Gregor }
1320718292f2SDouglas Gregor }
1321718292f2SDouglas Gregor
resolveExports(Module * Mod,bool Complain)13222b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
132342413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedExports);
132442413141SRichard Smith Mod->UnresolvedExports.clear();
132542413141SRichard Smith for (auto &UE : Unresolved) {
132642413141SRichard Smith Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
1327f5eedd05SDouglas Gregor if (Export.getPointer() || Export.getInt())
13282b82c2a5SDouglas Gregor Mod->Exports.push_back(Export);
13292b82c2a5SDouglas Gregor else
133042413141SRichard Smith Mod->UnresolvedExports.push_back(UE);
13312b82c2a5SDouglas Gregor }
133242413141SRichard Smith return !Mod->UnresolvedExports.empty();
13332b82c2a5SDouglas Gregor }
13342b82c2a5SDouglas Gregor
resolveUses(Module * Mod,bool Complain)1335ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
133642413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedDirectUses);
133742413141SRichard Smith Mod->UnresolvedDirectUses.clear();
133842413141SRichard Smith for (auto &UDU : Unresolved) {
133942413141SRichard Smith Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
1340ba7f2f71SDaniel Jasper if (DirectUse)
1341ba7f2f71SDaniel Jasper Mod->DirectUses.push_back(DirectUse);
1342ba7f2f71SDaniel Jasper else
134342413141SRichard Smith Mod->UnresolvedDirectUses.push_back(UDU);
1344ba7f2f71SDaniel Jasper }
134542413141SRichard Smith return !Mod->UnresolvedDirectUses.empty();
1346ba7f2f71SDaniel Jasper }
1347ba7f2f71SDaniel Jasper
resolveConflicts(Module * Mod,bool Complain)1348fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
134942413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedConflicts);
135042413141SRichard Smith Mod->UnresolvedConflicts.clear();
135142413141SRichard Smith for (auto &UC : Unresolved) {
135242413141SRichard Smith if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1353fb912657SDouglas Gregor Module::Conflict Conflict;
1354fb912657SDouglas Gregor Conflict.Other = OtherMod;
135542413141SRichard Smith Conflict.Message = UC.Message;
1356fb912657SDouglas Gregor Mod->Conflicts.push_back(Conflict);
135742413141SRichard Smith } else
135842413141SRichard Smith Mod->UnresolvedConflicts.push_back(UC);
1359fb912657SDouglas Gregor }
136042413141SRichard Smith return !Mod->UnresolvedConflicts.empty();
1361fb912657SDouglas Gregor }
1362fb912657SDouglas Gregor
1363718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1364718292f2SDouglas Gregor // Module map file parser
1365718292f2SDouglas Gregor //----------------------------------------------------------------------------//
1366718292f2SDouglas Gregor
1367718292f2SDouglas Gregor namespace clang {
1368afd1b1c9SEugene Zelenko
13699fc8faf9SAdrian Prantl /// A token in a module map file.
1370718292f2SDouglas Gregor struct MMToken {
1371718292f2SDouglas Gregor enum TokenKind {
13721fb5c3a6SDouglas Gregor Comma,
137335b13eceSDouglas Gregor ConfigMacros,
1374fb912657SDouglas Gregor Conflict,
1375718292f2SDouglas Gregor EndOfFile,
1376718292f2SDouglas Gregor HeaderKeyword,
1377718292f2SDouglas Gregor Identifier,
1378a3feee2aSRichard Smith Exclaim,
137959527666SDouglas Gregor ExcludeKeyword,
1380718292f2SDouglas Gregor ExplicitKeyword,
13812b82c2a5SDouglas Gregor ExportKeyword,
1382f0b11de2SDouglas Gregor ExportAsKeyword,
138397292843SDaniel Jasper ExternKeyword,
1384755b2055SDouglas Gregor FrameworkKeyword,
13856ddfca91SDouglas Gregor LinkKeyword,
1386718292f2SDouglas Gregor ModuleKeyword,
13872b82c2a5SDouglas Gregor Period,
1388b53e5483SLawrence Crowl PrivateKeyword,
1389718292f2SDouglas Gregor UmbrellaKeyword,
1390ba7f2f71SDaniel Jasper UseKeyword,
13911fb5c3a6SDouglas Gregor RequiresKeyword,
13922b82c2a5SDouglas Gregor Star,
1393718292f2SDouglas Gregor StringLiteral,
1394040e1266SRichard Smith IntegerLiteral,
1395306d8920SRichard Smith TextualKeyword,
1396718292f2SDouglas Gregor LBrace,
1397a686e1b0SDouglas Gregor RBrace,
1398a686e1b0SDouglas Gregor LSquare,
1399a686e1b0SDouglas Gregor RSquare
1400718292f2SDouglas Gregor } Kind;
1401718292f2SDouglas Gregor
140221401a72SSimon Tatham SourceLocation::UIntTy Location;
1403718292f2SDouglas Gregor unsigned StringLength;
1404040e1266SRichard Smith union {
1405040e1266SRichard Smith // If Kind != IntegerLiteral.
1406718292f2SDouglas Gregor const char *StringData;
1407afd1b1c9SEugene Zelenko
1408040e1266SRichard Smith // If Kind == IntegerLiteral.
1409040e1266SRichard Smith uint64_t IntegerValue;
1410040e1266SRichard Smith };
1411718292f2SDouglas Gregor
clearclang::MMToken1412718292f2SDouglas Gregor void clear() {
1413718292f2SDouglas Gregor Kind = EndOfFile;
1414718292f2SDouglas Gregor Location = 0;
1415718292f2SDouglas Gregor StringLength = 0;
1416d2d442caSCraig Topper StringData = nullptr;
1417718292f2SDouglas Gregor }
1418718292f2SDouglas Gregor
isclang::MMToken1419718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; }
1420718292f2SDouglas Gregor
getLocationclang::MMToken1421718292f2SDouglas Gregor SourceLocation getLocation() const {
1422718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location);
1423718292f2SDouglas Gregor }
1424718292f2SDouglas Gregor
getIntegerclang::MMToken1425040e1266SRichard Smith uint64_t getInteger() const {
1426040e1266SRichard Smith return Kind == IntegerLiteral ? IntegerValue : 0;
1427040e1266SRichard Smith }
1428040e1266SRichard Smith
getStringclang::MMToken1429718292f2SDouglas Gregor StringRef getString() const {
1430040e1266SRichard Smith return Kind == IntegerLiteral ? StringRef()
1431040e1266SRichard Smith : StringRef(StringData, StringLength);
1432718292f2SDouglas Gregor }
1433718292f2SDouglas Gregor };
1434718292f2SDouglas Gregor
1435718292f2SDouglas Gregor class ModuleMapParser {
1436718292f2SDouglas Gregor Lexer &L;
1437718292f2SDouglas Gregor SourceManager &SourceMgr;
1438bc10b9fbSDouglas Gregor
14399fc8faf9SAdrian Prantl /// Default target information, used only for string literal
1440bc10b9fbSDouglas Gregor /// parsing.
1441bc10b9fbSDouglas Gregor const TargetInfo *Target;
1442bc10b9fbSDouglas Gregor
1443718292f2SDouglas Gregor DiagnosticsEngine &Diags;
1444718292f2SDouglas Gregor ModuleMap ⤅
1445718292f2SDouglas Gregor
14469fc8faf9SAdrian Prantl /// The current module map file.
1447beee15e7SBen Langmuir const FileEntry *ModuleMapFile;
1448beee15e7SBen Langmuir
14499f6020bcSBruno Cardoso Lopes /// Source location of most recent parsed module declaration
14509f6020bcSBruno Cardoso Lopes SourceLocation CurrModuleDeclLoc;
14519f6020bcSBruno Cardoso Lopes
14529fc8faf9SAdrian Prantl /// The directory that file names in this module map file should
14539acb99e3SRichard Smith /// be resolved relative to.
14545257fc63SDouglas Gregor const DirectoryEntry *Directory;
14555257fc63SDouglas Gregor
14569fc8faf9SAdrian Prantl /// Whether this module map is in a system header directory.
1457963c5535SDouglas Gregor bool IsSystem;
1458963c5535SDouglas Gregor
14599fc8faf9SAdrian Prantl /// Whether an error occurred.
1460afd1b1c9SEugene Zelenko bool HadError = false;
1461718292f2SDouglas Gregor
14629fc8faf9SAdrian Prantl /// Stores string data for the various string literals referenced
1463718292f2SDouglas Gregor /// during parsing.
1464718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData;
1465718292f2SDouglas Gregor
14669fc8faf9SAdrian Prantl /// The current token.
1467718292f2SDouglas Gregor MMToken Tok;
1468718292f2SDouglas Gregor
14699fc8faf9SAdrian Prantl /// The active module.
1470afd1b1c9SEugene Zelenko Module *ActiveModule = nullptr;
1471718292f2SDouglas Gregor
14729fc8faf9SAdrian Prantl /// Whether a module uses the 'requires excluded' hack to mark its
14737ff29148SBen Langmuir /// contents as 'textual'.
14747ff29148SBen Langmuir ///
14757ff29148SBen Langmuir /// On older Darwin SDK versions, 'requires excluded' is used to mark the
14767ff29148SBen Langmuir /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
14777ff29148SBen Langmuir /// non-modular headers. For backwards compatibility, we continue to
14787ff29148SBen Langmuir /// support this idiom for just these modules, and map the headers to
14797ff29148SBen Langmuir /// 'textual' to match the original intent.
14807ff29148SBen Langmuir llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
14817ff29148SBen Langmuir
14829fc8faf9SAdrian Prantl /// Consume the current token and return its location.
1483718292f2SDouglas Gregor SourceLocation consumeToken();
1484718292f2SDouglas Gregor
14859fc8faf9SAdrian Prantl /// Skip tokens until we reach the a token with the given kind
1486718292f2SDouglas Gregor /// (or the end of the file).
1487718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K);
1488718292f2SDouglas Gregor
1489afd1b1c9SEugene Zelenko using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
1490afd1b1c9SEugene Zelenko
1491e7ab3669SDouglas Gregor bool parseModuleId(ModuleId &Id);
1492718292f2SDouglas Gregor void parseModuleDecl();
149397292843SDaniel Jasper void parseExternModuleDecl();
14941fb5c3a6SDouglas Gregor void parseRequiresDecl();
1495afd1b1c9SEugene Zelenko void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
1496524e33e1SDouglas Gregor void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
14972b82c2a5SDouglas Gregor void parseExportDecl();
1498f0b11de2SDouglas Gregor void parseExportAsDecl();
1499ba7f2f71SDaniel Jasper void parseUseDecl();
15006ddfca91SDouglas Gregor void parseLinkDecl();
150135b13eceSDouglas Gregor void parseConfigMacros();
1502fb912657SDouglas Gregor void parseConflict();
15039194a91dSDouglas Gregor void parseInferredModuleDecl(bool Framework, bool Explicit);
1504c1d88ea5SBen Langmuir
15055f11e128SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra
15065f11e128SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH
15075f11e128SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written
15085f11e128SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
15095f11e128SBruno Cardoso Lopes void diagnosePrivateModules(SourceLocation ExplicitLoc,
15105f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc);
15115f11e128SBruno Cardoso Lopes
1512afd1b1c9SEugene Zelenko using Attributes = ModuleMap::Attributes;
1513afd1b1c9SEugene Zelenko
15144442605fSBill Wendling bool parseOptionalAttributes(Attributes &Attrs);
1515718292f2SDouglas Gregor
1516718292f2SDouglas Gregor public:
ModuleMapParser(Lexer & L,SourceManager & SourceMgr,const TargetInfo * Target,DiagnosticsEngine & Diags,ModuleMap & Map,const FileEntry * ModuleMapFile,const DirectoryEntry * Directory,bool IsSystem)1517718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
15188587dfd9SBruno Cardoso Lopes const TargetInfo *Target, DiagnosticsEngine &Diags,
15198587dfd9SBruno Cardoso Lopes ModuleMap &Map, const FileEntry *ModuleMapFile,
1520c192d194SBruno Cardoso Lopes const DirectoryEntry *Directory, bool IsSystem)
1521bc10b9fbSDouglas Gregor : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
1522beee15e7SBen Langmuir ModuleMapFile(ModuleMapFile), Directory(Directory),
1523c192d194SBruno Cardoso Lopes IsSystem(IsSystem) {
1524718292f2SDouglas Gregor Tok.clear();
1525718292f2SDouglas Gregor consumeToken();
1526718292f2SDouglas Gregor }
1527718292f2SDouglas Gregor
1528718292f2SDouglas Gregor bool parseModuleMapFile();
15298128f332SRichard Smith
terminatedByDirective()15308128f332SRichard Smith bool terminatedByDirective() { return false; }
getLocation()15318128f332SRichard Smith SourceLocation getLocation() { return Tok.getLocation(); }
1532718292f2SDouglas Gregor };
1533afd1b1c9SEugene Zelenko
1534afd1b1c9SEugene Zelenko } // namespace clang
1535718292f2SDouglas Gregor
consumeToken()1536718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() {
1537718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation();
1538718292f2SDouglas Gregor
15398128f332SRichard Smith retry:
15408128f332SRichard Smith Tok.clear();
1541718292f2SDouglas Gregor Token LToken;
1542718292f2SDouglas Gregor L.LexFromRawLexer(LToken);
1543718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding();
1544718292f2SDouglas Gregor switch (LToken.getKind()) {
15452d57cea2SAlp Toker case tok::raw_identifier: {
15462d57cea2SAlp Toker StringRef RI = LToken.getRawIdentifier();
15472d57cea2SAlp Toker Tok.StringData = RI.data();
15482d57cea2SAlp Toker Tok.StringLength = RI.size();
15492d57cea2SAlp Toker Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
155035b13eceSDouglas Gregor .Case("config_macros", MMToken::ConfigMacros)
1551fb912657SDouglas Gregor .Case("conflict", MMToken::Conflict)
155259527666SDouglas Gregor .Case("exclude", MMToken::ExcludeKeyword)
1553718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword)
15542b82c2a5SDouglas Gregor .Case("export", MMToken::ExportKeyword)
1555f0b11de2SDouglas Gregor .Case("export_as", MMToken::ExportAsKeyword)
155697292843SDaniel Jasper .Case("extern", MMToken::ExternKeyword)
1557755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword)
155835b13eceSDouglas Gregor .Case("header", MMToken::HeaderKeyword)
15596ddfca91SDouglas Gregor .Case("link", MMToken::LinkKeyword)
1560718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword)
1561b53e5483SLawrence Crowl .Case("private", MMToken::PrivateKeyword)
15621fb5c3a6SDouglas Gregor .Case("requires", MMToken::RequiresKeyword)
1563306d8920SRichard Smith .Case("textual", MMToken::TextualKeyword)
1564718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword)
1565ba7f2f71SDaniel Jasper .Case("use", MMToken::UseKeyword)
1566718292f2SDouglas Gregor .Default(MMToken::Identifier);
1567718292f2SDouglas Gregor break;
15682d57cea2SAlp Toker }
1569718292f2SDouglas Gregor
15701fb5c3a6SDouglas Gregor case tok::comma:
15711fb5c3a6SDouglas Gregor Tok.Kind = MMToken::Comma;
15721fb5c3a6SDouglas Gregor break;
15731fb5c3a6SDouglas Gregor
1574718292f2SDouglas Gregor case tok::eof:
1575718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile;
1576718292f2SDouglas Gregor break;
1577718292f2SDouglas Gregor
1578718292f2SDouglas Gregor case tok::l_brace:
1579718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace;
1580718292f2SDouglas Gregor break;
1581718292f2SDouglas Gregor
1582a686e1b0SDouglas Gregor case tok::l_square:
1583a686e1b0SDouglas Gregor Tok.Kind = MMToken::LSquare;
1584a686e1b0SDouglas Gregor break;
1585a686e1b0SDouglas Gregor
15862b82c2a5SDouglas Gregor case tok::period:
15872b82c2a5SDouglas Gregor Tok.Kind = MMToken::Period;
15882b82c2a5SDouglas Gregor break;
15892b82c2a5SDouglas Gregor
1590718292f2SDouglas Gregor case tok::r_brace:
1591718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace;
1592718292f2SDouglas Gregor break;
1593718292f2SDouglas Gregor
1594a686e1b0SDouglas Gregor case tok::r_square:
1595a686e1b0SDouglas Gregor Tok.Kind = MMToken::RSquare;
1596a686e1b0SDouglas Gregor break;
1597a686e1b0SDouglas Gregor
15982b82c2a5SDouglas Gregor case tok::star:
15992b82c2a5SDouglas Gregor Tok.Kind = MMToken::Star;
16002b82c2a5SDouglas Gregor break;
16012b82c2a5SDouglas Gregor
1602a3feee2aSRichard Smith case tok::exclaim:
1603a3feee2aSRichard Smith Tok.Kind = MMToken::Exclaim;
1604a3feee2aSRichard Smith break;
1605a3feee2aSRichard Smith
1606718292f2SDouglas Gregor case tok::string_literal: {
1607d67aea28SRichard Smith if (LToken.hasUDSuffix()) {
1608d67aea28SRichard Smith Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
1609d67aea28SRichard Smith HadError = true;
1610d67aea28SRichard Smith goto retry;
1611d67aea28SRichard Smith }
1612d67aea28SRichard Smith
1613718292f2SDouglas Gregor // Parse the string literal.
1614718292f2SDouglas Gregor LangOptions LangOpts;
16159d5583efSCraig Topper StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
1616718292f2SDouglas Gregor if (StringLiteral.hadError)
1617718292f2SDouglas Gregor goto retry;
1618718292f2SDouglas Gregor
1619718292f2SDouglas Gregor // Copy the string literal into our string data allocator.
1620718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength();
1621718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1);
1622718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length);
1623718292f2SDouglas Gregor Saved[Length] = 0;
1624718292f2SDouglas Gregor
1625718292f2SDouglas Gregor // Form the token.
1626718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral;
1627718292f2SDouglas Gregor Tok.StringData = Saved;
1628718292f2SDouglas Gregor Tok.StringLength = Length;
1629718292f2SDouglas Gregor break;
1630718292f2SDouglas Gregor }
1631718292f2SDouglas Gregor
1632040e1266SRichard Smith case tok::numeric_constant: {
1633040e1266SRichard Smith // We don't support any suffixes or other complications.
1634040e1266SRichard Smith SmallString<32> SpellingBuffer;
1635040e1266SRichard Smith SpellingBuffer.resize(LToken.getLength() + 1);
1636040e1266SRichard Smith const char *Start = SpellingBuffer.data();
1637040e1266SRichard Smith unsigned Length =
1638d813116cSDawid Jurczak Lexer::getSpelling(LToken, Start, SourceMgr, Map.LangOpts);
1639040e1266SRichard Smith uint64_t Value;
1640040e1266SRichard Smith if (StringRef(Start, Length).getAsInteger(0, Value)) {
1641040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1642040e1266SRichard Smith HadError = true;
1643040e1266SRichard Smith goto retry;
1644040e1266SRichard Smith }
1645040e1266SRichard Smith
1646040e1266SRichard Smith Tok.Kind = MMToken::IntegerLiteral;
1647040e1266SRichard Smith Tok.IntegerValue = Value;
1648040e1266SRichard Smith break;
1649040e1266SRichard Smith }
1650040e1266SRichard Smith
1651718292f2SDouglas Gregor case tok::comment:
1652718292f2SDouglas Gregor goto retry;
1653718292f2SDouglas Gregor
16548128f332SRichard Smith case tok::hash:
16558128f332SRichard Smith // A module map can be terminated prematurely by
16568128f332SRichard Smith // #pragma clang module contents
16578128f332SRichard Smith // When building the module, we'll treat the rest of the file as the
16588128f332SRichard Smith // contents of the module.
16598128f332SRichard Smith {
16608128f332SRichard Smith auto NextIsIdent = [&](StringRef Str) -> bool {
16618128f332SRichard Smith L.LexFromRawLexer(LToken);
16628128f332SRichard Smith return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
16638128f332SRichard Smith LToken.getRawIdentifier() == Str;
16648128f332SRichard Smith };
16658128f332SRichard Smith if (NextIsIdent("pragma") && NextIsIdent("clang") &&
16668128f332SRichard Smith NextIsIdent("module") && NextIsIdent("contents")) {
16678128f332SRichard Smith Tok.Kind = MMToken::EndOfFile;
16688128f332SRichard Smith break;
16698128f332SRichard Smith }
16708128f332SRichard Smith }
16718128f332SRichard Smith LLVM_FALLTHROUGH;
16728128f332SRichard Smith
1673718292f2SDouglas Gregor default:
16748128f332SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1675718292f2SDouglas Gregor HadError = true;
1676718292f2SDouglas Gregor goto retry;
1677718292f2SDouglas Gregor }
1678718292f2SDouglas Gregor
1679718292f2SDouglas Gregor return Result;
1680718292f2SDouglas Gregor }
1681718292f2SDouglas Gregor
skipUntil(MMToken::TokenKind K)1682718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
1683718292f2SDouglas Gregor unsigned braceDepth = 0;
1684a686e1b0SDouglas Gregor unsigned squareDepth = 0;
1685718292f2SDouglas Gregor do {
1686718292f2SDouglas Gregor switch (Tok.Kind) {
1687718292f2SDouglas Gregor case MMToken::EndOfFile:
1688718292f2SDouglas Gregor return;
1689718292f2SDouglas Gregor
1690718292f2SDouglas Gregor case MMToken::LBrace:
1691a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1692718292f2SDouglas Gregor return;
1693718292f2SDouglas Gregor
1694718292f2SDouglas Gregor ++braceDepth;
1695718292f2SDouglas Gregor break;
1696718292f2SDouglas Gregor
1697a686e1b0SDouglas Gregor case MMToken::LSquare:
1698a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1699a686e1b0SDouglas Gregor return;
1700a686e1b0SDouglas Gregor
1701a686e1b0SDouglas Gregor ++squareDepth;
1702a686e1b0SDouglas Gregor break;
1703a686e1b0SDouglas Gregor
1704718292f2SDouglas Gregor case MMToken::RBrace:
1705718292f2SDouglas Gregor if (braceDepth > 0)
1706718292f2SDouglas Gregor --braceDepth;
1707718292f2SDouglas Gregor else if (Tok.is(K))
1708718292f2SDouglas Gregor return;
1709718292f2SDouglas Gregor break;
1710718292f2SDouglas Gregor
1711a686e1b0SDouglas Gregor case MMToken::RSquare:
1712a686e1b0SDouglas Gregor if (squareDepth > 0)
1713a686e1b0SDouglas Gregor --squareDepth;
1714a686e1b0SDouglas Gregor else if (Tok.is(K))
1715a686e1b0SDouglas Gregor return;
1716a686e1b0SDouglas Gregor break;
1717a686e1b0SDouglas Gregor
1718718292f2SDouglas Gregor default:
1719a686e1b0SDouglas Gregor if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
1720718292f2SDouglas Gregor return;
1721718292f2SDouglas Gregor break;
1722718292f2SDouglas Gregor }
1723718292f2SDouglas Gregor
1724718292f2SDouglas Gregor consumeToken();
1725718292f2SDouglas Gregor } while (true);
1726718292f2SDouglas Gregor }
1727718292f2SDouglas Gregor
17289fc8faf9SAdrian Prantl /// Parse a module-id.
1729e7ab3669SDouglas Gregor ///
1730e7ab3669SDouglas Gregor /// module-id:
1731e7ab3669SDouglas Gregor /// identifier
1732e7ab3669SDouglas Gregor /// identifier '.' module-id
1733e7ab3669SDouglas Gregor ///
1734e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise.
parseModuleId(ModuleId & Id)1735e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) {
1736e7ab3669SDouglas Gregor Id.clear();
1737e7ab3669SDouglas Gregor do {
17383cd34c76SDaniel Jasper if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1739adcd0268SBenjamin Kramer Id.push_back(
1740adcd0268SBenjamin Kramer std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
1741e7ab3669SDouglas Gregor consumeToken();
1742e7ab3669SDouglas Gregor } else {
1743e7ab3669SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1744e7ab3669SDouglas Gregor return true;
1745e7ab3669SDouglas Gregor }
1746e7ab3669SDouglas Gregor
1747e7ab3669SDouglas Gregor if (!Tok.is(MMToken::Period))
1748e7ab3669SDouglas Gregor break;
1749e7ab3669SDouglas Gregor
1750e7ab3669SDouglas Gregor consumeToken();
1751e7ab3669SDouglas Gregor } while (true);
1752e7ab3669SDouglas Gregor
1753e7ab3669SDouglas Gregor return false;
1754e7ab3669SDouglas Gregor }
1755e7ab3669SDouglas Gregor
1756a686e1b0SDouglas Gregor namespace {
1757afd1b1c9SEugene Zelenko
17589fc8faf9SAdrian Prantl /// Enumerates the known attributes.
1759a686e1b0SDouglas Gregor enum AttributeKind {
17609fc8faf9SAdrian Prantl /// An unknown attribute.
1761a686e1b0SDouglas Gregor AT_unknown,
1762afd1b1c9SEugene Zelenko
17639fc8faf9SAdrian Prantl /// The 'system' attribute.
176435b13eceSDouglas Gregor AT_system,
1765afd1b1c9SEugene Zelenko
17669fc8faf9SAdrian Prantl /// The 'extern_c' attribute.
176777944868SRichard Smith AT_extern_c,
1768afd1b1c9SEugene Zelenko
17699fc8faf9SAdrian Prantl /// The 'exhaustive' attribute.
1770ed84df00SBruno Cardoso Lopes AT_exhaustive,
1771afd1b1c9SEugene Zelenko
17729fc8faf9SAdrian Prantl /// The 'no_undeclared_includes' attribute.
1773ed84df00SBruno Cardoso Lopes AT_no_undeclared_includes
1774a686e1b0SDouglas Gregor };
1775afd1b1c9SEugene Zelenko
1776afd1b1c9SEugene Zelenko } // namespace
1777a686e1b0SDouglas Gregor
177829729919SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra
177929729919SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH
178029729919SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written
178129729919SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
diagnosePrivateModules(SourceLocation ExplicitLoc,SourceLocation FrameworkLoc)17825f11e128SBruno Cardoso Lopes void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
17835f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc) {
178429729919SBruno Cardoso Lopes auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
17857d29486dSBruno Cardoso Lopes const Module *M, SourceRange ReplLoc) {
178629729919SBruno Cardoso Lopes auto D = Diags.Report(ActiveModule->DefinitionLoc,
178729729919SBruno Cardoso Lopes diag::note_mmap_rename_top_level_private_module);
178829729919SBruno Cardoso Lopes D << BadName << M->Name;
17897d29486dSBruno Cardoso Lopes D << FixItHint::CreateReplacement(ReplLoc, Canonical);
179029729919SBruno Cardoso Lopes };
179129729919SBruno Cardoso Lopes
179229729919SBruno Cardoso Lopes for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
179329729919SBruno Cardoso Lopes auto const *M = E->getValue();
179429729919SBruno Cardoso Lopes if (M->Directory != ActiveModule->Directory)
179529729919SBruno Cardoso Lopes continue;
179629729919SBruno Cardoso Lopes
179729729919SBruno Cardoso Lopes SmallString<128> FullName(ActiveModule->getFullModuleName());
179829729919SBruno Cardoso Lopes if (!FullName.startswith(M->Name) && !FullName.endswith("Private"))
179929729919SBruno Cardoso Lopes continue;
18005f11e128SBruno Cardoso Lopes SmallString<128> FixedPrivModDecl;
180129729919SBruno Cardoso Lopes SmallString<128> Canonical(M->Name);
180229729919SBruno Cardoso Lopes Canonical.append("_Private");
180329729919SBruno Cardoso Lopes
180429729919SBruno Cardoso Lopes // Foo.Private -> Foo_Private
180529729919SBruno Cardoso Lopes if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
180629729919SBruno Cardoso Lopes M->Name == ActiveModule->Parent->Name) {
180729729919SBruno Cardoso Lopes Diags.Report(ActiveModule->DefinitionLoc,
180829729919SBruno Cardoso Lopes diag::warn_mmap_mismatched_private_submodule)
180929729919SBruno Cardoso Lopes << FullName;
18105f11e128SBruno Cardoso Lopes
18115f11e128SBruno Cardoso Lopes SourceLocation FixItInitBegin = CurrModuleDeclLoc;
18125f11e128SBruno Cardoso Lopes if (FrameworkLoc.isValid())
18135f11e128SBruno Cardoso Lopes FixItInitBegin = FrameworkLoc;
18145f11e128SBruno Cardoso Lopes if (ExplicitLoc.isValid())
18155f11e128SBruno Cardoso Lopes FixItInitBegin = ExplicitLoc;
18165f11e128SBruno Cardoso Lopes
18175f11e128SBruno Cardoso Lopes if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
18185f11e128SBruno Cardoso Lopes FixedPrivModDecl.append("framework ");
18195f11e128SBruno Cardoso Lopes FixedPrivModDecl.append("module ");
18205f11e128SBruno Cardoso Lopes FixedPrivModDecl.append(Canonical);
18215f11e128SBruno Cardoso Lopes
18225f11e128SBruno Cardoso Lopes GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
18235f11e128SBruno Cardoso Lopes SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
182429729919SBruno Cardoso Lopes continue;
182529729919SBruno Cardoso Lopes }
182629729919SBruno Cardoso Lopes
182729729919SBruno Cardoso Lopes // FooPrivate and whatnots -> Foo_Private
182829729919SBruno Cardoso Lopes if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
182929729919SBruno Cardoso Lopes ActiveModule->Name != Canonical) {
183029729919SBruno Cardoso Lopes Diags.Report(ActiveModule->DefinitionLoc,
183129729919SBruno Cardoso Lopes diag::warn_mmap_mismatched_private_module_name)
183229729919SBruno Cardoso Lopes << ActiveModule->Name;
18337d29486dSBruno Cardoso Lopes GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
18347d29486dSBruno Cardoso Lopes SourceRange(ActiveModule->DefinitionLoc));
183529729919SBruno Cardoso Lopes }
183629729919SBruno Cardoso Lopes }
183729729919SBruno Cardoso Lopes }
183829729919SBruno Cardoso Lopes
18399fc8faf9SAdrian Prantl /// Parse a module declaration.
1840718292f2SDouglas Gregor ///
1841718292f2SDouglas Gregor /// module-declaration:
184297292843SDaniel Jasper /// 'extern' 'module' module-id string-literal
1843a686e1b0SDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1844a686e1b0SDouglas Gregor /// { module-member* }
1845a686e1b0SDouglas Gregor ///
1846718292f2SDouglas Gregor /// module-member:
18471fb5c3a6SDouglas Gregor /// requires-declaration
1848718292f2SDouglas Gregor /// header-declaration
1849e7ab3669SDouglas Gregor /// submodule-declaration
18502b82c2a5SDouglas Gregor /// export-declaration
1851f0b11de2SDouglas Gregor /// export-as-declaration
18526ddfca91SDouglas Gregor /// link-declaration
185373441091SDouglas Gregor ///
185473441091SDouglas Gregor /// submodule-declaration:
185573441091SDouglas Gregor /// module-declaration
185673441091SDouglas Gregor /// inferred-submodule-declaration
parseModuleDecl()1857718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() {
1858755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
185997292843SDaniel Jasper Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
186097292843SDaniel Jasper if (Tok.is(MMToken::ExternKeyword)) {
186197292843SDaniel Jasper parseExternModuleDecl();
186297292843SDaniel Jasper return;
186397292843SDaniel Jasper }
186497292843SDaniel Jasper
1865f2161a70SDouglas Gregor // Parse 'explicit' or 'framework' keyword, if present.
1866e7ab3669SDouglas Gregor SourceLocation ExplicitLoc;
18675f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc;
1868718292f2SDouglas Gregor bool Explicit = false;
1869f2161a70SDouglas Gregor bool Framework = false;
1870755b2055SDouglas Gregor
1871f2161a70SDouglas Gregor // Parse 'explicit' keyword, if present.
1872f2161a70SDouglas Gregor if (Tok.is(MMToken::ExplicitKeyword)) {
1873e7ab3669SDouglas Gregor ExplicitLoc = consumeToken();
1874f2161a70SDouglas Gregor Explicit = true;
1875f2161a70SDouglas Gregor }
1876f2161a70SDouglas Gregor
1877f2161a70SDouglas Gregor // Parse 'framework' keyword, if present.
1878755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) {
18795f11e128SBruno Cardoso Lopes FrameworkLoc = consumeToken();
1880755b2055SDouglas Gregor Framework = true;
1881755b2055SDouglas Gregor }
1882718292f2SDouglas Gregor
1883718292f2SDouglas Gregor // Parse 'module' keyword.
1884718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) {
1885d6343c99SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1886718292f2SDouglas Gregor consumeToken();
1887718292f2SDouglas Gregor HadError = true;
1888718292f2SDouglas Gregor return;
1889718292f2SDouglas Gregor }
18909f6020bcSBruno Cardoso Lopes CurrModuleDeclLoc = consumeToken(); // 'module' keyword
1891718292f2SDouglas Gregor
189273441091SDouglas Gregor // If we have a wildcard for the module name, this is an inferred submodule.
189373441091SDouglas Gregor // Parse it.
189473441091SDouglas Gregor if (Tok.is(MMToken::Star))
18959194a91dSDouglas Gregor return parseInferredModuleDecl(Framework, Explicit);
189673441091SDouglas Gregor
1897718292f2SDouglas Gregor // Parse the module name.
1898e7ab3669SDouglas Gregor ModuleId Id;
1899e7ab3669SDouglas Gregor if (parseModuleId(Id)) {
1900718292f2SDouglas Gregor HadError = true;
1901718292f2SDouglas Gregor return;
1902718292f2SDouglas Gregor }
1903e7ab3669SDouglas Gregor
1904e7ab3669SDouglas Gregor if (ActiveModule) {
1905e7ab3669SDouglas Gregor if (Id.size() > 1) {
1906e7ab3669SDouglas Gregor Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1907e7ab3669SDouglas Gregor << SourceRange(Id.front().second, Id.back().second);
1908e7ab3669SDouglas Gregor
1909e7ab3669SDouglas Gregor HadError = true;
1910e7ab3669SDouglas Gregor return;
1911e7ab3669SDouglas Gregor }
1912e7ab3669SDouglas Gregor } else if (Id.size() == 1 && Explicit) {
1913e7ab3669SDouglas Gregor // Top-level modules can't be explicit.
1914e7ab3669SDouglas Gregor Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1915e7ab3669SDouglas Gregor Explicit = false;
1916e7ab3669SDouglas Gregor ExplicitLoc = SourceLocation();
1917e7ab3669SDouglas Gregor HadError = true;
1918e7ab3669SDouglas Gregor }
1919e7ab3669SDouglas Gregor
1920e7ab3669SDouglas Gregor Module *PreviousActiveModule = ActiveModule;
1921e7ab3669SDouglas Gregor if (Id.size() > 1) {
1922e7ab3669SDouglas Gregor // This module map defines a submodule. Go find the module of which it
1923e7ab3669SDouglas Gregor // is a submodule.
1924d2d442caSCraig Topper ActiveModule = nullptr;
19254b8a9e95SBen Langmuir const Module *TopLevelModule = nullptr;
1926e7ab3669SDouglas Gregor for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1927e7ab3669SDouglas Gregor if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
19284b8a9e95SBen Langmuir if (I == 0)
19294b8a9e95SBen Langmuir TopLevelModule = Next;
1930e7ab3669SDouglas Gregor ActiveModule = Next;
1931e7ab3669SDouglas Gregor continue;
1932e7ab3669SDouglas Gregor }
1933e7ab3669SDouglas Gregor
19348839e278SVolodymyr Sapsai Diags.Report(Id[I].second, diag::err_mmap_missing_parent_module)
19358839e278SVolodymyr Sapsai << Id[I].first << (ActiveModule != nullptr)
19368839e278SVolodymyr Sapsai << (ActiveModule
19378839e278SVolodymyr Sapsai ? ActiveModule->getTopLevelModule()->getFullModuleName()
19388839e278SVolodymyr Sapsai : "");
1939e7ab3669SDouglas Gregor HadError = true;
1940e7ab3669SDouglas Gregor }
19414b8a9e95SBen Langmuir
19428839e278SVolodymyr Sapsai if (TopLevelModule &&
19438839e278SVolodymyr Sapsai ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
19444b8a9e95SBen Langmuir assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
19454b8a9e95SBen Langmuir "submodule defined in same file as 'module *' that allowed its "
19464b8a9e95SBen Langmuir "top-level module");
19474b8a9e95SBen Langmuir Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
19484b8a9e95SBen Langmuir }
1949e7ab3669SDouglas Gregor }
1950e7ab3669SDouglas Gregor
1951e7ab3669SDouglas Gregor StringRef ModuleName = Id.back().first;
1952e7ab3669SDouglas Gregor SourceLocation ModuleNameLoc = Id.back().second;
1953718292f2SDouglas Gregor
1954a686e1b0SDouglas Gregor // Parse the optional attribute list.
19554442605fSBill Wendling Attributes Attrs;
19565d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs))
19575d29dee0SDavide Italiano return;
19585d29dee0SDavide Italiano
1959718292f2SDouglas Gregor // Parse the opening brace.
1960718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) {
1961718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1962718292f2SDouglas Gregor << ModuleName;
1963718292f2SDouglas Gregor HadError = true;
1964718292f2SDouglas Gregor return;
1965718292f2SDouglas Gregor }
1966718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken();
1967718292f2SDouglas Gregor
1968718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined.
19698587dfd9SBruno Cardoso Lopes Module *ShadowingModule = nullptr;
1970eb90e830SDouglas Gregor if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
19714a3751ffSRichard Smith // We might see a (re)definition of a module that we already have a
19724a3751ffSRichard Smith // definition for in two cases:
19734a3751ffSRichard Smith // - If we loaded one definition from an AST file and we've just found a
19744a3751ffSRichard Smith // corresponding definition in a module map file, or
19754a3751ffSRichard Smith bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
19764a3751ffSRichard Smith // - If we're building a (preprocessed) module and we've just loaded the
19774a3751ffSRichard Smith // module map file from which it was created.
19784a3751ffSRichard Smith bool ParsedAsMainInput =
19794a3751ffSRichard Smith Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
19804a3751ffSRichard Smith Map.LangOpts.CurrentModule == ModuleName &&
19814a3751ffSRichard Smith SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
19824a3751ffSRichard Smith SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
19834a3751ffSRichard Smith if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
1984fcc54a3bSDouglas Gregor // Skip the module definition.
1985fcc54a3bSDouglas Gregor skipUntil(MMToken::RBrace);
1986fcc54a3bSDouglas Gregor if (Tok.is(MMToken::RBrace))
1987fcc54a3bSDouglas Gregor consumeToken();
1988fcc54a3bSDouglas Gregor else {
1989fcc54a3bSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1990fcc54a3bSDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1991fcc54a3bSDouglas Gregor HadError = true;
1992fcc54a3bSDouglas Gregor }
1993fcc54a3bSDouglas Gregor return;
1994fcc54a3bSDouglas Gregor }
1995fcc54a3bSDouglas Gregor
1996c192d194SBruno Cardoso Lopes if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
19978587dfd9SBruno Cardoso Lopes ShadowingModule = Existing;
19988587dfd9SBruno Cardoso Lopes } else {
19998587dfd9SBruno Cardoso Lopes // This is not a shawdowed module decl, it is an illegal redefinition.
2000718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
2001718292f2SDouglas Gregor << ModuleName;
2002eb90e830SDouglas Gregor Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
2003718292f2SDouglas Gregor
2004718292f2SDouglas Gregor // Skip the module definition.
2005718292f2SDouglas Gregor skipUntil(MMToken::RBrace);
2006718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace))
2007718292f2SDouglas Gregor consumeToken();
2008718292f2SDouglas Gregor
2009718292f2SDouglas Gregor HadError = true;
2010718292f2SDouglas Gregor return;
2011718292f2SDouglas Gregor }
20128587dfd9SBruno Cardoso Lopes }
2013718292f2SDouglas Gregor
2014718292f2SDouglas Gregor // Start defining this module.
20158587dfd9SBruno Cardoso Lopes if (ShadowingModule) {
20168587dfd9SBruno Cardoso Lopes ActiveModule =
20178587dfd9SBruno Cardoso Lopes Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
20188587dfd9SBruno Cardoso Lopes } else {
2019c192d194SBruno Cardoso Lopes ActiveModule =
2020c192d194SBruno Cardoso Lopes Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
20218587dfd9SBruno Cardoso Lopes .first;
20228587dfd9SBruno Cardoso Lopes }
20238587dfd9SBruno Cardoso Lopes
2024eb90e830SDouglas Gregor ActiveModule->DefinitionLoc = ModuleNameLoc;
2025963c5535SDouglas Gregor if (Attrs.IsSystem || IsSystem)
2026a686e1b0SDouglas Gregor ActiveModule->IsSystem = true;
202777944868SRichard Smith if (Attrs.IsExternC)
202877944868SRichard Smith ActiveModule->IsExternC = true;
2029ed84df00SBruno Cardoso Lopes if (Attrs.NoUndeclaredIncludes ||
2030ed84df00SBruno Cardoso Lopes (!ActiveModule->Parent && ModuleName == "Darwin"))
2031ed84df00SBruno Cardoso Lopes ActiveModule->NoUndeclaredIncludes = true;
20323c1a41adSRichard Smith ActiveModule->Directory = Directory;
2033718292f2SDouglas Gregor
203490b0a1fcSJordan Rose StringRef MapFileName(ModuleMapFile->getName());
203590b0a1fcSJordan Rose if (MapFileName.endswith("module.private.modulemap") ||
203690b0a1fcSJordan Rose MapFileName.endswith("module_private.map")) {
203790b0a1fcSJordan Rose ActiveModule->ModuleMapIsPrivate = true;
203890b0a1fcSJordan Rose }
203929729919SBruno Cardoso Lopes
204029729919SBruno Cardoso Lopes // Private modules named as FooPrivate, Foo.Private or similar are likely a
204129729919SBruno Cardoso Lopes // user error; provide warnings, notes and fixits to direct users to use
204229729919SBruno Cardoso Lopes // Foo_Private instead.
204329729919SBruno Cardoso Lopes SourceLocation StartLoc =
204429729919SBruno Cardoso Lopes SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
204529729919SBruno Cardoso Lopes if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
204629729919SBruno Cardoso Lopes !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
204729729919SBruno Cardoso Lopes StartLoc) &&
204829729919SBruno Cardoso Lopes !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
204929729919SBruno Cardoso Lopes StartLoc) &&
205090b0a1fcSJordan Rose ActiveModule->ModuleMapIsPrivate)
20515f11e128SBruno Cardoso Lopes diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
20524d867640SGraydon Hoare
2053718292f2SDouglas Gregor bool Done = false;
2054718292f2SDouglas Gregor do {
2055718292f2SDouglas Gregor switch (Tok.Kind) {
2056718292f2SDouglas Gregor case MMToken::EndOfFile:
2057718292f2SDouglas Gregor case MMToken::RBrace:
2058718292f2SDouglas Gregor Done = true;
2059718292f2SDouglas Gregor break;
2060718292f2SDouglas Gregor
206135b13eceSDouglas Gregor case MMToken::ConfigMacros:
206235b13eceSDouglas Gregor parseConfigMacros();
206335b13eceSDouglas Gregor break;
206435b13eceSDouglas Gregor
2065fb912657SDouglas Gregor case MMToken::Conflict:
2066fb912657SDouglas Gregor parseConflict();
2067fb912657SDouglas Gregor break;
2068fb912657SDouglas Gregor
2069718292f2SDouglas Gregor case MMToken::ExplicitKeyword:
207097292843SDaniel Jasper case MMToken::ExternKeyword:
2071f2161a70SDouglas Gregor case MMToken::FrameworkKeyword:
2072718292f2SDouglas Gregor case MMToken::ModuleKeyword:
2073718292f2SDouglas Gregor parseModuleDecl();
2074718292f2SDouglas Gregor break;
2075718292f2SDouglas Gregor
20762b82c2a5SDouglas Gregor case MMToken::ExportKeyword:
20772b82c2a5SDouglas Gregor parseExportDecl();
20782b82c2a5SDouglas Gregor break;
20792b82c2a5SDouglas Gregor
2080f0b11de2SDouglas Gregor case MMToken::ExportAsKeyword:
2081f0b11de2SDouglas Gregor parseExportAsDecl();
2082f0b11de2SDouglas Gregor break;
2083f0b11de2SDouglas Gregor
2084ba7f2f71SDaniel Jasper case MMToken::UseKeyword:
2085ba7f2f71SDaniel Jasper parseUseDecl();
2086ba7f2f71SDaniel Jasper break;
2087ba7f2f71SDaniel Jasper
20881fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword:
20891fb5c3a6SDouglas Gregor parseRequiresDecl();
20901fb5c3a6SDouglas Gregor break;
20911fb5c3a6SDouglas Gregor
2092202210b3SRichard Smith case MMToken::TextualKeyword:
2093202210b3SRichard Smith parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
2094306d8920SRichard Smith break;
2095306d8920SRichard Smith
2096524e33e1SDouglas Gregor case MMToken::UmbrellaKeyword: {
2097524e33e1SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken();
2098524e33e1SDouglas Gregor if (Tok.is(MMToken::HeaderKeyword))
2099b53e5483SLawrence Crowl parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
2100524e33e1SDouglas Gregor else
2101524e33e1SDouglas Gregor parseUmbrellaDirDecl(UmbrellaLoc);
2102718292f2SDouglas Gregor break;
2103524e33e1SDouglas Gregor }
2104718292f2SDouglas Gregor
2105202210b3SRichard Smith case MMToken::ExcludeKeyword:
2106202210b3SRichard Smith parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
210759527666SDouglas Gregor break;
210859527666SDouglas Gregor
2109202210b3SRichard Smith case MMToken::PrivateKeyword:
2110202210b3SRichard Smith parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
2111b53e5483SLawrence Crowl break;
2112b53e5483SLawrence Crowl
2113322f633cSDouglas Gregor case MMToken::HeaderKeyword:
2114202210b3SRichard Smith parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
2115718292f2SDouglas Gregor break;
2116718292f2SDouglas Gregor
21176ddfca91SDouglas Gregor case MMToken::LinkKeyword:
21186ddfca91SDouglas Gregor parseLinkDecl();
21196ddfca91SDouglas Gregor break;
21206ddfca91SDouglas Gregor
2121718292f2SDouglas Gregor default:
2122718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
2123718292f2SDouglas Gregor consumeToken();
2124718292f2SDouglas Gregor break;
2125718292f2SDouglas Gregor }
2126718292f2SDouglas Gregor } while (!Done);
2127718292f2SDouglas Gregor
2128718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace))
2129718292f2SDouglas Gregor consumeToken();
2130718292f2SDouglas Gregor else {
2131718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2132718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2133718292f2SDouglas Gregor HadError = true;
2134718292f2SDouglas Gregor }
2135718292f2SDouglas Gregor
213611dfe6feSDouglas Gregor // If the active module is a top-level framework, and there are no link
213711dfe6feSDouglas Gregor // libraries, automatically link against the framework.
213811dfe6feSDouglas Gregor if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
213911dfe6feSDouglas Gregor ActiveModule->LinkLibraries.empty()) {
214011dfe6feSDouglas Gregor inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
214111dfe6feSDouglas Gregor }
214211dfe6feSDouglas Gregor
2143ec8c9752SBen Langmuir // If the module meets all requirements but is still unavailable, mark the
2144ec8c9752SBen Langmuir // whole tree as unavailable to prevent it from building.
2145fc76b4adSRichard Smith if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
2146ec8c9752SBen Langmuir ActiveModule->Parent) {
2147fc76b4adSRichard Smith ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false);
2148ec8c9752SBen Langmuir ActiveModule->getTopLevelModule()->MissingHeaders.append(
2149ec8c9752SBen Langmuir ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
2150ec8c9752SBen Langmuir }
2151ec8c9752SBen Langmuir
2152e7ab3669SDouglas Gregor // We're done parsing this module. Pop back to the previous module.
2153e7ab3669SDouglas Gregor ActiveModule = PreviousActiveModule;
2154718292f2SDouglas Gregor }
2155718292f2SDouglas Gregor
21569fc8faf9SAdrian Prantl /// Parse an extern module declaration.
215797292843SDaniel Jasper ///
215897292843SDaniel Jasper /// extern module-declaration:
215997292843SDaniel Jasper /// 'extern' 'module' module-id string-literal
parseExternModuleDecl()216097292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() {
216197292843SDaniel Jasper assert(Tok.is(MMToken::ExternKeyword));
2162ae6df27eSRichard Smith SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
216397292843SDaniel Jasper
216497292843SDaniel Jasper // Parse 'module' keyword.
216597292843SDaniel Jasper if (!Tok.is(MMToken::ModuleKeyword)) {
216697292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
216797292843SDaniel Jasper consumeToken();
216897292843SDaniel Jasper HadError = true;
216997292843SDaniel Jasper return;
217097292843SDaniel Jasper }
217197292843SDaniel Jasper consumeToken(); // 'module' keyword
217297292843SDaniel Jasper
217397292843SDaniel Jasper // Parse the module name.
217497292843SDaniel Jasper ModuleId Id;
217597292843SDaniel Jasper if (parseModuleId(Id)) {
217697292843SDaniel Jasper HadError = true;
217797292843SDaniel Jasper return;
217897292843SDaniel Jasper }
217997292843SDaniel Jasper
218097292843SDaniel Jasper // Parse the referenced module map file name.
218197292843SDaniel Jasper if (!Tok.is(MMToken::StringLiteral)) {
218297292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
218397292843SDaniel Jasper HadError = true;
218497292843SDaniel Jasper return;
218597292843SDaniel Jasper }
2186adcd0268SBenjamin Kramer std::string FileName = std::string(Tok.getString());
218797292843SDaniel Jasper consumeToken(); // filename
218897292843SDaniel Jasper
218997292843SDaniel Jasper StringRef FileNameRef = FileName;
219097292843SDaniel Jasper SmallString<128> ModuleMapFileName;
219197292843SDaniel Jasper if (llvm::sys::path::is_relative(FileNameRef)) {
219297292843SDaniel Jasper ModuleMapFileName += Directory->getName();
219397292843SDaniel Jasper llvm::sys::path::append(ModuleMapFileName, FileName);
219492e1b62dSYaron Keren FileNameRef = ModuleMapFileName;
219597292843SDaniel Jasper }
21967799ef71SNico Weber if (auto File = SourceMgr.getFileManager().getFile(FileNameRef))
21979acb99e3SRichard Smith Map.parseModuleMapFile(
2198d0e7bdc2SVolodymyr Sapsai *File, IsSystem,
21999acb99e3SRichard Smith Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
22009acb99e3SRichard Smith ? Directory
22017799ef71SNico Weber : (*File)->getDir(),
2202c192d194SBruno Cardoso Lopes FileID(), nullptr, ExternLoc);
220397292843SDaniel Jasper }
220497292843SDaniel Jasper
22057ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M.
22067ff29148SBen Langmuir ///
22077ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system
22087ff29148SBen Langmuir /// module map files:
22097ff29148SBen Langmuir ///
22107ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which
22117ff29148SBen Langmuir /// should really be mapped to 'textual' now that we have this feature. We
22127ff29148SBen Langmuir /// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
22137ff29148SBen Langmuir /// true. Later, this bit will be used to map all the headers inside this
22147ff29148SBen Langmuir /// module to 'textual'.
22157ff29148SBen Langmuir ///
22167ff29148SBen Langmuir /// This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
22177ff29148SBen Langmuir ///
22187ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement
22197ff29148SBen Langmuir /// was never correct and causes issues now that we check it, so drop it.
shouldAddRequirement(Module * M,StringRef Feature,bool & IsRequiresExcludedHack)22207ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature,
22217ff29148SBen Langmuir bool &IsRequiresExcludedHack) {
22228013e81dSBenjamin Kramer if (Feature == "excluded" &&
22238013e81dSBenjamin Kramer (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
22248013e81dSBenjamin Kramer M->fullModuleNameIs({"Tcl", "Private"}))) {
22257ff29148SBen Langmuir IsRequiresExcludedHack = true;
22267ff29148SBen Langmuir return false;
22278013e81dSBenjamin Kramer } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
22287ff29148SBen Langmuir return false;
22297ff29148SBen Langmuir }
22307ff29148SBen Langmuir
22317ff29148SBen Langmuir return true;
22327ff29148SBen Langmuir }
22337ff29148SBen Langmuir
22349fc8faf9SAdrian Prantl /// Parse a requires declaration.
22351fb5c3a6SDouglas Gregor ///
22361fb5c3a6SDouglas Gregor /// requires-declaration:
22371fb5c3a6SDouglas Gregor /// 'requires' feature-list
22381fb5c3a6SDouglas Gregor ///
22391fb5c3a6SDouglas Gregor /// feature-list:
2240a3feee2aSRichard Smith /// feature ',' feature-list
2241a3feee2aSRichard Smith /// feature
2242a3feee2aSRichard Smith ///
2243a3feee2aSRichard Smith /// feature:
2244a3feee2aSRichard Smith /// '!'[opt] identifier
parseRequiresDecl()22451fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() {
22461fb5c3a6SDouglas Gregor assert(Tok.is(MMToken::RequiresKeyword));
22471fb5c3a6SDouglas Gregor
22481fb5c3a6SDouglas Gregor // Parse 'requires' keyword.
22491fb5c3a6SDouglas Gregor consumeToken();
22501fb5c3a6SDouglas Gregor
22511fb5c3a6SDouglas Gregor // Parse the feature-list.
22521fb5c3a6SDouglas Gregor do {
2253a3feee2aSRichard Smith bool RequiredState = true;
2254a3feee2aSRichard Smith if (Tok.is(MMToken::Exclaim)) {
2255a3feee2aSRichard Smith RequiredState = false;
2256a3feee2aSRichard Smith consumeToken();
2257a3feee2aSRichard Smith }
2258a3feee2aSRichard Smith
22591fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Identifier)) {
22601fb5c3a6SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
22611fb5c3a6SDouglas Gregor HadError = true;
22621fb5c3a6SDouglas Gregor return;
22631fb5c3a6SDouglas Gregor }
22641fb5c3a6SDouglas Gregor
22651fb5c3a6SDouglas Gregor // Consume the feature name.
2266adcd0268SBenjamin Kramer std::string Feature = std::string(Tok.getString());
22671fb5c3a6SDouglas Gregor consumeToken();
22681fb5c3a6SDouglas Gregor
22697ff29148SBen Langmuir bool IsRequiresExcludedHack = false;
22707ff29148SBen Langmuir bool ShouldAddRequirement =
22717ff29148SBen Langmuir shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
22727ff29148SBen Langmuir
22737ff29148SBen Langmuir if (IsRequiresExcludedHack)
22747ff29148SBen Langmuir UsesRequiresExcludedHack.insert(ActiveModule);
22757ff29148SBen Langmuir
22767ff29148SBen Langmuir if (ShouldAddRequirement) {
22771fb5c3a6SDouglas Gregor // Add this feature.
22787ff29148SBen Langmuir ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
22797ff29148SBen Langmuir *Map.Target);
22807ff29148SBen Langmuir }
22811fb5c3a6SDouglas Gregor
22821fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Comma))
22831fb5c3a6SDouglas Gregor break;
22841fb5c3a6SDouglas Gregor
22851fb5c3a6SDouglas Gregor // Consume the comma.
22861fb5c3a6SDouglas Gregor consumeToken();
22871fb5c3a6SDouglas Gregor } while (true);
22881fb5c3a6SDouglas Gregor }
22891fb5c3a6SDouglas Gregor
22909fc8faf9SAdrian Prantl /// Parse a header declaration.
2291718292f2SDouglas Gregor ///
2292718292f2SDouglas Gregor /// header-declaration:
2293306d8920SRichard Smith /// 'textual'[opt] 'header' string-literal
2294202210b3SRichard Smith /// 'private' 'textual'[opt] 'header' string-literal
2295202210b3SRichard Smith /// 'exclude' 'header' string-literal
2296202210b3SRichard Smith /// 'umbrella' 'header' string-literal
2297306d8920SRichard Smith ///
2298306d8920SRichard Smith /// FIXME: Support 'private textual header'.
parseHeaderDecl(MMToken::TokenKind LeadingToken,SourceLocation LeadingLoc)2299b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
2300b53e5483SLawrence Crowl SourceLocation LeadingLoc) {
2301202210b3SRichard Smith // We've already consumed the first token.
2302202210b3SRichard Smith ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
2303202210b3SRichard Smith if (LeadingToken == MMToken::PrivateKeyword) {
2304202210b3SRichard Smith Role = ModuleMap::PrivateHeader;
2305202210b3SRichard Smith // 'private' may optionally be followed by 'textual'.
2306202210b3SRichard Smith if (Tok.is(MMToken::TextualKeyword)) {
2307202210b3SRichard Smith LeadingToken = Tok.Kind;
23081871ed3dSBenjamin Kramer consumeToken();
2309202210b3SRichard Smith }
2310202210b3SRichard Smith }
23117ff29148SBen Langmuir
2312202210b3SRichard Smith if (LeadingToken == MMToken::TextualKeyword)
2313202210b3SRichard Smith Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
2314202210b3SRichard Smith
23157ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) {
23167ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for
23177ff29148SBen Langmuir // Module::UsesRequiresExcludedHack).
23187ff29148SBen Langmuir Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
23197ff29148SBen Langmuir }
23207ff29148SBen Langmuir
2321202210b3SRichard Smith if (LeadingToken != MMToken::HeaderKeyword) {
2322202210b3SRichard Smith if (!Tok.is(MMToken::HeaderKeyword)) {
2323202210b3SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2324202210b3SRichard Smith << (LeadingToken == MMToken::PrivateKeyword ? "private" :
2325202210b3SRichard Smith LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
2326202210b3SRichard Smith LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
2327202210b3SRichard Smith return;
2328202210b3SRichard Smith }
2329202210b3SRichard Smith consumeToken();
2330202210b3SRichard Smith }
2331718292f2SDouglas Gregor
2332718292f2SDouglas Gregor // Parse the header name.
2333718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) {
2334718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2335718292f2SDouglas Gregor << "header";
2336718292f2SDouglas Gregor HadError = true;
2337718292f2SDouglas Gregor return;
2338718292f2SDouglas Gregor }
23393c1a41adSRichard Smith Module::UnresolvedHeaderDirective Header;
2340adcd0268SBenjamin Kramer Header.FileName = std::string(Tok.getString());
23410761a8a0SDaniel Jasper Header.FileNameLoc = consumeToken();
23421d60987fSRichard Smith Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
2343040e1266SRichard Smith Header.Kind =
2344040e1266SRichard Smith (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded
2345040e1266SRichard Smith : Map.headerRoleToKind(Role));
2346718292f2SDouglas Gregor
2347524e33e1SDouglas Gregor // Check whether we already have an umbrella.
23481d60987fSRichard Smith if (Header.IsUmbrella && ActiveModule->Umbrella) {
23490761a8a0SDaniel Jasper Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2350524e33e1SDouglas Gregor << ActiveModule->getFullModuleName();
2351322f633cSDouglas Gregor HadError = true;
2352322f633cSDouglas Gregor return;
2353322f633cSDouglas Gregor }
2354322f633cSDouglas Gregor
2355040e1266SRichard Smith // If we were given stat information, parse it so we can skip looking for
2356040e1266SRichard Smith // the file.
2357040e1266SRichard Smith if (Tok.is(MMToken::LBrace)) {
2358040e1266SRichard Smith SourceLocation LBraceLoc = consumeToken();
23593ec6663bSDouglas Gregor
2360040e1266SRichard Smith while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
2361040e1266SRichard Smith enum Attribute { Size, ModTime, Unknown };
2362040e1266SRichard Smith StringRef Str = Tok.getString();
2363040e1266SRichard Smith SourceLocation Loc = consumeToken();
2364040e1266SRichard Smith switch (llvm::StringSwitch<Attribute>(Str)
2365040e1266SRichard Smith .Case("size", Size)
2366040e1266SRichard Smith .Case("mtime", ModTime)
2367040e1266SRichard Smith .Default(Unknown)) {
2368040e1266SRichard Smith case Size:
2369040e1266SRichard Smith if (Header.Size)
2370040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2371040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) {
2372040e1266SRichard Smith Diags.Report(Tok.getLocation(),
2373040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str;
2374040e1266SRichard Smith skipUntil(MMToken::RBrace);
2375040e1266SRichard Smith break;
2376040e1266SRichard Smith }
2377040e1266SRichard Smith Header.Size = Tok.getInteger();
2378040e1266SRichard Smith consumeToken();
2379040e1266SRichard Smith break;
2380040e1266SRichard Smith
2381040e1266SRichard Smith case ModTime:
2382040e1266SRichard Smith if (Header.ModTime)
2383040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2384040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) {
2385040e1266SRichard Smith Diags.Report(Tok.getLocation(),
2386040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str;
2387040e1266SRichard Smith skipUntil(MMToken::RBrace);
2388040e1266SRichard Smith break;
2389040e1266SRichard Smith }
2390040e1266SRichard Smith Header.ModTime = Tok.getInteger();
2391040e1266SRichard Smith consumeToken();
2392040e1266SRichard Smith break;
2393040e1266SRichard Smith
2394040e1266SRichard Smith case Unknown:
2395040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
2396040e1266SRichard Smith skipUntil(MMToken::RBrace);
2397040e1266SRichard Smith break;
2398040e1266SRichard Smith }
23993ec6663bSDouglas Gregor }
24005257fc63SDouglas Gregor
2401040e1266SRichard Smith if (Tok.is(MMToken::RBrace))
2402040e1266SRichard Smith consumeToken();
2403040e1266SRichard Smith else {
2404040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2405040e1266SRichard Smith Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2406322f633cSDouglas Gregor HadError = true;
2407322f633cSDouglas Gregor }
24080101b540SHans Wennborg }
240925d50758SRichard Smith
24109f6020bcSBruno Cardoso Lopes bool NeedsFramework = false;
24119f6020bcSBruno Cardoso Lopes Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
24129f6020bcSBruno Cardoso Lopes
24139f6020bcSBruno Cardoso Lopes if (NeedsFramework && ActiveModule)
24149f6020bcSBruno Cardoso Lopes Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
24159f6020bcSBruno Cardoso Lopes << ActiveModule->getFullModuleName()
24169f6020bcSBruno Cardoso Lopes << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
2417718292f2SDouglas Gregor }
2418718292f2SDouglas Gregor
compareModuleHeaders(const Module::Header * A,const Module::Header * B)241941f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A,
242041f81994SBen Langmuir const Module::Header *B) {
242141f81994SBen Langmuir return A->NameAsWritten.compare(B->NameAsWritten);
242241f81994SBen Langmuir }
242341f81994SBen Langmuir
24249fc8faf9SAdrian Prantl /// Parse an umbrella directory declaration.
2425524e33e1SDouglas Gregor ///
2426524e33e1SDouglas Gregor /// umbrella-dir-declaration:
2427524e33e1SDouglas Gregor /// umbrella string-literal
parseUmbrellaDirDecl(SourceLocation UmbrellaLoc)2428524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
2429524e33e1SDouglas Gregor // Parse the directory name.
2430524e33e1SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) {
2431524e33e1SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2432524e33e1SDouglas Gregor << "umbrella";
2433524e33e1SDouglas Gregor HadError = true;
2434524e33e1SDouglas Gregor return;
2435524e33e1SDouglas Gregor }
2436524e33e1SDouglas Gregor
2437adcd0268SBenjamin Kramer std::string DirName = std::string(Tok.getString());
2438d3676d4bSMichael Spencer std::string DirNameAsWritten = DirName;
2439524e33e1SDouglas Gregor SourceLocation DirNameLoc = consumeToken();
2440524e33e1SDouglas Gregor
2441524e33e1SDouglas Gregor // Check whether we already have an umbrella.
2442524e33e1SDouglas Gregor if (ActiveModule->Umbrella) {
2443524e33e1SDouglas Gregor Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
2444524e33e1SDouglas Gregor << ActiveModule->getFullModuleName();
2445524e33e1SDouglas Gregor HadError = true;
2446524e33e1SDouglas Gregor return;
2447524e33e1SDouglas Gregor }
2448524e33e1SDouglas Gregor
2449524e33e1SDouglas Gregor // Look for this file.
245064d8c781SDuncan P. N. Exon Smith const DirectoryEntry *Dir = nullptr;
24518d323d15SHarlan Haskins if (llvm::sys::path::is_absolute(DirName)) {
245264d8c781SDuncan P. N. Exon Smith if (auto D = SourceMgr.getFileManager().getDirectory(DirName))
24538d323d15SHarlan Haskins Dir = *D;
24548d323d15SHarlan Haskins } else {
24552c1dd271SDylan Noblesmith SmallString<128> PathName;
2456524e33e1SDouglas Gregor PathName = Directory->getName();
2457524e33e1SDouglas Gregor llvm::sys::path::append(PathName, DirName);
245864d8c781SDuncan P. N. Exon Smith if (auto D = SourceMgr.getFileManager().getDirectory(PathName))
24598d323d15SHarlan Haskins Dir = *D;
2460524e33e1SDouglas Gregor }
2461524e33e1SDouglas Gregor
2462524e33e1SDouglas Gregor if (!Dir) {
2463a0320b97SVassil Vassilev Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
2464524e33e1SDouglas Gregor << DirName;
2465524e33e1SDouglas Gregor return;
2466524e33e1SDouglas Gregor }
2467524e33e1SDouglas Gregor
24687ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) {
24697ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for
24707ff29148SBen Langmuir // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
24717ff29148SBen Langmuir // directory is relatively expensive, in practice this only applies to the
24727ff29148SBen Langmuir // uncommonly used Tcl module on Darwin platforms.
24737ff29148SBen Langmuir std::error_code EC;
24747ff29148SBen Langmuir SmallVector<Module::Header, 6> Headers;
2475fc51490bSJonas Devlieghere llvm::vfs::FileSystem &FS =
2476db8a7422SDuncan P. N. Exon Smith SourceMgr.getFileManager().getVirtualFileSystem();
2477fc51490bSJonas Devlieghere for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
24787ff29148SBen Langmuir I != E && !EC; I.increment(EC)) {
247964d8c781SDuncan P. N. Exon Smith if (auto FE = SourceMgr.getFileManager().getFile(I->path())) {
2480d3676d4bSMichael Spencer Module::Header Header = {"", std::string(I->path()), *FE};
24817ff29148SBen Langmuir Headers.push_back(std::move(Header));
24827ff29148SBen Langmuir }
24837ff29148SBen Langmuir }
24847ff29148SBen Langmuir
24857ff29148SBen Langmuir // Sort header paths so that the pcm doesn't depend on iteration order.
248641f81994SBen Langmuir llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
248741f81994SBen Langmuir
24887ff29148SBen Langmuir for (auto &Header : Headers)
24897ff29148SBen Langmuir Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
24907ff29148SBen Langmuir return;
24917ff29148SBen Langmuir }
24927ff29148SBen Langmuir
249364d8c781SDuncan P. N. Exon Smith if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
2494524e33e1SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
2495524e33e1SDouglas Gregor << OwningModule->getFullModuleName();
2496524e33e1SDouglas Gregor HadError = true;
2497524e33e1SDouglas Gregor return;
2498524e33e1SDouglas Gregor }
2499524e33e1SDouglas Gregor
2500524e33e1SDouglas Gregor // Record this umbrella directory.
2501d3676d4bSMichael Spencer Map.setUmbrellaDir(ActiveModule, Dir, DirNameAsWritten, DirName);
2502524e33e1SDouglas Gregor }
2503524e33e1SDouglas Gregor
25049fc8faf9SAdrian Prantl /// Parse a module export declaration.
25052b82c2a5SDouglas Gregor ///
25062b82c2a5SDouglas Gregor /// export-declaration:
25072b82c2a5SDouglas Gregor /// 'export' wildcard-module-id
25082b82c2a5SDouglas Gregor ///
25092b82c2a5SDouglas Gregor /// wildcard-module-id:
25102b82c2a5SDouglas Gregor /// identifier
25112b82c2a5SDouglas Gregor /// '*'
25122b82c2a5SDouglas Gregor /// identifier '.' wildcard-module-id
parseExportDecl()25132b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() {
25142b82c2a5SDouglas Gregor assert(Tok.is(MMToken::ExportKeyword));
25152b82c2a5SDouglas Gregor SourceLocation ExportLoc = consumeToken();
25162b82c2a5SDouglas Gregor
25172b82c2a5SDouglas Gregor // Parse the module-id with an optional wildcard at the end.
25182b82c2a5SDouglas Gregor ModuleId ParsedModuleId;
25192b82c2a5SDouglas Gregor bool Wildcard = false;
25202b82c2a5SDouglas Gregor do {
2521306d8920SRichard Smith // FIXME: Support string-literal module names here.
25222b82c2a5SDouglas Gregor if (Tok.is(MMToken::Identifier)) {
2523adcd0268SBenjamin Kramer ParsedModuleId.push_back(
2524adcd0268SBenjamin Kramer std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
25252b82c2a5SDouglas Gregor consumeToken();
25262b82c2a5SDouglas Gregor
25272b82c2a5SDouglas Gregor if (Tok.is(MMToken::Period)) {
25282b82c2a5SDouglas Gregor consumeToken();
25292b82c2a5SDouglas Gregor continue;
25302b82c2a5SDouglas Gregor }
25312b82c2a5SDouglas Gregor
25322b82c2a5SDouglas Gregor break;
25332b82c2a5SDouglas Gregor }
25342b82c2a5SDouglas Gregor
25352b82c2a5SDouglas Gregor if(Tok.is(MMToken::Star)) {
25362b82c2a5SDouglas Gregor Wildcard = true;
2537f5eedd05SDouglas Gregor consumeToken();
25382b82c2a5SDouglas Gregor break;
25392b82c2a5SDouglas Gregor }
25402b82c2a5SDouglas Gregor
2541ba7f2f71SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
25422b82c2a5SDouglas Gregor HadError = true;
25432b82c2a5SDouglas Gregor return;
25442b82c2a5SDouglas Gregor } while (true);
25452b82c2a5SDouglas Gregor
25462b82c2a5SDouglas Gregor Module::UnresolvedExportDecl Unresolved = {
25472b82c2a5SDouglas Gregor ExportLoc, ParsedModuleId, Wildcard
25482b82c2a5SDouglas Gregor };
25492b82c2a5SDouglas Gregor ActiveModule->UnresolvedExports.push_back(Unresolved);
25502b82c2a5SDouglas Gregor }
25512b82c2a5SDouglas Gregor
25529fc8faf9SAdrian Prantl /// Parse a module export_as declaration.
2553f0b11de2SDouglas Gregor ///
2554f0b11de2SDouglas Gregor /// export-as-declaration:
2555f0b11de2SDouglas Gregor /// 'export_as' identifier
parseExportAsDecl()2556f0b11de2SDouglas Gregor void ModuleMapParser::parseExportAsDecl() {
2557f0b11de2SDouglas Gregor assert(Tok.is(MMToken::ExportAsKeyword));
2558f0b11de2SDouglas Gregor consumeToken();
2559f0b11de2SDouglas Gregor
2560f0b11de2SDouglas Gregor if (!Tok.is(MMToken::Identifier)) {
2561f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
2562f0b11de2SDouglas Gregor HadError = true;
2563f0b11de2SDouglas Gregor return;
2564f0b11de2SDouglas Gregor }
2565f0b11de2SDouglas Gregor
2566f0b11de2SDouglas Gregor if (ActiveModule->Parent) {
2567f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
2568f0b11de2SDouglas Gregor consumeToken();
2569f0b11de2SDouglas Gregor return;
2570f0b11de2SDouglas Gregor }
2571f0b11de2SDouglas Gregor
2572f0b11de2SDouglas Gregor if (!ActiveModule->ExportAsModule.empty()) {
2573f0b11de2SDouglas Gregor if (ActiveModule->ExportAsModule == Tok.getString()) {
2574f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
2575f0b11de2SDouglas Gregor << ActiveModule->Name << Tok.getString();
2576f0b11de2SDouglas Gregor } else {
2577f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
2578f0b11de2SDouglas Gregor << ActiveModule->Name << ActiveModule->ExportAsModule
2579f0b11de2SDouglas Gregor << Tok.getString();
2580f0b11de2SDouglas Gregor }
2581f0b11de2SDouglas Gregor }
2582f0b11de2SDouglas Gregor
2583adcd0268SBenjamin Kramer ActiveModule->ExportAsModule = std::string(Tok.getString());
2584a3b5f71eSBruno Cardoso Lopes Map.addLinkAsDependency(ActiveModule);
2585a3b5f71eSBruno Cardoso Lopes
2586f0b11de2SDouglas Gregor consumeToken();
2587f0b11de2SDouglas Gregor }
2588f0b11de2SDouglas Gregor
25899fc8faf9SAdrian Prantl /// Parse a module use declaration.
2590ba7f2f71SDaniel Jasper ///
25918f4d3ff1SRichard Smith /// use-declaration:
25928f4d3ff1SRichard Smith /// 'use' wildcard-module-id
parseUseDecl()2593ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() {
2594ba7f2f71SDaniel Jasper assert(Tok.is(MMToken::UseKeyword));
25958f4d3ff1SRichard Smith auto KWLoc = consumeToken();
2596ba7f2f71SDaniel Jasper // Parse the module-id.
2597ba7f2f71SDaniel Jasper ModuleId ParsedModuleId;
25983cd34c76SDaniel Jasper parseModuleId(ParsedModuleId);
2599ba7f2f71SDaniel Jasper
26008f4d3ff1SRichard Smith if (ActiveModule->Parent)
26018f4d3ff1SRichard Smith Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
26028f4d3ff1SRichard Smith else
2603ba7f2f71SDaniel Jasper ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
2604ba7f2f71SDaniel Jasper }
2605ba7f2f71SDaniel Jasper
26069fc8faf9SAdrian Prantl /// Parse a link declaration.
26076ddfca91SDouglas Gregor ///
26086ddfca91SDouglas Gregor /// module-declaration:
26096ddfca91SDouglas Gregor /// 'link' 'framework'[opt] string-literal
parseLinkDecl()26106ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() {
26116ddfca91SDouglas Gregor assert(Tok.is(MMToken::LinkKeyword));
26126ddfca91SDouglas Gregor SourceLocation LinkLoc = consumeToken();
26136ddfca91SDouglas Gregor
26146ddfca91SDouglas Gregor // Parse the optional 'framework' keyword.
26156ddfca91SDouglas Gregor bool IsFramework = false;
26166ddfca91SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) {
26176ddfca91SDouglas Gregor consumeToken();
26186ddfca91SDouglas Gregor IsFramework = true;
26196ddfca91SDouglas Gregor }
26206ddfca91SDouglas Gregor
26216ddfca91SDouglas Gregor // Parse the library name
26226ddfca91SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) {
26236ddfca91SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
26246ddfca91SDouglas Gregor << IsFramework << SourceRange(LinkLoc);
26256ddfca91SDouglas Gregor HadError = true;
26266ddfca91SDouglas Gregor return;
26276ddfca91SDouglas Gregor }
26286ddfca91SDouglas Gregor
2629adcd0268SBenjamin Kramer std::string LibraryName = std::string(Tok.getString());
26306ddfca91SDouglas Gregor consumeToken();
26316ddfca91SDouglas Gregor ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
26326ddfca91SDouglas Gregor IsFramework));
26336ddfca91SDouglas Gregor }
26346ddfca91SDouglas Gregor
26359fc8faf9SAdrian Prantl /// Parse a configuration macro declaration.
263635b13eceSDouglas Gregor ///
263735b13eceSDouglas Gregor /// module-declaration:
263835b13eceSDouglas Gregor /// 'config_macros' attributes[opt] config-macro-list?
263935b13eceSDouglas Gregor ///
264035b13eceSDouglas Gregor /// config-macro-list:
264135b13eceSDouglas Gregor /// identifier (',' identifier)?
parseConfigMacros()264235b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() {
264335b13eceSDouglas Gregor assert(Tok.is(MMToken::ConfigMacros));
264435b13eceSDouglas Gregor SourceLocation ConfigMacrosLoc = consumeToken();
264535b13eceSDouglas Gregor
264635b13eceSDouglas Gregor // Only top-level modules can have configuration macros.
264735b13eceSDouglas Gregor if (ActiveModule->Parent) {
264835b13eceSDouglas Gregor Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
264935b13eceSDouglas Gregor }
265035b13eceSDouglas Gregor
265135b13eceSDouglas Gregor // Parse the optional attributes.
265235b13eceSDouglas Gregor Attributes Attrs;
26535d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs))
26545d29dee0SDavide Italiano return;
26555d29dee0SDavide Italiano
265635b13eceSDouglas Gregor if (Attrs.IsExhaustive && !ActiveModule->Parent) {
265735b13eceSDouglas Gregor ActiveModule->ConfigMacrosExhaustive = true;
265835b13eceSDouglas Gregor }
265935b13eceSDouglas Gregor
266035b13eceSDouglas Gregor // If we don't have an identifier, we're done.
2661306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here.
266235b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier))
266335b13eceSDouglas Gregor return;
266435b13eceSDouglas Gregor
266535b13eceSDouglas Gregor // Consume the first identifier.
266635b13eceSDouglas Gregor if (!ActiveModule->Parent) {
266735b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str());
266835b13eceSDouglas Gregor }
266935b13eceSDouglas Gregor consumeToken();
267035b13eceSDouglas Gregor
267135b13eceSDouglas Gregor do {
267235b13eceSDouglas Gregor // If there's a comma, consume it.
267335b13eceSDouglas Gregor if (!Tok.is(MMToken::Comma))
267435b13eceSDouglas Gregor break;
267535b13eceSDouglas Gregor consumeToken();
267635b13eceSDouglas Gregor
267735b13eceSDouglas Gregor // We expect to see a macro name here.
2678306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here.
267935b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) {
268035b13eceSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
268135b13eceSDouglas Gregor break;
268235b13eceSDouglas Gregor }
268335b13eceSDouglas Gregor
268435b13eceSDouglas Gregor // Consume the macro name.
268535b13eceSDouglas Gregor if (!ActiveModule->Parent) {
268635b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str());
268735b13eceSDouglas Gregor }
268835b13eceSDouglas Gregor consumeToken();
268935b13eceSDouglas Gregor } while (true);
269035b13eceSDouglas Gregor }
269135b13eceSDouglas Gregor
26929fc8faf9SAdrian Prantl /// Format a module-id into a string.
formatModuleId(const ModuleId & Id)2693fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) {
2694fb912657SDouglas Gregor std::string result;
2695fb912657SDouglas Gregor {
2696fb912657SDouglas Gregor llvm::raw_string_ostream OS(result);
2697fb912657SDouglas Gregor
2698fb912657SDouglas Gregor for (unsigned I = 0, N = Id.size(); I != N; ++I) {
2699fb912657SDouglas Gregor if (I)
2700fb912657SDouglas Gregor OS << ".";
2701fb912657SDouglas Gregor OS << Id[I].first;
2702fb912657SDouglas Gregor }
2703fb912657SDouglas Gregor }
2704fb912657SDouglas Gregor
2705fb912657SDouglas Gregor return result;
2706fb912657SDouglas Gregor }
2707fb912657SDouglas Gregor
27089fc8faf9SAdrian Prantl /// Parse a conflict declaration.
2709fb912657SDouglas Gregor ///
2710fb912657SDouglas Gregor /// module-declaration:
2711fb912657SDouglas Gregor /// 'conflict' module-id ',' string-literal
parseConflict()2712fb912657SDouglas Gregor void ModuleMapParser::parseConflict() {
2713fb912657SDouglas Gregor assert(Tok.is(MMToken::Conflict));
2714fb912657SDouglas Gregor SourceLocation ConflictLoc = consumeToken();
2715fb912657SDouglas Gregor Module::UnresolvedConflict Conflict;
2716fb912657SDouglas Gregor
2717fb912657SDouglas Gregor // Parse the module-id.
2718fb912657SDouglas Gregor if (parseModuleId(Conflict.Id))
2719fb912657SDouglas Gregor return;
2720fb912657SDouglas Gregor
2721fb912657SDouglas Gregor // Parse the ','.
2722fb912657SDouglas Gregor if (!Tok.is(MMToken::Comma)) {
2723fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
2724fb912657SDouglas Gregor << SourceRange(ConflictLoc);
2725fb912657SDouglas Gregor return;
2726fb912657SDouglas Gregor }
2727fb912657SDouglas Gregor consumeToken();
2728fb912657SDouglas Gregor
2729fb912657SDouglas Gregor // Parse the message.
2730fb912657SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) {
2731fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
2732fb912657SDouglas Gregor << formatModuleId(Conflict.Id);
2733fb912657SDouglas Gregor return;
2734fb912657SDouglas Gregor }
2735fb912657SDouglas Gregor Conflict.Message = Tok.getString().str();
2736fb912657SDouglas Gregor consumeToken();
2737fb912657SDouglas Gregor
2738fb912657SDouglas Gregor // Add this unresolved conflict.
2739fb912657SDouglas Gregor ActiveModule->UnresolvedConflicts.push_back(Conflict);
2740fb912657SDouglas Gregor }
2741fb912657SDouglas Gregor
27429fc8faf9SAdrian Prantl /// Parse an inferred module declaration (wildcard modules).
27439194a91dSDouglas Gregor ///
27449194a91dSDouglas Gregor /// module-declaration:
27459194a91dSDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
27469194a91dSDouglas Gregor /// { inferred-module-member* }
27479194a91dSDouglas Gregor ///
27489194a91dSDouglas Gregor /// inferred-module-member:
27499194a91dSDouglas Gregor /// 'export' '*'
27509194a91dSDouglas Gregor /// 'exclude' identifier
parseInferredModuleDecl(bool Framework,bool Explicit)27519194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
275273441091SDouglas Gregor assert(Tok.is(MMToken::Star));
275373441091SDouglas Gregor SourceLocation StarLoc = consumeToken();
275473441091SDouglas Gregor bool Failed = false;
275573441091SDouglas Gregor
275673441091SDouglas Gregor // Inferred modules must be submodules.
27579194a91dSDouglas Gregor if (!ActiveModule && !Framework) {
275873441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
275973441091SDouglas Gregor Failed = true;
276073441091SDouglas Gregor }
276173441091SDouglas Gregor
27629194a91dSDouglas Gregor if (ActiveModule) {
2763524e33e1SDouglas Gregor // Inferred modules must have umbrella directories.
27644898cde4SBen Langmuir if (!Failed && ActiveModule->IsAvailable &&
27654898cde4SBen Langmuir !ActiveModule->getUmbrellaDir()) {
276673441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
276773441091SDouglas Gregor Failed = true;
276873441091SDouglas Gregor }
276973441091SDouglas Gregor
277073441091SDouglas Gregor // Check for redefinition of an inferred module.
2771dd005f69SDouglas Gregor if (!Failed && ActiveModule->InferSubmodules) {
277273441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2773dd005f69SDouglas Gregor if (ActiveModule->InferredSubmoduleLoc.isValid())
2774dd005f69SDouglas Gregor Diags.Report(ActiveModule->InferredSubmoduleLoc,
277573441091SDouglas Gregor diag::note_mmap_prev_definition);
277673441091SDouglas Gregor Failed = true;
277773441091SDouglas Gregor }
277873441091SDouglas Gregor
27799194a91dSDouglas Gregor // Check for the 'framework' keyword, which is not permitted here.
27809194a91dSDouglas Gregor if (Framework) {
27819194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
27829194a91dSDouglas Gregor Framework = false;
27839194a91dSDouglas Gregor }
27849194a91dSDouglas Gregor } else if (Explicit) {
27859194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
27869194a91dSDouglas Gregor Explicit = false;
27879194a91dSDouglas Gregor }
27889194a91dSDouglas Gregor
278973441091SDouglas Gregor // If there were any problems with this inferred submodule, skip its body.
279073441091SDouglas Gregor if (Failed) {
279173441091SDouglas Gregor if (Tok.is(MMToken::LBrace)) {
279273441091SDouglas Gregor consumeToken();
279373441091SDouglas Gregor skipUntil(MMToken::RBrace);
279473441091SDouglas Gregor if (Tok.is(MMToken::RBrace))
279573441091SDouglas Gregor consumeToken();
279673441091SDouglas Gregor }
279773441091SDouglas Gregor HadError = true;
279873441091SDouglas Gregor return;
279973441091SDouglas Gregor }
280073441091SDouglas Gregor
28019194a91dSDouglas Gregor // Parse optional attributes.
28024442605fSBill Wendling Attributes Attrs;
28035d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs))
28045d29dee0SDavide Italiano return;
28059194a91dSDouglas Gregor
28069194a91dSDouglas Gregor if (ActiveModule) {
280773441091SDouglas Gregor // Note that we have an inferred submodule.
2808dd005f69SDouglas Gregor ActiveModule->InferSubmodules = true;
2809dd005f69SDouglas Gregor ActiveModule->InferredSubmoduleLoc = StarLoc;
2810dd005f69SDouglas Gregor ActiveModule->InferExplicitSubmodules = Explicit;
28119194a91dSDouglas Gregor } else {
28129194a91dSDouglas Gregor // We'll be inferring framework modules for this directory.
28139194a91dSDouglas Gregor Map.InferredDirectories[Directory].InferModules = true;
2814c1d88ea5SBen Langmuir Map.InferredDirectories[Directory].Attrs = Attrs;
2815beee15e7SBen Langmuir Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
2816131daca0SRichard Smith // FIXME: Handle the 'framework' keyword.
28179194a91dSDouglas Gregor }
281873441091SDouglas Gregor
281973441091SDouglas Gregor // Parse the opening brace.
282073441091SDouglas Gregor if (!Tok.is(MMToken::LBrace)) {
282173441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
282273441091SDouglas Gregor HadError = true;
282373441091SDouglas Gregor return;
282473441091SDouglas Gregor }
282573441091SDouglas Gregor SourceLocation LBraceLoc = consumeToken();
282673441091SDouglas Gregor
282773441091SDouglas Gregor // Parse the body of the inferred submodule.
282873441091SDouglas Gregor bool Done = false;
282973441091SDouglas Gregor do {
283073441091SDouglas Gregor switch (Tok.Kind) {
283173441091SDouglas Gregor case MMToken::EndOfFile:
283273441091SDouglas Gregor case MMToken::RBrace:
283373441091SDouglas Gregor Done = true;
283473441091SDouglas Gregor break;
283573441091SDouglas Gregor
2836afd1b1c9SEugene Zelenko case MMToken::ExcludeKeyword:
28379194a91dSDouglas Gregor if (ActiveModule) {
28389194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2839d2d442caSCraig Topper << (ActiveModule != nullptr);
28409194a91dSDouglas Gregor consumeToken();
28419194a91dSDouglas Gregor break;
28429194a91dSDouglas Gregor }
28439194a91dSDouglas Gregor
28449194a91dSDouglas Gregor consumeToken();
2845306d8920SRichard Smith // FIXME: Support string-literal module names here.
28469194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) {
28479194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
28489194a91dSDouglas Gregor break;
28499194a91dSDouglas Gregor }
28509194a91dSDouglas Gregor
2851adcd0268SBenjamin Kramer Map.InferredDirectories[Directory].ExcludedModules.push_back(
2852adcd0268SBenjamin Kramer std::string(Tok.getString()));
28539194a91dSDouglas Gregor consumeToken();
28549194a91dSDouglas Gregor break;
28559194a91dSDouglas Gregor
28569194a91dSDouglas Gregor case MMToken::ExportKeyword:
28579194a91dSDouglas Gregor if (!ActiveModule) {
28589194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2859d2d442caSCraig Topper << (ActiveModule != nullptr);
28609194a91dSDouglas Gregor consumeToken();
28619194a91dSDouglas Gregor break;
28629194a91dSDouglas Gregor }
28639194a91dSDouglas Gregor
286473441091SDouglas Gregor consumeToken();
286573441091SDouglas Gregor if (Tok.is(MMToken::Star))
2866dd005f69SDouglas Gregor ActiveModule->InferExportWildcard = true;
286773441091SDouglas Gregor else
286873441091SDouglas Gregor Diags.Report(Tok.getLocation(),
286973441091SDouglas Gregor diag::err_mmap_expected_export_wildcard);
287073441091SDouglas Gregor consumeToken();
287173441091SDouglas Gregor break;
287273441091SDouglas Gregor
287373441091SDouglas Gregor case MMToken::ExplicitKeyword:
287473441091SDouglas Gregor case MMToken::ModuleKeyword:
287573441091SDouglas Gregor case MMToken::HeaderKeyword:
2876b53e5483SLawrence Crowl case MMToken::PrivateKeyword:
287773441091SDouglas Gregor case MMToken::UmbrellaKeyword:
287873441091SDouglas Gregor default:
28799194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2880d2d442caSCraig Topper << (ActiveModule != nullptr);
288173441091SDouglas Gregor consumeToken();
288273441091SDouglas Gregor break;
288373441091SDouglas Gregor }
288473441091SDouglas Gregor } while (!Done);
288573441091SDouglas Gregor
288673441091SDouglas Gregor if (Tok.is(MMToken::RBrace))
288773441091SDouglas Gregor consumeToken();
288873441091SDouglas Gregor else {
288973441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
289073441091SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
289173441091SDouglas Gregor HadError = true;
289273441091SDouglas Gregor }
289373441091SDouglas Gregor }
289473441091SDouglas Gregor
28959fc8faf9SAdrian Prantl /// Parse optional attributes.
28969194a91dSDouglas Gregor ///
28979194a91dSDouglas Gregor /// attributes:
28989194a91dSDouglas Gregor /// attribute attributes
28999194a91dSDouglas Gregor /// attribute
29009194a91dSDouglas Gregor ///
29019194a91dSDouglas Gregor /// attribute:
29029194a91dSDouglas Gregor /// [ identifier ]
29039194a91dSDouglas Gregor ///
29049194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes.
29059194a91dSDouglas Gregor ///
29069194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise.
parseOptionalAttributes(Attributes & Attrs)29074442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
29089194a91dSDouglas Gregor bool HadError = false;
29099194a91dSDouglas Gregor
29109194a91dSDouglas Gregor while (Tok.is(MMToken::LSquare)) {
29119194a91dSDouglas Gregor // Consume the '['.
29129194a91dSDouglas Gregor SourceLocation LSquareLoc = consumeToken();
29139194a91dSDouglas Gregor
29149194a91dSDouglas Gregor // Check whether we have an attribute name here.
29159194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) {
29169194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
29179194a91dSDouglas Gregor skipUntil(MMToken::RSquare);
29189194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare))
29199194a91dSDouglas Gregor consumeToken();
29209194a91dSDouglas Gregor HadError = true;
29219194a91dSDouglas Gregor }
29229194a91dSDouglas Gregor
29239194a91dSDouglas Gregor // Decode the attribute name.
29249194a91dSDouglas Gregor AttributeKind Attribute
29259194a91dSDouglas Gregor = llvm::StringSwitch<AttributeKind>(Tok.getString())
292635b13eceSDouglas Gregor .Case("exhaustive", AT_exhaustive)
292777944868SRichard Smith .Case("extern_c", AT_extern_c)
2928ed84df00SBruno Cardoso Lopes .Case("no_undeclared_includes", AT_no_undeclared_includes)
29299194a91dSDouglas Gregor .Case("system", AT_system)
29309194a91dSDouglas Gregor .Default(AT_unknown);
29319194a91dSDouglas Gregor switch (Attribute) {
29329194a91dSDouglas Gregor case AT_unknown:
29339194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
29349194a91dSDouglas Gregor << Tok.getString();
29359194a91dSDouglas Gregor break;
29369194a91dSDouglas Gregor
29379194a91dSDouglas Gregor case AT_system:
29389194a91dSDouglas Gregor Attrs.IsSystem = true;
29399194a91dSDouglas Gregor break;
294035b13eceSDouglas Gregor
294177944868SRichard Smith case AT_extern_c:
294277944868SRichard Smith Attrs.IsExternC = true;
294377944868SRichard Smith break;
294477944868SRichard Smith
294535b13eceSDouglas Gregor case AT_exhaustive:
294635b13eceSDouglas Gregor Attrs.IsExhaustive = true;
294735b13eceSDouglas Gregor break;
2948ed84df00SBruno Cardoso Lopes
2949ed84df00SBruno Cardoso Lopes case AT_no_undeclared_includes:
2950ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes = true;
2951ed84df00SBruno Cardoso Lopes break;
29529194a91dSDouglas Gregor }
29539194a91dSDouglas Gregor consumeToken();
29549194a91dSDouglas Gregor
29559194a91dSDouglas Gregor // Consume the ']'.
29569194a91dSDouglas Gregor if (!Tok.is(MMToken::RSquare)) {
29579194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
29589194a91dSDouglas Gregor Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
29599194a91dSDouglas Gregor skipUntil(MMToken::RSquare);
29609194a91dSDouglas Gregor HadError = true;
29619194a91dSDouglas Gregor }
29629194a91dSDouglas Gregor
29639194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare))
29649194a91dSDouglas Gregor consumeToken();
29659194a91dSDouglas Gregor }
29669194a91dSDouglas Gregor
29679194a91dSDouglas Gregor return HadError;
29689194a91dSDouglas Gregor }
29699194a91dSDouglas Gregor
29709fc8faf9SAdrian Prantl /// Parse a module map file.
2971718292f2SDouglas Gregor ///
2972718292f2SDouglas Gregor /// module-map-file:
2973718292f2SDouglas Gregor /// module-declaration*
parseModuleMapFile()2974718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() {
2975718292f2SDouglas Gregor do {
2976718292f2SDouglas Gregor switch (Tok.Kind) {
2977718292f2SDouglas Gregor case MMToken::EndOfFile:
2978718292f2SDouglas Gregor return HadError;
2979718292f2SDouglas Gregor
2980e7ab3669SDouglas Gregor case MMToken::ExplicitKeyword:
298197292843SDaniel Jasper case MMToken::ExternKeyword:
2982718292f2SDouglas Gregor case MMToken::ModuleKeyword:
2983755b2055SDouglas Gregor case MMToken::FrameworkKeyword:
2984718292f2SDouglas Gregor parseModuleDecl();
2985718292f2SDouglas Gregor break;
2986718292f2SDouglas Gregor
29871fb5c3a6SDouglas Gregor case MMToken::Comma:
298835b13eceSDouglas Gregor case MMToken::ConfigMacros:
2989fb912657SDouglas Gregor case MMToken::Conflict:
2990a3feee2aSRichard Smith case MMToken::Exclaim:
299159527666SDouglas Gregor case MMToken::ExcludeKeyword:
29922b82c2a5SDouglas Gregor case MMToken::ExportKeyword:
2993f0b11de2SDouglas Gregor case MMToken::ExportAsKeyword:
2994718292f2SDouglas Gregor case MMToken::HeaderKeyword:
2995718292f2SDouglas Gregor case MMToken::Identifier:
2996718292f2SDouglas Gregor case MMToken::LBrace:
29976ddfca91SDouglas Gregor case MMToken::LinkKeyword:
2998a686e1b0SDouglas Gregor case MMToken::LSquare:
29992b82c2a5SDouglas Gregor case MMToken::Period:
3000b53e5483SLawrence Crowl case MMToken::PrivateKeyword:
3001718292f2SDouglas Gregor case MMToken::RBrace:
3002a686e1b0SDouglas Gregor case MMToken::RSquare:
30031fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword:
30042b82c2a5SDouglas Gregor case MMToken::Star:
3005718292f2SDouglas Gregor case MMToken::StringLiteral:
3006040e1266SRichard Smith case MMToken::IntegerLiteral:
3007b8afebe2SRichard Smith case MMToken::TextualKeyword:
3008718292f2SDouglas Gregor case MMToken::UmbrellaKeyword:
3009ba7f2f71SDaniel Jasper case MMToken::UseKeyword:
3010718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
3011718292f2SDouglas Gregor HadError = true;
3012718292f2SDouglas Gregor consumeToken();
3013718292f2SDouglas Gregor break;
3014718292f2SDouglas Gregor }
3015718292f2SDouglas Gregor } while (true);
3016718292f2SDouglas Gregor }
3017718292f2SDouglas Gregor
parseModuleMapFile(const FileEntry * File,bool IsSystem,const DirectoryEntry * Dir,FileID ID,unsigned * Offset,SourceLocation ExternModuleLoc)30187799ef71SNico Weber bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
3019c192d194SBruno Cardoso Lopes const DirectoryEntry *Dir, FileID ID,
30208128f332SRichard Smith unsigned *Offset,
3021ae6df27eSRichard Smith SourceLocation ExternModuleLoc) {
30228128f332SRichard Smith assert(Target && "Missing target information");
30234ddf2221SDouglas Gregor llvm::DenseMap<const FileEntry *, bool>::iterator Known
30244ddf2221SDouglas Gregor = ParsedModuleMap.find(File);
30254ddf2221SDouglas Gregor if (Known != ParsedModuleMap.end())
30264ddf2221SDouglas Gregor return Known->second;
30274ddf2221SDouglas Gregor
30288128f332SRichard Smith // If the module map file wasn't already entered, do so now.
30298128f332SRichard Smith if (ID.isInvalid()) {
3030f3f84616SRichard Smith auto FileCharacter =
3031f3f84616SRichard Smith IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
30328128f332SRichard Smith ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
30338128f332SRichard Smith }
30348128f332SRichard Smith
30358128f332SRichard Smith assert(Target && "Missing target information");
3036b03ae743SDuncan P. N. Exon Smith llvm::Optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
3037718292f2SDouglas Gregor if (!Buffer)
30384ddf2221SDouglas Gregor return ParsedModuleMap[File] = true;
30398128f332SRichard Smith assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
30408128f332SRichard Smith "invalid buffer offset");
3041718292f2SDouglas Gregor
3042718292f2SDouglas Gregor // Parse this module map file.
30438128f332SRichard Smith Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
30448128f332SRichard Smith Buffer->getBufferStart(),
30458128f332SRichard Smith Buffer->getBufferStart() + (Offset ? *Offset : 0),
30468128f332SRichard Smith Buffer->getBufferEnd());
30472a6edb30SRichard Smith SourceLocation Start = L.getSourceLocation();
3048beee15e7SBen Langmuir ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
3049c192d194SBruno Cardoso Lopes IsSystem);
3050718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile();
30514ddf2221SDouglas Gregor ParsedModuleMap[File] = Result;
30522a6edb30SRichard Smith
30538128f332SRichard Smith if (Offset) {
30548128f332SRichard Smith auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
30558128f332SRichard Smith assert(Loc.first == ID && "stopped in a different file?");
30568128f332SRichard Smith *Offset = Loc.second;
30578128f332SRichard Smith }
30588128f332SRichard Smith
30592a6edb30SRichard Smith // Notify callbacks that we parsed it.
30602a6edb30SRichard Smith for (const auto &Cb : Callbacks)
30612a6edb30SRichard Smith Cb->moduleMapFileRead(Start, *File, IsSystem);
30628587dfd9SBruno Cardoso Lopes
3063718292f2SDouglas Gregor return Result;
3064718292f2SDouglas Gregor }
3065