1e5dd7070Spatrick //===- ModuleMap.cpp - Describe the layout of modules ---------------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This file defines the ModuleMap implementation, which describes the layout
10e5dd7070Spatrick // of a module as it relates to headers.
11e5dd7070Spatrick //
12e5dd7070Spatrick //===----------------------------------------------------------------------===//
13e5dd7070Spatrick
14e5dd7070Spatrick #include "clang/Lex/ModuleMap.h"
15e5dd7070Spatrick #include "clang/Basic/CharInfo.h"
16e5dd7070Spatrick #include "clang/Basic/Diagnostic.h"
17e5dd7070Spatrick #include "clang/Basic/FileManager.h"
18e5dd7070Spatrick #include "clang/Basic/LLVM.h"
19e5dd7070Spatrick #include "clang/Basic/LangOptions.h"
20e5dd7070Spatrick #include "clang/Basic/Module.h"
21e5dd7070Spatrick #include "clang/Basic/SourceLocation.h"
22e5dd7070Spatrick #include "clang/Basic/SourceManager.h"
23e5dd7070Spatrick #include "clang/Basic/TargetInfo.h"
24e5dd7070Spatrick #include "clang/Lex/HeaderSearch.h"
25e5dd7070Spatrick #include "clang/Lex/HeaderSearchOptions.h"
26e5dd7070Spatrick #include "clang/Lex/LexDiagnostic.h"
27e5dd7070Spatrick #include "clang/Lex/Lexer.h"
28e5dd7070Spatrick #include "clang/Lex/LiteralSupport.h"
29e5dd7070Spatrick #include "clang/Lex/Token.h"
30e5dd7070Spatrick #include "llvm/ADT/DenseMap.h"
31e5dd7070Spatrick #include "llvm/ADT/STLExtras.h"
32e5dd7070Spatrick #include "llvm/ADT/SmallPtrSet.h"
33e5dd7070Spatrick #include "llvm/ADT/SmallString.h"
34e5dd7070Spatrick #include "llvm/ADT/SmallVector.h"
35e5dd7070Spatrick #include "llvm/ADT/StringMap.h"
36e5dd7070Spatrick #include "llvm/ADT/StringRef.h"
37e5dd7070Spatrick #include "llvm/ADT/StringSwitch.h"
38e5dd7070Spatrick #include "llvm/Support/Allocator.h"
39e5dd7070Spatrick #include "llvm/Support/Compiler.h"
40e5dd7070Spatrick #include "llvm/Support/ErrorHandling.h"
41e5dd7070Spatrick #include "llvm/Support/MemoryBuffer.h"
42e5dd7070Spatrick #include "llvm/Support/Path.h"
43e5dd7070Spatrick #include "llvm/Support/VirtualFileSystem.h"
44e5dd7070Spatrick #include "llvm/Support/raw_ostream.h"
45e5dd7070Spatrick #include <algorithm>
46e5dd7070Spatrick #include <cassert>
47e5dd7070Spatrick #include <cstdint>
48e5dd7070Spatrick #include <cstring>
49*12c85518Srobert #include <optional>
50e5dd7070Spatrick #include <string>
51e5dd7070Spatrick #include <system_error>
52e5dd7070Spatrick #include <utility>
53e5dd7070Spatrick
54e5dd7070Spatrick using namespace clang;
55e5dd7070Spatrick
anchor()56e5dd7070Spatrick void ModuleMapCallbacks::anchor() {}
57e5dd7070Spatrick
resolveLinkAsDependencies(Module * Mod)58e5dd7070Spatrick void ModuleMap::resolveLinkAsDependencies(Module *Mod) {
59e5dd7070Spatrick auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name);
60e5dd7070Spatrick if (PendingLinkAs != PendingLinkAsModule.end()) {
61e5dd7070Spatrick for (auto &Name : PendingLinkAs->second) {
62e5dd7070Spatrick auto *M = findModule(Name.getKey());
63e5dd7070Spatrick if (M)
64e5dd7070Spatrick M->UseExportAsModuleLinkName = true;
65e5dd7070Spatrick }
66e5dd7070Spatrick }
67e5dd7070Spatrick }
68e5dd7070Spatrick
addLinkAsDependency(Module * Mod)69e5dd7070Spatrick void ModuleMap::addLinkAsDependency(Module *Mod) {
70e5dd7070Spatrick if (findModule(Mod->ExportAsModule))
71e5dd7070Spatrick Mod->UseExportAsModuleLinkName = true;
72e5dd7070Spatrick else
73e5dd7070Spatrick PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name);
74e5dd7070Spatrick }
75e5dd7070Spatrick
headerRoleToKind(ModuleHeaderRole Role)76e5dd7070Spatrick Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
77e5dd7070Spatrick switch ((int)Role) {
78e5dd7070Spatrick case NormalHeader:
79e5dd7070Spatrick return Module::HK_Normal;
80e5dd7070Spatrick case PrivateHeader:
81e5dd7070Spatrick return Module::HK_Private;
82e5dd7070Spatrick case TextualHeader:
83e5dd7070Spatrick return Module::HK_Textual;
84e5dd7070Spatrick case PrivateHeader | TextualHeader:
85e5dd7070Spatrick return Module::HK_PrivateTextual;
86*12c85518Srobert case ExcludedHeader:
87*12c85518Srobert return Module::HK_Excluded;
88e5dd7070Spatrick }
89*12c85518Srobert llvm_unreachable("unknown header role");
90e5dd7070Spatrick }
91e5dd7070Spatrick
92e5dd7070Spatrick ModuleMap::ModuleHeaderRole
headerKindToRole(Module::HeaderKind Kind)93e5dd7070Spatrick ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
94e5dd7070Spatrick switch ((int)Kind) {
95e5dd7070Spatrick case Module::HK_Normal:
96e5dd7070Spatrick return NormalHeader;
97e5dd7070Spatrick case Module::HK_Private:
98e5dd7070Spatrick return PrivateHeader;
99e5dd7070Spatrick case Module::HK_Textual:
100e5dd7070Spatrick return TextualHeader;
101e5dd7070Spatrick case Module::HK_PrivateTextual:
102e5dd7070Spatrick return ModuleHeaderRole(PrivateHeader | TextualHeader);
103e5dd7070Spatrick case Module::HK_Excluded:
104*12c85518Srobert return ExcludedHeader;
105e5dd7070Spatrick }
106e5dd7070Spatrick llvm_unreachable("unknown header kind");
107e5dd7070Spatrick }
108e5dd7070Spatrick
isModular(ModuleHeaderRole Role)109*12c85518Srobert bool ModuleMap::isModular(ModuleHeaderRole Role) {
110*12c85518Srobert return !(Role & (ModuleMap::TextualHeader | ModuleMap::ExcludedHeader));
111*12c85518Srobert }
112*12c85518Srobert
113e5dd7070Spatrick Module::ExportDecl
resolveExport(Module * Mod,const Module::UnresolvedExportDecl & Unresolved,bool Complain) const114e5dd7070Spatrick ModuleMap::resolveExport(Module *Mod,
115e5dd7070Spatrick const Module::UnresolvedExportDecl &Unresolved,
116e5dd7070Spatrick bool Complain) const {
117e5dd7070Spatrick // We may have just a wildcard.
118e5dd7070Spatrick if (Unresolved.Id.empty()) {
119e5dd7070Spatrick assert(Unresolved.Wildcard && "Invalid unresolved export");
120e5dd7070Spatrick return Module::ExportDecl(nullptr, true);
121e5dd7070Spatrick }
122e5dd7070Spatrick
123e5dd7070Spatrick // Resolve the module-id.
124e5dd7070Spatrick Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
125e5dd7070Spatrick if (!Context)
126e5dd7070Spatrick return {};
127e5dd7070Spatrick
128e5dd7070Spatrick return Module::ExportDecl(Context, Unresolved.Wildcard);
129e5dd7070Spatrick }
130e5dd7070Spatrick
resolveModuleId(const ModuleId & Id,Module * Mod,bool Complain) const131e5dd7070Spatrick Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
132e5dd7070Spatrick bool Complain) const {
133e5dd7070Spatrick // Find the starting module.
134e5dd7070Spatrick Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
135e5dd7070Spatrick if (!Context) {
136e5dd7070Spatrick if (Complain)
137e5dd7070Spatrick Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
138e5dd7070Spatrick << Id[0].first << Mod->getFullModuleName();
139e5dd7070Spatrick
140e5dd7070Spatrick return nullptr;
141e5dd7070Spatrick }
142e5dd7070Spatrick
143e5dd7070Spatrick // Dig into the module path.
144e5dd7070Spatrick for (unsigned I = 1, N = Id.size(); I != N; ++I) {
145e5dd7070Spatrick Module *Sub = lookupModuleQualified(Id[I].first, Context);
146e5dd7070Spatrick if (!Sub) {
147e5dd7070Spatrick if (Complain)
148e5dd7070Spatrick Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
149e5dd7070Spatrick << Id[I].first << Context->getFullModuleName()
150e5dd7070Spatrick << SourceRange(Id[0].second, Id[I-1].second);
151e5dd7070Spatrick
152e5dd7070Spatrick return nullptr;
153e5dd7070Spatrick }
154e5dd7070Spatrick
155e5dd7070Spatrick Context = Sub;
156e5dd7070Spatrick }
157e5dd7070Spatrick
158e5dd7070Spatrick return Context;
159e5dd7070Spatrick }
160e5dd7070Spatrick
161e5dd7070Spatrick /// Append to \p Paths the set of paths needed to get to the
162e5dd7070Spatrick /// subframework in which the given module lives.
appendSubframeworkPaths(Module * Mod,SmallVectorImpl<char> & Path)163e5dd7070Spatrick static void appendSubframeworkPaths(Module *Mod,
164e5dd7070Spatrick SmallVectorImpl<char> &Path) {
165e5dd7070Spatrick // Collect the framework names from the given module to the top-level module.
166e5dd7070Spatrick SmallVector<StringRef, 2> Paths;
167e5dd7070Spatrick for (; Mod; Mod = Mod->Parent) {
168e5dd7070Spatrick if (Mod->IsFramework)
169e5dd7070Spatrick Paths.push_back(Mod->Name);
170e5dd7070Spatrick }
171e5dd7070Spatrick
172e5dd7070Spatrick if (Paths.empty())
173e5dd7070Spatrick return;
174e5dd7070Spatrick
175e5dd7070Spatrick // Add Frameworks/Name.framework for each subframework.
176*12c85518Srobert for (StringRef Framework : llvm::drop_begin(llvm::reverse(Paths)))
177*12c85518Srobert llvm::sys::path::append(Path, "Frameworks", Framework + ".framework");
178e5dd7070Spatrick }
179e5dd7070Spatrick
findHeader(Module * M,const Module::UnresolvedHeaderDirective & Header,SmallVectorImpl<char> & RelativePathName,bool & NeedsFramework)180*12c85518Srobert OptionalFileEntryRef ModuleMap::findHeader(
181e5dd7070Spatrick Module *M, const Module::UnresolvedHeaderDirective &Header,
182e5dd7070Spatrick SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) {
183e5dd7070Spatrick // Search for the header file within the module's home directory.
184e5dd7070Spatrick auto *Directory = M->Directory;
185e5dd7070Spatrick SmallString<128> FullPathName(Directory->getName());
186e5dd7070Spatrick
187*12c85518Srobert auto GetFile = [&](StringRef Filename) -> OptionalFileEntryRef {
188a9ac8606Spatrick auto File =
189a9ac8606Spatrick expectedToOptional(SourceMgr.getFileManager().getFileRef(Filename));
190a9ac8606Spatrick if (!File || (Header.Size && File->getSize() != *Header.Size) ||
191a9ac8606Spatrick (Header.ModTime && File->getModificationTime() != *Header.ModTime))
192*12c85518Srobert return std::nullopt;
193e5dd7070Spatrick return *File;
194e5dd7070Spatrick };
195e5dd7070Spatrick
196*12c85518Srobert auto GetFrameworkFile = [&]() -> OptionalFileEntryRef {
197e5dd7070Spatrick unsigned FullPathLength = FullPathName.size();
198e5dd7070Spatrick appendSubframeworkPaths(M, RelativePathName);
199e5dd7070Spatrick unsigned RelativePathLength = RelativePathName.size();
200e5dd7070Spatrick
201e5dd7070Spatrick // Check whether this file is in the public headers.
202e5dd7070Spatrick llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
203e5dd7070Spatrick llvm::sys::path::append(FullPathName, RelativePathName);
204a9ac8606Spatrick if (auto File = GetFile(FullPathName))
205e5dd7070Spatrick return File;
206e5dd7070Spatrick
207e5dd7070Spatrick // Check whether this file is in the private headers.
208e5dd7070Spatrick // Ideally, private modules in the form 'FrameworkName.Private' should
209e5dd7070Spatrick // be defined as 'module FrameworkName.Private', and not as
210e5dd7070Spatrick // 'framework module FrameworkName.Private', since a 'Private.Framework'
211e5dd7070Spatrick // does not usually exist. However, since both are currently widely used
212e5dd7070Spatrick // for private modules, make sure we find the right path in both cases.
213e5dd7070Spatrick if (M->IsFramework && M->Name == "Private")
214e5dd7070Spatrick RelativePathName.clear();
215e5dd7070Spatrick else
216e5dd7070Spatrick RelativePathName.resize(RelativePathLength);
217e5dd7070Spatrick FullPathName.resize(FullPathLength);
218e5dd7070Spatrick llvm::sys::path::append(RelativePathName, "PrivateHeaders",
219e5dd7070Spatrick Header.FileName);
220e5dd7070Spatrick llvm::sys::path::append(FullPathName, RelativePathName);
221e5dd7070Spatrick return GetFile(FullPathName);
222e5dd7070Spatrick };
223e5dd7070Spatrick
224e5dd7070Spatrick if (llvm::sys::path::is_absolute(Header.FileName)) {
225e5dd7070Spatrick RelativePathName.clear();
226e5dd7070Spatrick RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
227e5dd7070Spatrick return GetFile(Header.FileName);
228e5dd7070Spatrick }
229e5dd7070Spatrick
230e5dd7070Spatrick if (M->isPartOfFramework())
231e5dd7070Spatrick return GetFrameworkFile();
232e5dd7070Spatrick
233e5dd7070Spatrick // Lookup for normal headers.
234e5dd7070Spatrick llvm::sys::path::append(RelativePathName, Header.FileName);
235e5dd7070Spatrick llvm::sys::path::append(FullPathName, RelativePathName);
236a9ac8606Spatrick auto NormalHdrFile = GetFile(FullPathName);
237e5dd7070Spatrick
238e5dd7070Spatrick if (!NormalHdrFile && Directory->getName().endswith(".framework")) {
239e5dd7070Spatrick // The lack of 'framework' keyword in a module declaration it's a simple
240e5dd7070Spatrick // mistake we can diagnose when the header exists within the proper
241e5dd7070Spatrick // framework style path.
242e5dd7070Spatrick FullPathName.assign(Directory->getName());
243e5dd7070Spatrick RelativePathName.clear();
244e5dd7070Spatrick if (GetFrameworkFile()) {
245e5dd7070Spatrick Diags.Report(Header.FileNameLoc,
246e5dd7070Spatrick diag::warn_mmap_incomplete_framework_module_declaration)
247e5dd7070Spatrick << Header.FileName << M->getFullModuleName();
248e5dd7070Spatrick NeedsFramework = true;
249e5dd7070Spatrick }
250*12c85518Srobert return std::nullopt;
251e5dd7070Spatrick }
252e5dd7070Spatrick
253e5dd7070Spatrick return NormalHdrFile;
254e5dd7070Spatrick }
255e5dd7070Spatrick
resolveHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header,bool & NeedsFramework)256e5dd7070Spatrick void ModuleMap::resolveHeader(Module *Mod,
257e5dd7070Spatrick const Module::UnresolvedHeaderDirective &Header,
258e5dd7070Spatrick bool &NeedsFramework) {
259e5dd7070Spatrick SmallString<128> RelativePathName;
260*12c85518Srobert if (OptionalFileEntryRef File =
261e5dd7070Spatrick findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
262e5dd7070Spatrick if (Header.IsUmbrella) {
263a9ac8606Spatrick const DirectoryEntry *UmbrellaDir = &File->getDir().getDirEntry();
264e5dd7070Spatrick if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
265e5dd7070Spatrick Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
266e5dd7070Spatrick << UmbrellaMod->getFullModuleName();
267e5dd7070Spatrick else
268e5dd7070Spatrick // Record this umbrella header.
269a9ac8606Spatrick setUmbrellaHeader(Mod, *File, Header.FileName, RelativePathName.str());
270e5dd7070Spatrick } else {
271a9ac8606Spatrick Module::Header H = {Header.FileName, std::string(RelativePathName.str()),
272a9ac8606Spatrick *File};
273e5dd7070Spatrick addHeader(Mod, H, headerKindToRole(Header.Kind));
274e5dd7070Spatrick }
275e5dd7070Spatrick } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
276e5dd7070Spatrick // There's a builtin header but no corresponding on-disk header. Assume
277e5dd7070Spatrick // this was supposed to modularize the builtin header alone.
278e5dd7070Spatrick } else if (Header.Kind == Module::HK_Excluded) {
279e5dd7070Spatrick // Ignore missing excluded header files. They're optional anyway.
280e5dd7070Spatrick } else {
281e5dd7070Spatrick // If we find a module that has a missing header, we mark this module as
282e5dd7070Spatrick // unavailable and store the header directive for displaying diagnostics.
283e5dd7070Spatrick Mod->MissingHeaders.push_back(Header);
284e5dd7070Spatrick // A missing header with stat information doesn't make the module
285e5dd7070Spatrick // unavailable; this keeps our behavior consistent as headers are lazily
286e5dd7070Spatrick // resolved. (Such a module still can't be built though, except from
287e5dd7070Spatrick // preprocessed source.)
288e5dd7070Spatrick if (!Header.Size && !Header.ModTime)
289ec727ea7Spatrick Mod->markUnavailable(/*Unimportable=*/false);
290e5dd7070Spatrick }
291e5dd7070Spatrick }
292e5dd7070Spatrick
resolveAsBuiltinHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header)293e5dd7070Spatrick bool ModuleMap::resolveAsBuiltinHeader(
294e5dd7070Spatrick Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
295e5dd7070Spatrick if (Header.Kind == Module::HK_Excluded ||
296e5dd7070Spatrick llvm::sys::path::is_absolute(Header.FileName) ||
297e5dd7070Spatrick Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
298e5dd7070Spatrick !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
299e5dd7070Spatrick !isBuiltinHeader(Header.FileName))
300e5dd7070Spatrick return false;
301e5dd7070Spatrick
302e5dd7070Spatrick // This is a system module with a top-level header. This header
303e5dd7070Spatrick // may have a counterpart (or replacement) in the set of headers
304e5dd7070Spatrick // supplied by Clang. Find that builtin header.
305e5dd7070Spatrick SmallString<128> Path;
306e5dd7070Spatrick llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
307*12c85518Srobert auto File = SourceMgr.getFileManager().getOptionalFileRef(Path);
308e5dd7070Spatrick if (!File)
309e5dd7070Spatrick return false;
310e5dd7070Spatrick
311e5dd7070Spatrick auto Role = headerKindToRole(Header.Kind);
312a9ac8606Spatrick Module::Header H = {Header.FileName, std::string(Path.str()), *File};
313e5dd7070Spatrick addHeader(Mod, H, Role);
314e5dd7070Spatrick return true;
315e5dd7070Spatrick }
316e5dd7070Spatrick
ModuleMap(SourceManager & SourceMgr,DiagnosticsEngine & Diags,const LangOptions & LangOpts,const TargetInfo * Target,HeaderSearch & HeaderInfo)317e5dd7070Spatrick ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
318e5dd7070Spatrick const LangOptions &LangOpts, const TargetInfo *Target,
319e5dd7070Spatrick HeaderSearch &HeaderInfo)
320e5dd7070Spatrick : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
321e5dd7070Spatrick HeaderInfo(HeaderInfo) {
322e5dd7070Spatrick MMapLangOpts.LineComment = true;
323e5dd7070Spatrick }
324e5dd7070Spatrick
~ModuleMap()325e5dd7070Spatrick ModuleMap::~ModuleMap() {
326e5dd7070Spatrick for (auto &M : Modules)
327e5dd7070Spatrick delete M.getValue();
328e5dd7070Spatrick for (auto *M : ShadowModules)
329e5dd7070Spatrick delete M;
330e5dd7070Spatrick }
331e5dd7070Spatrick
setTarget(const TargetInfo & Target)332e5dd7070Spatrick void ModuleMap::setTarget(const TargetInfo &Target) {
333e5dd7070Spatrick assert((!this->Target || this->Target == &Target) &&
334e5dd7070Spatrick "Improper target override");
335e5dd7070Spatrick this->Target = &Target;
336e5dd7070Spatrick }
337e5dd7070Spatrick
338e5dd7070Spatrick /// "Sanitize" a filename so that it can be used as an identifier.
sanitizeFilenameAsIdentifier(StringRef Name,SmallVectorImpl<char> & Buffer)339e5dd7070Spatrick static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
340e5dd7070Spatrick SmallVectorImpl<char> &Buffer) {
341e5dd7070Spatrick if (Name.empty())
342e5dd7070Spatrick return Name;
343e5dd7070Spatrick
344*12c85518Srobert if (!isValidAsciiIdentifier(Name)) {
345e5dd7070Spatrick // If we don't already have something with the form of an identifier,
346e5dd7070Spatrick // create a buffer with the sanitized name.
347e5dd7070Spatrick Buffer.clear();
348e5dd7070Spatrick if (isDigit(Name[0]))
349e5dd7070Spatrick Buffer.push_back('_');
350e5dd7070Spatrick Buffer.reserve(Buffer.size() + Name.size());
351e5dd7070Spatrick for (unsigned I = 0, N = Name.size(); I != N; ++I) {
352*12c85518Srobert if (isAsciiIdentifierContinue(Name[I]))
353e5dd7070Spatrick Buffer.push_back(Name[I]);
354e5dd7070Spatrick else
355e5dd7070Spatrick Buffer.push_back('_');
356e5dd7070Spatrick }
357e5dd7070Spatrick
358e5dd7070Spatrick Name = StringRef(Buffer.data(), Buffer.size());
359e5dd7070Spatrick }
360e5dd7070Spatrick
361e5dd7070Spatrick while (llvm::StringSwitch<bool>(Name)
362e5dd7070Spatrick #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
363e5dd7070Spatrick #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
364e5dd7070Spatrick #include "clang/Basic/TokenKinds.def"
365e5dd7070Spatrick .Default(false)) {
366e5dd7070Spatrick if (Name.data() != Buffer.data())
367e5dd7070Spatrick Buffer.append(Name.begin(), Name.end());
368e5dd7070Spatrick Buffer.push_back('_');
369e5dd7070Spatrick Name = StringRef(Buffer.data(), Buffer.size());
370e5dd7070Spatrick }
371e5dd7070Spatrick
372e5dd7070Spatrick return Name;
373e5dd7070Spatrick }
374e5dd7070Spatrick
375e5dd7070Spatrick /// Determine whether the given file name is the name of a builtin
376e5dd7070Spatrick /// header, supplied by Clang to replace, override, or augment existing system
377e5dd7070Spatrick /// headers.
isBuiltinHeader(StringRef FileName)378e5dd7070Spatrick bool ModuleMap::isBuiltinHeader(StringRef FileName) {
379e5dd7070Spatrick return llvm::StringSwitch<bool>(FileName)
380e5dd7070Spatrick .Case("float.h", true)
381e5dd7070Spatrick .Case("iso646.h", true)
382e5dd7070Spatrick .Case("limits.h", true)
383e5dd7070Spatrick .Case("stdalign.h", true)
384e5dd7070Spatrick .Case("stdarg.h", true)
385e5dd7070Spatrick .Case("stdatomic.h", true)
386e5dd7070Spatrick .Case("stdbool.h", true)
387e5dd7070Spatrick .Case("stddef.h", true)
388e5dd7070Spatrick .Case("stdint.h", true)
389e5dd7070Spatrick .Case("tgmath.h", true)
390e5dd7070Spatrick .Case("unwind.h", true)
391e5dd7070Spatrick .Default(false);
392e5dd7070Spatrick }
393e5dd7070Spatrick
isBuiltinHeader(const FileEntry * File)394ec727ea7Spatrick bool ModuleMap::isBuiltinHeader(const FileEntry *File) {
395ec727ea7Spatrick return File->getDir() == BuiltinIncludeDir &&
396ec727ea7Spatrick ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()));
397ec727ea7Spatrick }
398ec727ea7Spatrick
399e5dd7070Spatrick ModuleMap::HeadersMap::iterator
findKnownHeader(const FileEntry * File)400e5dd7070Spatrick ModuleMap::findKnownHeader(const FileEntry *File) {
401e5dd7070Spatrick resolveHeaderDirectives(File);
402e5dd7070Spatrick HeadersMap::iterator Known = Headers.find(File);
403e5dd7070Spatrick if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
404ec727ea7Spatrick Known == Headers.end() && ModuleMap::isBuiltinHeader(File)) {
405e5dd7070Spatrick HeaderInfo.loadTopLevelSystemModules();
406e5dd7070Spatrick return Headers.find(File);
407e5dd7070Spatrick }
408e5dd7070Spatrick return Known;
409e5dd7070Spatrick }
410e5dd7070Spatrick
411e5dd7070Spatrick ModuleMap::KnownHeader
findHeaderInUmbrellaDirs(const FileEntry * File,SmallVectorImpl<const DirectoryEntry * > & IntermediateDirs)412e5dd7070Spatrick ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
413e5dd7070Spatrick SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
414e5dd7070Spatrick if (UmbrellaDirs.empty())
415e5dd7070Spatrick return {};
416e5dd7070Spatrick
417e5dd7070Spatrick const DirectoryEntry *Dir = File->getDir();
418e5dd7070Spatrick assert(Dir && "file in no directory");
419e5dd7070Spatrick
420e5dd7070Spatrick // Note: as an egregious but useful hack we use the real path here, because
421e5dd7070Spatrick // frameworks moving from top-level frameworks to embedded frameworks tend
422e5dd7070Spatrick // to be symlinked from the top-level location to the embedded location,
423e5dd7070Spatrick // and we need to resolve lookups as if we had found the embedded location.
424e5dd7070Spatrick StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
425e5dd7070Spatrick
426e5dd7070Spatrick // Keep walking up the directory hierarchy, looking for a directory with
427e5dd7070Spatrick // an umbrella header.
428e5dd7070Spatrick do {
429e5dd7070Spatrick auto KnownDir = UmbrellaDirs.find(Dir);
430e5dd7070Spatrick if (KnownDir != UmbrellaDirs.end())
431e5dd7070Spatrick return KnownHeader(KnownDir->second, NormalHeader);
432e5dd7070Spatrick
433e5dd7070Spatrick IntermediateDirs.push_back(Dir);
434e5dd7070Spatrick
435e5dd7070Spatrick // Retrieve our parent path.
436e5dd7070Spatrick DirName = llvm::sys::path::parent_path(DirName);
437e5dd7070Spatrick if (DirName.empty())
438e5dd7070Spatrick break;
439e5dd7070Spatrick
440e5dd7070Spatrick // Resolve the parent path to a directory entry.
441e5dd7070Spatrick if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName))
442e5dd7070Spatrick Dir = *DirEntry;
443e5dd7070Spatrick else
444e5dd7070Spatrick Dir = nullptr;
445e5dd7070Spatrick } while (Dir);
446e5dd7070Spatrick return {};
447e5dd7070Spatrick }
448e5dd7070Spatrick
violatesPrivateInclude(Module * RequestingModule,const FileEntry * IncFileEnt,ModuleMap::KnownHeader Header)449e5dd7070Spatrick static bool violatesPrivateInclude(Module *RequestingModule,
450e5dd7070Spatrick const FileEntry *IncFileEnt,
451e5dd7070Spatrick ModuleMap::KnownHeader Header) {
452e5dd7070Spatrick #ifndef NDEBUG
453e5dd7070Spatrick if (Header.getRole() & ModuleMap::PrivateHeader) {
454e5dd7070Spatrick // Check for consistency between the module header role
455e5dd7070Spatrick // as obtained from the lookup and as obtained from the module.
456e5dd7070Spatrick // This check is not cheap, so enable it only for debugging.
457e5dd7070Spatrick bool IsPrivate = false;
458e5dd7070Spatrick SmallVectorImpl<Module::Header> *HeaderList[] = {
459e5dd7070Spatrick &Header.getModule()->Headers[Module::HK_Private],
460e5dd7070Spatrick &Header.getModule()->Headers[Module::HK_PrivateTextual]};
461e5dd7070Spatrick for (auto *Hs : HeaderList)
462*12c85518Srobert IsPrivate |= llvm::any_of(
463*12c85518Srobert *Hs, [&](const Module::Header &H) { return H.Entry == IncFileEnt; });
464e5dd7070Spatrick assert(IsPrivate && "inconsistent headers and roles");
465e5dd7070Spatrick }
466e5dd7070Spatrick #endif
467e5dd7070Spatrick return !Header.isAccessibleFrom(RequestingModule);
468e5dd7070Spatrick }
469e5dd7070Spatrick
getTopLevelOrNull(Module * M)470e5dd7070Spatrick static Module *getTopLevelOrNull(Module *M) {
471e5dd7070Spatrick return M ? M->getTopLevelModule() : nullptr;
472e5dd7070Spatrick }
473e5dd7070Spatrick
diagnoseHeaderInclusion(Module * RequestingModule,bool RequestingModuleIsModuleInterface,SourceLocation FilenameLoc,StringRef Filename,FileEntryRef File)474e5dd7070Spatrick void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
475e5dd7070Spatrick bool RequestingModuleIsModuleInterface,
476e5dd7070Spatrick SourceLocation FilenameLoc,
477*12c85518Srobert StringRef Filename, FileEntryRef File) {
478e5dd7070Spatrick // No errors for indirect modules. This may be a bit of a problem for modules
479e5dd7070Spatrick // with no source files.
480e5dd7070Spatrick if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
481e5dd7070Spatrick return;
482e5dd7070Spatrick
483e5dd7070Spatrick if (RequestingModule) {
484e5dd7070Spatrick resolveUses(RequestingModule, /*Complain=*/false);
485*12c85518Srobert resolveHeaderDirectives(RequestingModule, /*File=*/std::nullopt);
486e5dd7070Spatrick }
487e5dd7070Spatrick
488e5dd7070Spatrick bool Excluded = false;
489e5dd7070Spatrick Module *Private = nullptr;
490e5dd7070Spatrick Module *NotUsed = nullptr;
491e5dd7070Spatrick
492e5dd7070Spatrick HeadersMap::iterator Known = findKnownHeader(File);
493e5dd7070Spatrick if (Known != Headers.end()) {
494e5dd7070Spatrick for (const KnownHeader &Header : Known->second) {
495*12c85518Srobert // Excluded headers don't really belong to a module.
496*12c85518Srobert if (Header.getRole() == ModuleMap::ExcludedHeader) {
497*12c85518Srobert Excluded = true;
498*12c85518Srobert continue;
499*12c85518Srobert }
500*12c85518Srobert
501e5dd7070Spatrick // Remember private headers for later printing of a diagnostic.
502e5dd7070Spatrick if (violatesPrivateInclude(RequestingModule, File, Header)) {
503e5dd7070Spatrick Private = Header.getModule();
504e5dd7070Spatrick continue;
505e5dd7070Spatrick }
506e5dd7070Spatrick
507e5dd7070Spatrick // If uses need to be specified explicitly, we are only allowed to return
508e5dd7070Spatrick // modules that are explicitly used by the requesting module.
509e5dd7070Spatrick if (RequestingModule && LangOpts.ModulesDeclUse &&
510e5dd7070Spatrick !RequestingModule->directlyUses(Header.getModule())) {
511e5dd7070Spatrick NotUsed = Header.getModule();
512e5dd7070Spatrick continue;
513e5dd7070Spatrick }
514e5dd7070Spatrick
515e5dd7070Spatrick // We have found a module that we can happily use.
516e5dd7070Spatrick return;
517e5dd7070Spatrick }
518e5dd7070Spatrick
519e5dd7070Spatrick Excluded = true;
520e5dd7070Spatrick }
521e5dd7070Spatrick
522e5dd7070Spatrick // We have found a header, but it is private.
523e5dd7070Spatrick if (Private) {
524e5dd7070Spatrick Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
525e5dd7070Spatrick << Filename;
526e5dd7070Spatrick return;
527e5dd7070Spatrick }
528e5dd7070Spatrick
529e5dd7070Spatrick // We have found a module, but we don't use it.
530e5dd7070Spatrick if (NotUsed) {
531e5dd7070Spatrick Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
532e5dd7070Spatrick << RequestingModule->getTopLevelModule()->Name << Filename;
533e5dd7070Spatrick return;
534e5dd7070Spatrick }
535e5dd7070Spatrick
536e5dd7070Spatrick if (Excluded || isHeaderInUmbrellaDirs(File))
537e5dd7070Spatrick return;
538e5dd7070Spatrick
539e5dd7070Spatrick // At this point, only non-modular includes remain.
540e5dd7070Spatrick
541e5dd7070Spatrick if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
542e5dd7070Spatrick Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
543e5dd7070Spatrick << RequestingModule->getTopLevelModule()->Name << Filename;
544e5dd7070Spatrick } else if (RequestingModule && RequestingModuleIsModuleInterface &&
545e5dd7070Spatrick LangOpts.isCompilingModule()) {
546e5dd7070Spatrick // Do not diagnose when we are not compiling a module.
547e5dd7070Spatrick diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
548e5dd7070Spatrick diag::warn_non_modular_include_in_framework_module :
549e5dd7070Spatrick diag::warn_non_modular_include_in_module;
550e5dd7070Spatrick Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
551*12c85518Srobert << File.getName();
552e5dd7070Spatrick }
553e5dd7070Spatrick }
554e5dd7070Spatrick
isBetterKnownHeader(const ModuleMap::KnownHeader & New,const ModuleMap::KnownHeader & Old)555e5dd7070Spatrick static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
556e5dd7070Spatrick const ModuleMap::KnownHeader &Old) {
557e5dd7070Spatrick // Prefer available modules.
558ec727ea7Spatrick // FIXME: Considering whether the module is available rather than merely
559ec727ea7Spatrick // importable is non-hermetic and can result in surprising behavior for
560ec727ea7Spatrick // prebuilt modules. Consider only checking for importability here.
561e5dd7070Spatrick if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
562e5dd7070Spatrick return true;
563e5dd7070Spatrick
564e5dd7070Spatrick // Prefer a public header over a private header.
565e5dd7070Spatrick if ((New.getRole() & ModuleMap::PrivateHeader) !=
566e5dd7070Spatrick (Old.getRole() & ModuleMap::PrivateHeader))
567e5dd7070Spatrick return !(New.getRole() & ModuleMap::PrivateHeader);
568e5dd7070Spatrick
569e5dd7070Spatrick // Prefer a non-textual header over a textual header.
570e5dd7070Spatrick if ((New.getRole() & ModuleMap::TextualHeader) !=
571e5dd7070Spatrick (Old.getRole() & ModuleMap::TextualHeader))
572e5dd7070Spatrick return !(New.getRole() & ModuleMap::TextualHeader);
573e5dd7070Spatrick
574*12c85518Srobert // Prefer a non-excluded header over an excluded header.
575*12c85518Srobert if ((New.getRole() == ModuleMap::ExcludedHeader) !=
576*12c85518Srobert (Old.getRole() == ModuleMap::ExcludedHeader))
577*12c85518Srobert return New.getRole() != ModuleMap::ExcludedHeader;
578*12c85518Srobert
579e5dd7070Spatrick // Don't have a reason to choose between these. Just keep the first one.
580e5dd7070Spatrick return false;
581e5dd7070Spatrick }
582e5dd7070Spatrick
findModuleForHeader(const FileEntry * File,bool AllowTextual,bool AllowExcluded)583e5dd7070Spatrick ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
584*12c85518Srobert bool AllowTextual,
585*12c85518Srobert bool AllowExcluded) {
586e5dd7070Spatrick auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
587e5dd7070Spatrick if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
588e5dd7070Spatrick return {};
589e5dd7070Spatrick return R;
590e5dd7070Spatrick };
591e5dd7070Spatrick
592e5dd7070Spatrick HeadersMap::iterator Known = findKnownHeader(File);
593e5dd7070Spatrick if (Known != Headers.end()) {
594e5dd7070Spatrick ModuleMap::KnownHeader Result;
595e5dd7070Spatrick // Iterate over all modules that 'File' is part of to find the best fit.
596e5dd7070Spatrick for (KnownHeader &H : Known->second) {
597*12c85518Srobert // Cannot use a module if the header is excluded in it.
598*12c85518Srobert if (!AllowExcluded && H.getRole() == ModuleMap::ExcludedHeader)
599*12c85518Srobert continue;
600e5dd7070Spatrick // Prefer a header from the source module over all others.
601e5dd7070Spatrick if (H.getModule()->getTopLevelModule() == SourceModule)
602e5dd7070Spatrick return MakeResult(H);
603e5dd7070Spatrick if (!Result || isBetterKnownHeader(H, Result))
604e5dd7070Spatrick Result = H;
605e5dd7070Spatrick }
606e5dd7070Spatrick return MakeResult(Result);
607e5dd7070Spatrick }
608e5dd7070Spatrick
609e5dd7070Spatrick return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
610e5dd7070Spatrick }
611e5dd7070Spatrick
612e5dd7070Spatrick ModuleMap::KnownHeader
findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry * File)613e5dd7070Spatrick ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
614e5dd7070Spatrick assert(!Headers.count(File) && "already have a module for this header");
615e5dd7070Spatrick
616e5dd7070Spatrick SmallVector<const DirectoryEntry *, 2> SkippedDirs;
617e5dd7070Spatrick KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
618e5dd7070Spatrick if (H) {
619e5dd7070Spatrick Module *Result = H.getModule();
620e5dd7070Spatrick
621e5dd7070Spatrick // Search up the module stack until we find a module with an umbrella
622e5dd7070Spatrick // directory.
623e5dd7070Spatrick Module *UmbrellaModule = Result;
624e5dd7070Spatrick while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
625e5dd7070Spatrick UmbrellaModule = UmbrellaModule->Parent;
626e5dd7070Spatrick
627e5dd7070Spatrick if (UmbrellaModule->InferSubmodules) {
628*12c85518Srobert OptionalFileEntryRefDegradesToFileEntryPtr UmbrellaModuleMap =
629e5dd7070Spatrick getModuleMapFileForUniquing(UmbrellaModule);
630e5dd7070Spatrick
631e5dd7070Spatrick // Infer submodules for each of the directories we found between
632e5dd7070Spatrick // the directory of the umbrella header and the directory where
633e5dd7070Spatrick // the actual header is located.
634e5dd7070Spatrick bool Explicit = UmbrellaModule->InferExplicitSubmodules;
635e5dd7070Spatrick
636*12c85518Srobert for (const DirectoryEntry *SkippedDir : llvm::reverse(SkippedDirs)) {
637e5dd7070Spatrick // Find or create the module that corresponds to this directory name.
638e5dd7070Spatrick SmallString<32> NameBuf;
639e5dd7070Spatrick StringRef Name = sanitizeFilenameAsIdentifier(
640*12c85518Srobert llvm::sys::path::stem(SkippedDir->getName()), NameBuf);
641e5dd7070Spatrick Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
642e5dd7070Spatrick Explicit).first;
643e5dd7070Spatrick InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
644e5dd7070Spatrick Result->IsInferred = true;
645e5dd7070Spatrick
646e5dd7070Spatrick // Associate the module and the directory.
647*12c85518Srobert UmbrellaDirs[SkippedDir] = Result;
648e5dd7070Spatrick
649e5dd7070Spatrick // If inferred submodules export everything they import, add a
650e5dd7070Spatrick // wildcard to the set of exports.
651e5dd7070Spatrick if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
652e5dd7070Spatrick Result->Exports.push_back(Module::ExportDecl(nullptr, true));
653e5dd7070Spatrick }
654e5dd7070Spatrick
655e5dd7070Spatrick // Infer a submodule with the same name as this header file.
656e5dd7070Spatrick SmallString<32> NameBuf;
657e5dd7070Spatrick StringRef Name = sanitizeFilenameAsIdentifier(
658e5dd7070Spatrick llvm::sys::path::stem(File->getName()), NameBuf);
659e5dd7070Spatrick Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
660e5dd7070Spatrick Explicit).first;
661e5dd7070Spatrick InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
662e5dd7070Spatrick Result->IsInferred = true;
663e5dd7070Spatrick Result->addTopHeader(File);
664e5dd7070Spatrick
665e5dd7070Spatrick // If inferred submodules export everything they import, add a
666e5dd7070Spatrick // wildcard to the set of exports.
667e5dd7070Spatrick if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
668e5dd7070Spatrick Result->Exports.push_back(Module::ExportDecl(nullptr, true));
669e5dd7070Spatrick } else {
670e5dd7070Spatrick // Record each of the directories we stepped through as being part of
671e5dd7070Spatrick // the module we found, since the umbrella header covers them all.
672e5dd7070Spatrick for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
673e5dd7070Spatrick UmbrellaDirs[SkippedDirs[I]] = Result;
674e5dd7070Spatrick }
675e5dd7070Spatrick
676e5dd7070Spatrick KnownHeader Header(Result, NormalHeader);
677e5dd7070Spatrick Headers[File].push_back(Header);
678e5dd7070Spatrick return Header;
679e5dd7070Spatrick }
680e5dd7070Spatrick
681e5dd7070Spatrick return {};
682e5dd7070Spatrick }
683e5dd7070Spatrick
684e5dd7070Spatrick ArrayRef<ModuleMap::KnownHeader>
findAllModulesForHeader(const FileEntry * File)685ec727ea7Spatrick ModuleMap::findAllModulesForHeader(const FileEntry *File) {
686ec727ea7Spatrick HeadersMap::iterator Known = findKnownHeader(File);
687ec727ea7Spatrick if (Known != Headers.end())
688ec727ea7Spatrick return Known->second;
689ec727ea7Spatrick
690ec727ea7Spatrick if (findOrCreateModuleForHeaderInUmbrellaDir(File))
691ec727ea7Spatrick return Headers.find(File)->second;
692ec727ea7Spatrick
693*12c85518Srobert return std::nullopt;
694ec727ea7Spatrick }
695ec727ea7Spatrick
696ec727ea7Spatrick ArrayRef<ModuleMap::KnownHeader>
findResolvedModulesForHeader(const FileEntry * File) const697ec727ea7Spatrick ModuleMap::findResolvedModulesForHeader(const FileEntry *File) const {
698ec727ea7Spatrick // FIXME: Is this necessary?
699e5dd7070Spatrick resolveHeaderDirectives(File);
700e5dd7070Spatrick auto It = Headers.find(File);
701e5dd7070Spatrick if (It == Headers.end())
702*12c85518Srobert return std::nullopt;
703e5dd7070Spatrick return It->second;
704e5dd7070Spatrick }
705e5dd7070Spatrick
isHeaderInUnavailableModule(const FileEntry * Header) const706e5dd7070Spatrick bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
707e5dd7070Spatrick return isHeaderUnavailableInModule(Header, nullptr);
708e5dd7070Spatrick }
709e5dd7070Spatrick
710e5dd7070Spatrick bool
isHeaderUnavailableInModule(const FileEntry * Header,const Module * RequestingModule) const711e5dd7070Spatrick ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
712e5dd7070Spatrick const Module *RequestingModule) const {
713e5dd7070Spatrick resolveHeaderDirectives(Header);
714e5dd7070Spatrick HeadersMap::const_iterator Known = Headers.find(Header);
715e5dd7070Spatrick if (Known != Headers.end()) {
716e5dd7070Spatrick for (SmallVectorImpl<KnownHeader>::const_iterator
717e5dd7070Spatrick I = Known->second.begin(),
718e5dd7070Spatrick E = Known->second.end();
719e5dd7070Spatrick I != E; ++I) {
720e5dd7070Spatrick
721*12c85518Srobert if (I->getRole() == ModuleMap::ExcludedHeader)
722*12c85518Srobert continue;
723*12c85518Srobert
724e5dd7070Spatrick if (I->isAvailable() &&
725e5dd7070Spatrick (!RequestingModule ||
726e5dd7070Spatrick I->getModule()->isSubModuleOf(RequestingModule))) {
727e5dd7070Spatrick // When no requesting module is available, the caller is looking if a
728e5dd7070Spatrick // header is part a module by only looking into the module map. This is
729e5dd7070Spatrick // done by warn_uncovered_module_header checks; don't consider textual
730e5dd7070Spatrick // headers part of it in this mode, otherwise we get misleading warnings
731e5dd7070Spatrick // that a umbrella header is not including a textual header.
732e5dd7070Spatrick if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
733e5dd7070Spatrick continue;
734e5dd7070Spatrick return false;
735e5dd7070Spatrick }
736e5dd7070Spatrick }
737e5dd7070Spatrick return true;
738e5dd7070Spatrick }
739e5dd7070Spatrick
740e5dd7070Spatrick const DirectoryEntry *Dir = Header->getDir();
741e5dd7070Spatrick SmallVector<const DirectoryEntry *, 2> SkippedDirs;
742e5dd7070Spatrick StringRef DirName = Dir->getName();
743e5dd7070Spatrick
744e5dd7070Spatrick auto IsUnavailable = [&](const Module *M) {
745e5dd7070Spatrick return !M->isAvailable() && (!RequestingModule ||
746e5dd7070Spatrick M->isSubModuleOf(RequestingModule));
747e5dd7070Spatrick };
748e5dd7070Spatrick
749e5dd7070Spatrick // Keep walking up the directory hierarchy, looking for a directory with
750e5dd7070Spatrick // an umbrella header.
751e5dd7070Spatrick do {
752e5dd7070Spatrick llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
753e5dd7070Spatrick = UmbrellaDirs.find(Dir);
754e5dd7070Spatrick if (KnownDir != UmbrellaDirs.end()) {
755e5dd7070Spatrick Module *Found = KnownDir->second;
756e5dd7070Spatrick if (IsUnavailable(Found))
757e5dd7070Spatrick return true;
758e5dd7070Spatrick
759e5dd7070Spatrick // Search up the module stack until we find a module with an umbrella
760e5dd7070Spatrick // directory.
761e5dd7070Spatrick Module *UmbrellaModule = Found;
762e5dd7070Spatrick while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
763e5dd7070Spatrick UmbrellaModule = UmbrellaModule->Parent;
764e5dd7070Spatrick
765e5dd7070Spatrick if (UmbrellaModule->InferSubmodules) {
766*12c85518Srobert for (const DirectoryEntry *SkippedDir : llvm::reverse(SkippedDirs)) {
767e5dd7070Spatrick // Find or create the module that corresponds to this directory name.
768e5dd7070Spatrick SmallString<32> NameBuf;
769e5dd7070Spatrick StringRef Name = sanitizeFilenameAsIdentifier(
770*12c85518Srobert llvm::sys::path::stem(SkippedDir->getName()), NameBuf);
771e5dd7070Spatrick Found = lookupModuleQualified(Name, Found);
772e5dd7070Spatrick if (!Found)
773e5dd7070Spatrick return false;
774e5dd7070Spatrick if (IsUnavailable(Found))
775e5dd7070Spatrick return true;
776e5dd7070Spatrick }
777e5dd7070Spatrick
778e5dd7070Spatrick // Infer a submodule with the same name as this header file.
779e5dd7070Spatrick SmallString<32> NameBuf;
780e5dd7070Spatrick StringRef Name = sanitizeFilenameAsIdentifier(
781e5dd7070Spatrick llvm::sys::path::stem(Header->getName()),
782e5dd7070Spatrick NameBuf);
783e5dd7070Spatrick Found = lookupModuleQualified(Name, Found);
784e5dd7070Spatrick if (!Found)
785e5dd7070Spatrick return false;
786e5dd7070Spatrick }
787e5dd7070Spatrick
788e5dd7070Spatrick return IsUnavailable(Found);
789e5dd7070Spatrick }
790e5dd7070Spatrick
791e5dd7070Spatrick SkippedDirs.push_back(Dir);
792e5dd7070Spatrick
793e5dd7070Spatrick // Retrieve our parent path.
794e5dd7070Spatrick DirName = llvm::sys::path::parent_path(DirName);
795e5dd7070Spatrick if (DirName.empty())
796e5dd7070Spatrick break;
797e5dd7070Spatrick
798e5dd7070Spatrick // Resolve the parent path to a directory entry.
799e5dd7070Spatrick if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName))
800e5dd7070Spatrick Dir = *DirEntry;
801e5dd7070Spatrick else
802e5dd7070Spatrick Dir = nullptr;
803e5dd7070Spatrick } while (Dir);
804e5dd7070Spatrick
805e5dd7070Spatrick return false;
806e5dd7070Spatrick }
807e5dd7070Spatrick
findModule(StringRef Name) const808e5dd7070Spatrick Module *ModuleMap::findModule(StringRef Name) const {
809e5dd7070Spatrick llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
810e5dd7070Spatrick if (Known != Modules.end())
811e5dd7070Spatrick return Known->getValue();
812e5dd7070Spatrick
813e5dd7070Spatrick return nullptr;
814e5dd7070Spatrick }
815e5dd7070Spatrick
lookupModuleUnqualified(StringRef Name,Module * Context) const816e5dd7070Spatrick Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
817e5dd7070Spatrick Module *Context) const {
818e5dd7070Spatrick for(; Context; Context = Context->Parent) {
819e5dd7070Spatrick if (Module *Sub = lookupModuleQualified(Name, Context))
820e5dd7070Spatrick return Sub;
821e5dd7070Spatrick }
822e5dd7070Spatrick
823e5dd7070Spatrick return findModule(Name);
824e5dd7070Spatrick }
825e5dd7070Spatrick
lookupModuleQualified(StringRef Name,Module * Context) const826e5dd7070Spatrick Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
827e5dd7070Spatrick if (!Context)
828e5dd7070Spatrick return findModule(Name);
829e5dd7070Spatrick
830e5dd7070Spatrick return Context->findSubmodule(Name);
831e5dd7070Spatrick }
832e5dd7070Spatrick
findOrCreateModule(StringRef Name,Module * Parent,bool IsFramework,bool IsExplicit)833e5dd7070Spatrick std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
834e5dd7070Spatrick Module *Parent,
835e5dd7070Spatrick bool IsFramework,
836e5dd7070Spatrick bool IsExplicit) {
837e5dd7070Spatrick // Try to find an existing module with this name.
838e5dd7070Spatrick if (Module *Sub = lookupModuleQualified(Name, Parent))
839e5dd7070Spatrick return std::make_pair(Sub, false);
840e5dd7070Spatrick
841e5dd7070Spatrick // Create a new module with this name.
842e5dd7070Spatrick Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
843e5dd7070Spatrick IsExplicit, NumCreatedModules++);
844e5dd7070Spatrick if (!Parent) {
845e5dd7070Spatrick if (LangOpts.CurrentModule == Name)
846e5dd7070Spatrick SourceModule = Result;
847e5dd7070Spatrick Modules[Name] = Result;
848e5dd7070Spatrick ModuleScopeIDs[Result] = CurrentModuleScopeID;
849e5dd7070Spatrick }
850e5dd7070Spatrick return std::make_pair(Result, true);
851e5dd7070Spatrick }
852e5dd7070Spatrick
createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,Module * Parent)853*12c85518Srobert Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
854*12c85518Srobert Module *Parent) {
855*12c85518Srobert auto *Result = new Module("<global>", Loc, Parent, /*IsFramework*/ false,
856*12c85518Srobert /*IsExplicit*/ true, NumCreatedModules++);
857*12c85518Srobert Result->Kind = Module::GlobalModuleFragment;
858*12c85518Srobert // If the created module isn't owned by a parent, send it to PendingSubmodules
859*12c85518Srobert // to wait for its parent.
860*12c85518Srobert if (!Result->Parent)
861*12c85518Srobert PendingSubmodules.emplace_back(Result);
862*12c85518Srobert return Result;
863e5dd7070Spatrick }
864e5dd7070Spatrick
865e5dd7070Spatrick Module *
createPrivateModuleFragmentForInterfaceUnit(Module * Parent,SourceLocation Loc)866e5dd7070Spatrick ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
867e5dd7070Spatrick SourceLocation Loc) {
868e5dd7070Spatrick auto *Result =
869e5dd7070Spatrick new Module("<private>", Loc, Parent, /*IsFramework*/ false,
870e5dd7070Spatrick /*IsExplicit*/ true, NumCreatedModules++);
871e5dd7070Spatrick Result->Kind = Module::PrivateModuleFragment;
872e5dd7070Spatrick return Result;
873e5dd7070Spatrick }
874e5dd7070Spatrick
createModuleForInterfaceUnit(SourceLocation Loc,StringRef Name)875e5dd7070Spatrick Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
876*12c85518Srobert StringRef Name) {
877e5dd7070Spatrick assert(LangOpts.CurrentModule == Name && "module name mismatch");
878e5dd7070Spatrick assert(!Modules[Name] && "redefining existing module");
879e5dd7070Spatrick
880e5dd7070Spatrick auto *Result =
881e5dd7070Spatrick new Module(Name, Loc, nullptr, /*IsFramework*/ false,
882e5dd7070Spatrick /*IsExplicit*/ false, NumCreatedModules++);
883e5dd7070Spatrick Result->Kind = Module::ModuleInterfaceUnit;
884e5dd7070Spatrick Modules[Name] = SourceModule = Result;
885e5dd7070Spatrick
886e5dd7070Spatrick // Reparent the current global module fragment as a submodule of this module.
887e5dd7070Spatrick for (auto &Submodule : PendingSubmodules) {
888e5dd7070Spatrick Submodule->setParent(Result);
889e5dd7070Spatrick Submodule.release(); // now owned by parent
890e5dd7070Spatrick }
891e5dd7070Spatrick PendingSubmodules.clear();
892e5dd7070Spatrick
893e5dd7070Spatrick // Mark the main source file as being within the newly-created module so that
894e5dd7070Spatrick // declarations and macros are properly visibility-restricted to it.
895e5dd7070Spatrick auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
896e5dd7070Spatrick assert(MainFile && "no input file for module interface");
897e5dd7070Spatrick Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader));
898e5dd7070Spatrick
899e5dd7070Spatrick return Result;
900e5dd7070Spatrick }
901e5dd7070Spatrick
createHeaderUnit(SourceLocation Loc,StringRef Name,Module::Header H)902*12c85518Srobert Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name,
903*12c85518Srobert Module::Header H) {
904e5dd7070Spatrick assert(LangOpts.CurrentModule == Name && "module name mismatch");
905e5dd7070Spatrick assert(!Modules[Name] && "redefining existing module");
906e5dd7070Spatrick
907*12c85518Srobert auto *Result = new Module(Name, Loc, nullptr, /*IsFramework*/ false,
908e5dd7070Spatrick /*IsExplicit*/ false, NumCreatedModules++);
909*12c85518Srobert Result->Kind = Module::ModuleHeaderUnit;
910e5dd7070Spatrick Modules[Name] = SourceModule = Result;
911*12c85518Srobert addHeader(Result, H, NormalHeader);
912e5dd7070Spatrick return Result;
913e5dd7070Spatrick }
914e5dd7070Spatrick
915e5dd7070Spatrick /// For a framework module, infer the framework against which we
916e5dd7070Spatrick /// should link.
inferFrameworkLink(Module * Mod,const DirectoryEntry * FrameworkDir,FileManager & FileMgr)917e5dd7070Spatrick static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
918e5dd7070Spatrick FileManager &FileMgr) {
919e5dd7070Spatrick assert(Mod->IsFramework && "Can only infer linking for framework modules");
920e5dd7070Spatrick assert(!Mod->isSubFramework() &&
921e5dd7070Spatrick "Can only infer linking for top-level frameworks");
922e5dd7070Spatrick
923e5dd7070Spatrick SmallString<128> LibName;
924e5dd7070Spatrick LibName += FrameworkDir->getName();
925e5dd7070Spatrick llvm::sys::path::append(LibName, Mod->Name);
926e5dd7070Spatrick
927e5dd7070Spatrick // The library name of a framework has more than one possible extension since
928e5dd7070Spatrick // the introduction of the text-based dynamic library format. We need to check
929e5dd7070Spatrick // for both before we give up.
930e5dd7070Spatrick for (const char *extension : {"", ".tbd"}) {
931e5dd7070Spatrick llvm::sys::path::replace_extension(LibName, extension);
932e5dd7070Spatrick if (FileMgr.getFile(LibName)) {
933e5dd7070Spatrick Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
934e5dd7070Spatrick /*IsFramework=*/true));
935e5dd7070Spatrick return;
936e5dd7070Spatrick }
937e5dd7070Spatrick }
938e5dd7070Spatrick }
939e5dd7070Spatrick
inferFrameworkModule(const DirectoryEntry * FrameworkDir,bool IsSystem,Module * Parent)940e5dd7070Spatrick Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
941e5dd7070Spatrick bool IsSystem, Module *Parent) {
942e5dd7070Spatrick Attributes Attrs;
943e5dd7070Spatrick Attrs.IsSystem = IsSystem;
944e5dd7070Spatrick return inferFrameworkModule(FrameworkDir, Attrs, Parent);
945e5dd7070Spatrick }
946e5dd7070Spatrick
inferFrameworkModule(const DirectoryEntry * FrameworkDir,Attributes Attrs,Module * Parent)947e5dd7070Spatrick Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
948e5dd7070Spatrick Attributes Attrs, Module *Parent) {
949e5dd7070Spatrick // Note: as an egregious but useful hack we use the real path here, because
950e5dd7070Spatrick // we might be looking at an embedded framework that symlinks out to a
951e5dd7070Spatrick // top-level framework, and we need to infer as if we were naming the
952e5dd7070Spatrick // top-level framework.
953e5dd7070Spatrick StringRef FrameworkDirName =
954e5dd7070Spatrick SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
955e5dd7070Spatrick
956e5dd7070Spatrick // In case this is a case-insensitive filesystem, use the canonical
957e5dd7070Spatrick // directory name as the ModuleName, since modules are case-sensitive.
958e5dd7070Spatrick // FIXME: we should be able to give a fix-it hint for the correct spelling.
959e5dd7070Spatrick SmallString<32> ModuleNameStorage;
960e5dd7070Spatrick StringRef ModuleName = sanitizeFilenameAsIdentifier(
961e5dd7070Spatrick llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
962e5dd7070Spatrick
963e5dd7070Spatrick // Check whether we've already found this module.
964e5dd7070Spatrick if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
965e5dd7070Spatrick return Mod;
966e5dd7070Spatrick
967e5dd7070Spatrick FileManager &FileMgr = SourceMgr.getFileManager();
968e5dd7070Spatrick
969e5dd7070Spatrick // If the framework has a parent path from which we're allowed to infer
970e5dd7070Spatrick // a framework module, do so.
971e5dd7070Spatrick const FileEntry *ModuleMapFile = nullptr;
972e5dd7070Spatrick if (!Parent) {
973e5dd7070Spatrick // Determine whether we're allowed to infer a module map.
974e5dd7070Spatrick bool canInfer = false;
975e5dd7070Spatrick if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
976e5dd7070Spatrick // Figure out the parent path.
977e5dd7070Spatrick StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
978e5dd7070Spatrick if (auto ParentDir = FileMgr.getDirectory(Parent)) {
979e5dd7070Spatrick // Check whether we have already looked into the parent directory
980e5dd7070Spatrick // for a module map.
981e5dd7070Spatrick llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
982e5dd7070Spatrick inferred = InferredDirectories.find(*ParentDir);
983e5dd7070Spatrick if (inferred == InferredDirectories.end()) {
984e5dd7070Spatrick // We haven't looked here before. Load a module map, if there is
985e5dd7070Spatrick // one.
986e5dd7070Spatrick bool IsFrameworkDir = Parent.endswith(".framework");
987e5dd7070Spatrick if (const FileEntry *ModMapFile =
988e5dd7070Spatrick HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) {
989e5dd7070Spatrick parseModuleMapFile(ModMapFile, Attrs.IsSystem, *ParentDir);
990e5dd7070Spatrick inferred = InferredDirectories.find(*ParentDir);
991e5dd7070Spatrick }
992e5dd7070Spatrick
993e5dd7070Spatrick if (inferred == InferredDirectories.end())
994e5dd7070Spatrick inferred = InferredDirectories.insert(
995e5dd7070Spatrick std::make_pair(*ParentDir, InferredDirectory())).first;
996e5dd7070Spatrick }
997e5dd7070Spatrick
998e5dd7070Spatrick if (inferred->second.InferModules) {
999e5dd7070Spatrick // We're allowed to infer for this directory, but make sure it's okay
1000e5dd7070Spatrick // to infer this particular module.
1001e5dd7070Spatrick StringRef Name = llvm::sys::path::stem(FrameworkDirName);
1002*12c85518Srobert canInfer =
1003*12c85518Srobert !llvm::is_contained(inferred->second.ExcludedModules, Name);
1004e5dd7070Spatrick
1005e5dd7070Spatrick Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
1006e5dd7070Spatrick Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
1007e5dd7070Spatrick Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
1008e5dd7070Spatrick Attrs.NoUndeclaredIncludes |=
1009e5dd7070Spatrick inferred->second.Attrs.NoUndeclaredIncludes;
1010e5dd7070Spatrick ModuleMapFile = inferred->second.ModuleMapFile;
1011e5dd7070Spatrick }
1012e5dd7070Spatrick }
1013e5dd7070Spatrick }
1014e5dd7070Spatrick
1015e5dd7070Spatrick // If we're not allowed to infer a framework module, don't.
1016e5dd7070Spatrick if (!canInfer)
1017e5dd7070Spatrick return nullptr;
1018*12c85518Srobert } else {
1019*12c85518Srobert OptionalFileEntryRefDegradesToFileEntryPtr ModuleMapRef =
1020*12c85518Srobert getModuleMapFileForUniquing(Parent);
1021*12c85518Srobert ModuleMapFile = ModuleMapRef;
1022*12c85518Srobert }
1023e5dd7070Spatrick
1024e5dd7070Spatrick // Look for an umbrella header.
1025e5dd7070Spatrick SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
1026e5dd7070Spatrick llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
1027*12c85518Srobert auto UmbrellaHeader = FileMgr.getOptionalFileRef(UmbrellaName);
1028e5dd7070Spatrick
1029e5dd7070Spatrick // FIXME: If there's no umbrella header, we could probably scan the
1030e5dd7070Spatrick // framework to load *everything*. But, it's not clear that this is a good
1031e5dd7070Spatrick // idea.
1032e5dd7070Spatrick if (!UmbrellaHeader)
1033e5dd7070Spatrick return nullptr;
1034e5dd7070Spatrick
1035e5dd7070Spatrick Module *Result = new Module(ModuleName, SourceLocation(), Parent,
1036e5dd7070Spatrick /*IsFramework=*/true, /*IsExplicit=*/false,
1037e5dd7070Spatrick NumCreatedModules++);
1038e5dd7070Spatrick InferredModuleAllowedBy[Result] = ModuleMapFile;
1039e5dd7070Spatrick Result->IsInferred = true;
1040e5dd7070Spatrick if (!Parent) {
1041e5dd7070Spatrick if (LangOpts.CurrentModule == ModuleName)
1042e5dd7070Spatrick SourceModule = Result;
1043e5dd7070Spatrick Modules[ModuleName] = Result;
1044e5dd7070Spatrick ModuleScopeIDs[Result] = CurrentModuleScopeID;
1045e5dd7070Spatrick }
1046e5dd7070Spatrick
1047e5dd7070Spatrick Result->IsSystem |= Attrs.IsSystem;
1048e5dd7070Spatrick Result->IsExternC |= Attrs.IsExternC;
1049e5dd7070Spatrick Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
1050e5dd7070Spatrick Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
1051e5dd7070Spatrick Result->Directory = FrameworkDir;
1052e5dd7070Spatrick
1053a9ac8606Spatrick // Chop off the first framework bit, as that is implied.
1054a9ac8606Spatrick StringRef RelativePath = UmbrellaName.str().substr(
1055a9ac8606Spatrick Result->getTopLevelModule()->Directory->getName().size());
1056a9ac8606Spatrick RelativePath = llvm::sys::path::relative_path(RelativePath);
1057a9ac8606Spatrick
1058e5dd7070Spatrick // umbrella header "umbrella-header-name"
1059a9ac8606Spatrick setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h", RelativePath);
1060e5dd7070Spatrick
1061e5dd7070Spatrick // export *
1062e5dd7070Spatrick Result->Exports.push_back(Module::ExportDecl(nullptr, true));
1063e5dd7070Spatrick
1064e5dd7070Spatrick // module * { export * }
1065e5dd7070Spatrick Result->InferSubmodules = true;
1066e5dd7070Spatrick Result->InferExportWildcard = true;
1067e5dd7070Spatrick
1068e5dd7070Spatrick // Look for subframeworks.
1069e5dd7070Spatrick std::error_code EC;
1070e5dd7070Spatrick SmallString<128> SubframeworksDirName
1071e5dd7070Spatrick = StringRef(FrameworkDir->getName());
1072e5dd7070Spatrick llvm::sys::path::append(SubframeworksDirName, "Frameworks");
1073e5dd7070Spatrick llvm::sys::path::native(SubframeworksDirName);
1074e5dd7070Spatrick llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
1075e5dd7070Spatrick for (llvm::vfs::directory_iterator
1076e5dd7070Spatrick Dir = FS.dir_begin(SubframeworksDirName, EC),
1077e5dd7070Spatrick DirEnd;
1078e5dd7070Spatrick Dir != DirEnd && !EC; Dir.increment(EC)) {
1079e5dd7070Spatrick if (!StringRef(Dir->path()).endswith(".framework"))
1080e5dd7070Spatrick continue;
1081e5dd7070Spatrick
1082e5dd7070Spatrick if (auto SubframeworkDir =
1083e5dd7070Spatrick FileMgr.getDirectory(Dir->path())) {
1084e5dd7070Spatrick // Note: as an egregious but useful hack, we use the real path here and
1085e5dd7070Spatrick // check whether it is actually a subdirectory of the parent directory.
1086e5dd7070Spatrick // This will not be the case if the 'subframework' is actually a symlink
1087e5dd7070Spatrick // out to a top-level framework.
1088e5dd7070Spatrick StringRef SubframeworkDirName =
1089e5dd7070Spatrick FileMgr.getCanonicalName(*SubframeworkDir);
1090e5dd7070Spatrick bool FoundParent = false;
1091e5dd7070Spatrick do {
1092e5dd7070Spatrick // Get the parent directory name.
1093e5dd7070Spatrick SubframeworkDirName
1094e5dd7070Spatrick = llvm::sys::path::parent_path(SubframeworkDirName);
1095e5dd7070Spatrick if (SubframeworkDirName.empty())
1096e5dd7070Spatrick break;
1097e5dd7070Spatrick
1098e5dd7070Spatrick if (auto SubDir = FileMgr.getDirectory(SubframeworkDirName)) {
1099e5dd7070Spatrick if (*SubDir == FrameworkDir) {
1100e5dd7070Spatrick FoundParent = true;
1101e5dd7070Spatrick break;
1102e5dd7070Spatrick }
1103e5dd7070Spatrick }
1104e5dd7070Spatrick } while (true);
1105e5dd7070Spatrick
1106e5dd7070Spatrick if (!FoundParent)
1107e5dd7070Spatrick continue;
1108e5dd7070Spatrick
1109e5dd7070Spatrick // FIXME: Do we want to warn about subframeworks without umbrella headers?
1110e5dd7070Spatrick inferFrameworkModule(*SubframeworkDir, Attrs, Result);
1111e5dd7070Spatrick }
1112e5dd7070Spatrick }
1113e5dd7070Spatrick
1114e5dd7070Spatrick // If the module is a top-level framework, automatically link against the
1115e5dd7070Spatrick // framework.
1116e5dd7070Spatrick if (!Result->isSubFramework()) {
1117e5dd7070Spatrick inferFrameworkLink(Result, FrameworkDir, FileMgr);
1118e5dd7070Spatrick }
1119e5dd7070Spatrick
1120e5dd7070Spatrick return Result;
1121e5dd7070Spatrick }
1122e5dd7070Spatrick
createShadowedModule(StringRef Name,bool IsFramework,Module * ShadowingModule)1123e5dd7070Spatrick Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
1124e5dd7070Spatrick Module *ShadowingModule) {
1125e5dd7070Spatrick
1126e5dd7070Spatrick // Create a new module with this name.
1127e5dd7070Spatrick Module *Result =
1128e5dd7070Spatrick new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
1129e5dd7070Spatrick /*IsExplicit=*/false, NumCreatedModules++);
1130e5dd7070Spatrick Result->ShadowingModule = ShadowingModule;
1131ec727ea7Spatrick Result->markUnavailable(/*Unimportable*/true);
1132e5dd7070Spatrick ModuleScopeIDs[Result] = CurrentModuleScopeID;
1133e5dd7070Spatrick ShadowModules.push_back(Result);
1134e5dd7070Spatrick
1135e5dd7070Spatrick return Result;
1136e5dd7070Spatrick }
1137e5dd7070Spatrick
setUmbrellaHeader(Module * Mod,FileEntryRef UmbrellaHeader,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)1138a9ac8606Spatrick void ModuleMap::setUmbrellaHeader(
1139*12c85518Srobert Module *Mod, FileEntryRef UmbrellaHeader, const Twine &NameAsWritten,
1140a9ac8606Spatrick const Twine &PathRelativeToRootModuleDirectory) {
1141e5dd7070Spatrick Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
1142*12c85518Srobert Mod->Umbrella = &UmbrellaHeader.getMapEntry();
1143e5dd7070Spatrick Mod->UmbrellaAsWritten = NameAsWritten.str();
1144a9ac8606Spatrick Mod->UmbrellaRelativeToRootModuleDirectory =
1145a9ac8606Spatrick PathRelativeToRootModuleDirectory.str();
1146*12c85518Srobert UmbrellaDirs[UmbrellaHeader.getDir()] = Mod;
1147e5dd7070Spatrick
1148e5dd7070Spatrick // Notify callbacks that we just added a new header.
1149e5dd7070Spatrick for (const auto &Cb : Callbacks)
1150e5dd7070Spatrick Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
1151e5dd7070Spatrick }
1152e5dd7070Spatrick
setUmbrellaDir(Module * Mod,const DirectoryEntry * UmbrellaDir,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)1153e5dd7070Spatrick void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
1154a9ac8606Spatrick const Twine &NameAsWritten,
1155a9ac8606Spatrick const Twine &PathRelativeToRootModuleDirectory) {
1156e5dd7070Spatrick Mod->Umbrella = UmbrellaDir;
1157e5dd7070Spatrick Mod->UmbrellaAsWritten = NameAsWritten.str();
1158a9ac8606Spatrick Mod->UmbrellaRelativeToRootModuleDirectory =
1159a9ac8606Spatrick PathRelativeToRootModuleDirectory.str();
1160e5dd7070Spatrick UmbrellaDirs[UmbrellaDir] = Mod;
1161e5dd7070Spatrick }
1162e5dd7070Spatrick
addUnresolvedHeader(Module * Mod,Module::UnresolvedHeaderDirective Header,bool & NeedsFramework)1163e5dd7070Spatrick void ModuleMap::addUnresolvedHeader(Module *Mod,
1164e5dd7070Spatrick Module::UnresolvedHeaderDirective Header,
1165e5dd7070Spatrick bool &NeedsFramework) {
1166e5dd7070Spatrick // If there is a builtin counterpart to this file, add it now so it can
1167e5dd7070Spatrick // wrap the system header.
1168e5dd7070Spatrick if (resolveAsBuiltinHeader(Mod, Header)) {
1169e5dd7070Spatrick // If we have both a builtin and system version of the file, the
1170e5dd7070Spatrick // builtin version may want to inject macros into the system header, so
1171e5dd7070Spatrick // force the system header to be treated as a textual header in this
1172e5dd7070Spatrick // case.
1173e5dd7070Spatrick Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
1174e5dd7070Spatrick headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
1175e5dd7070Spatrick Header.HasBuiltinHeader = true;
1176e5dd7070Spatrick }
1177e5dd7070Spatrick
1178e5dd7070Spatrick // If possible, don't stat the header until we need to. This requires the
1179e5dd7070Spatrick // user to have provided us with some stat information about the file.
1180e5dd7070Spatrick // FIXME: Add support for lazily stat'ing umbrella headers and excluded
1181e5dd7070Spatrick // headers.
1182e5dd7070Spatrick if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
1183e5dd7070Spatrick Header.Kind != Module::HK_Excluded) {
1184e5dd7070Spatrick // We expect more variation in mtime than size, so if we're given both,
1185e5dd7070Spatrick // use the mtime as the key.
1186e5dd7070Spatrick if (Header.ModTime)
1187e5dd7070Spatrick LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
1188e5dd7070Spatrick else
1189e5dd7070Spatrick LazyHeadersBySize[*Header.Size].push_back(Mod);
1190e5dd7070Spatrick Mod->UnresolvedHeaders.push_back(Header);
1191e5dd7070Spatrick return;
1192e5dd7070Spatrick }
1193e5dd7070Spatrick
1194e5dd7070Spatrick // We don't have stat information or can't defer looking this file up.
1195e5dd7070Spatrick // Perform the lookup now.
1196e5dd7070Spatrick resolveHeader(Mod, Header, NeedsFramework);
1197e5dd7070Spatrick }
1198e5dd7070Spatrick
resolveHeaderDirectives(const FileEntry * File) const1199e5dd7070Spatrick void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
1200e5dd7070Spatrick auto BySize = LazyHeadersBySize.find(File->getSize());
1201e5dd7070Spatrick if (BySize != LazyHeadersBySize.end()) {
1202e5dd7070Spatrick for (auto *M : BySize->second)
1203*12c85518Srobert resolveHeaderDirectives(M, File);
1204e5dd7070Spatrick LazyHeadersBySize.erase(BySize);
1205e5dd7070Spatrick }
1206e5dd7070Spatrick
1207e5dd7070Spatrick auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
1208e5dd7070Spatrick if (ByModTime != LazyHeadersByModTime.end()) {
1209e5dd7070Spatrick for (auto *M : ByModTime->second)
1210*12c85518Srobert resolveHeaderDirectives(M, File);
1211e5dd7070Spatrick LazyHeadersByModTime.erase(ByModTime);
1212e5dd7070Spatrick }
1213e5dd7070Spatrick }
1214e5dd7070Spatrick
resolveHeaderDirectives(Module * Mod,std::optional<const FileEntry * > File) const1215*12c85518Srobert void ModuleMap::resolveHeaderDirectives(
1216*12c85518Srobert Module *Mod, std::optional<const FileEntry *> File) const {
1217e5dd7070Spatrick bool NeedsFramework = false;
1218*12c85518Srobert SmallVector<Module::UnresolvedHeaderDirective, 1> NewHeaders;
1219*12c85518Srobert const auto Size = File ? (*File)->getSize() : 0;
1220*12c85518Srobert const auto ModTime = File ? (*File)->getModificationTime() : 0;
1221*12c85518Srobert
1222*12c85518Srobert for (auto &Header : Mod->UnresolvedHeaders) {
1223*12c85518Srobert if (File && ((Header.ModTime && Header.ModTime != ModTime) ||
1224*12c85518Srobert (Header.Size && Header.Size != Size)))
1225*12c85518Srobert NewHeaders.push_back(Header);
1226*12c85518Srobert else
1227e5dd7070Spatrick // This operation is logically const; we're just changing how we represent
1228e5dd7070Spatrick // the header information for this file.
1229e5dd7070Spatrick const_cast<ModuleMap *>(this)->resolveHeader(Mod, Header, NeedsFramework);
1230*12c85518Srobert }
1231*12c85518Srobert Mod->UnresolvedHeaders.swap(NewHeaders);
1232e5dd7070Spatrick }
1233e5dd7070Spatrick
addHeader(Module * Mod,Module::Header Header,ModuleHeaderRole Role,bool Imported)1234e5dd7070Spatrick void ModuleMap::addHeader(Module *Mod, Module::Header Header,
1235e5dd7070Spatrick ModuleHeaderRole Role, bool Imported) {
1236e5dd7070Spatrick KnownHeader KH(Mod, Role);
1237e5dd7070Spatrick
1238e5dd7070Spatrick // Only add each header to the headers list once.
1239e5dd7070Spatrick // FIXME: Should we diagnose if a header is listed twice in the
1240e5dd7070Spatrick // same module definition?
1241e5dd7070Spatrick auto &HeaderList = Headers[Header.Entry];
1242*12c85518Srobert if (llvm::is_contained(HeaderList, KH))
1243e5dd7070Spatrick return;
1244e5dd7070Spatrick
1245e5dd7070Spatrick HeaderList.push_back(KH);
1246e5dd7070Spatrick Mod->Headers[headerRoleToKind(Role)].push_back(Header);
1247e5dd7070Spatrick
1248e5dd7070Spatrick bool isCompilingModuleHeader =
1249e5dd7070Spatrick LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
1250e5dd7070Spatrick if (!Imported || isCompilingModuleHeader) {
1251e5dd7070Spatrick // When we import HeaderFileInfo, the external source is expected to
1252e5dd7070Spatrick // set the isModuleHeader flag itself.
1253e5dd7070Spatrick HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
1254e5dd7070Spatrick isCompilingModuleHeader);
1255e5dd7070Spatrick }
1256e5dd7070Spatrick
1257e5dd7070Spatrick // Notify callbacks that we just added a new header.
1258e5dd7070Spatrick for (const auto &Cb : Callbacks)
1259e5dd7070Spatrick Cb->moduleMapAddHeader(Header.Entry->getName());
1260e5dd7070Spatrick }
1261e5dd7070Spatrick
1262*12c85518Srobert OptionalFileEntryRef
getContainingModuleMapFile(const Module * Module) const1263e5dd7070Spatrick ModuleMap::getContainingModuleMapFile(const Module *Module) const {
1264e5dd7070Spatrick if (Module->DefinitionLoc.isInvalid())
1265*12c85518Srobert return std::nullopt;
1266e5dd7070Spatrick
1267*12c85518Srobert return SourceMgr.getFileEntryRefForID(
1268e5dd7070Spatrick SourceMgr.getFileID(Module->DefinitionLoc));
1269e5dd7070Spatrick }
1270e5dd7070Spatrick
1271*12c85518Srobert OptionalFileEntryRef
getModuleMapFileForUniquing(const Module * M) const1272*12c85518Srobert ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
1273e5dd7070Spatrick if (M->IsInferred) {
1274e5dd7070Spatrick assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
1275*12c85518Srobert // FIXME: Update InferredModuleAllowedBy to use FileEntryRef.
1276*12c85518Srobert return InferredModuleAllowedBy.find(M)->second->getLastRef();
1277e5dd7070Spatrick }
1278e5dd7070Spatrick return getContainingModuleMapFile(M);
1279e5dd7070Spatrick }
1280e5dd7070Spatrick
setInferredModuleAllowedBy(Module * M,const FileEntry * ModMap)1281e5dd7070Spatrick void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
1282e5dd7070Spatrick assert(M->IsInferred && "module not inferred");
1283e5dd7070Spatrick InferredModuleAllowedBy[M] = ModMap;
1284e5dd7070Spatrick }
1285e5dd7070Spatrick
1286*12c85518Srobert std::error_code
canonicalizeModuleMapPath(SmallVectorImpl<char> & Path)1287*12c85518Srobert ModuleMap::canonicalizeModuleMapPath(SmallVectorImpl<char> &Path) {
1288*12c85518Srobert StringRef Dir = llvm::sys::path::parent_path({Path.data(), Path.size()});
1289*12c85518Srobert
1290*12c85518Srobert // Do not canonicalize within the framework; the module map parser expects
1291*12c85518Srobert // Modules/ not Versions/A/Modules.
1292*12c85518Srobert if (llvm::sys::path::filename(Dir) == "Modules") {
1293*12c85518Srobert StringRef Parent = llvm::sys::path::parent_path(Dir);
1294*12c85518Srobert if (Parent.endswith(".framework"))
1295*12c85518Srobert Dir = Parent;
1296*12c85518Srobert }
1297*12c85518Srobert
1298*12c85518Srobert FileManager &FM = SourceMgr.getFileManager();
1299*12c85518Srobert auto DirEntry = FM.getDirectory(Dir.empty() ? "." : Dir);
1300*12c85518Srobert if (!DirEntry)
1301*12c85518Srobert return DirEntry.getError();
1302*12c85518Srobert
1303*12c85518Srobert // Canonicalize the directory.
1304*12c85518Srobert StringRef CanonicalDir = FM.getCanonicalName(*DirEntry);
1305*12c85518Srobert if (CanonicalDir != Dir) {
1306*12c85518Srobert auto CanonicalDirEntry = FM.getDirectory(CanonicalDir);
1307*12c85518Srobert // Only use the canonicalized path if it resolves to the same entry as the
1308*12c85518Srobert // original. This is not true if there's a VFS overlay on top of a FS where
1309*12c85518Srobert // the directory is a symlink. The overlay would not remap the target path
1310*12c85518Srobert // of the symlink to the same directory entry in that case.
1311*12c85518Srobert if (CanonicalDirEntry && *CanonicalDirEntry == *DirEntry) {
1312*12c85518Srobert bool Done = llvm::sys::path::replace_path_prefix(Path, Dir, CanonicalDir);
1313*12c85518Srobert (void)Done;
1314*12c85518Srobert assert(Done && "Path should always start with Dir");
1315*12c85518Srobert }
1316*12c85518Srobert }
1317*12c85518Srobert
1318*12c85518Srobert // In theory, the filename component should also be canonicalized if it
1319*12c85518Srobert // on a case-insensitive filesystem. However, the extra canonicalization is
1320*12c85518Srobert // expensive and if clang looked up the filename it will always be lowercase.
1321*12c85518Srobert
1322*12c85518Srobert // Remove ., remove redundant separators, and switch to native separators.
1323*12c85518Srobert // This is needed for separators between CanonicalDir and the filename.
1324*12c85518Srobert llvm::sys::path::remove_dots(Path);
1325*12c85518Srobert
1326*12c85518Srobert return std::error_code();
1327*12c85518Srobert }
1328*12c85518Srobert
addAdditionalModuleMapFile(const Module * M,const FileEntry * ModuleMap)1329ec727ea7Spatrick void ModuleMap::addAdditionalModuleMapFile(const Module *M,
1330ec727ea7Spatrick const FileEntry *ModuleMap) {
1331ec727ea7Spatrick AdditionalModMaps[M].insert(ModuleMap);
1332ec727ea7Spatrick }
1333ec727ea7Spatrick
dump()1334e5dd7070Spatrick LLVM_DUMP_METHOD void ModuleMap::dump() {
1335e5dd7070Spatrick llvm::errs() << "Modules:";
1336e5dd7070Spatrick for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1337e5dd7070Spatrick MEnd = Modules.end();
1338e5dd7070Spatrick M != MEnd; ++M)
1339e5dd7070Spatrick M->getValue()->print(llvm::errs(), 2);
1340e5dd7070Spatrick
1341e5dd7070Spatrick llvm::errs() << "Headers:";
1342e5dd7070Spatrick for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1343e5dd7070Spatrick H != HEnd; ++H) {
1344e5dd7070Spatrick llvm::errs() << " \"" << H->first->getName() << "\" -> ";
1345e5dd7070Spatrick for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
1346e5dd7070Spatrick E = H->second.end();
1347e5dd7070Spatrick I != E; ++I) {
1348e5dd7070Spatrick if (I != H->second.begin())
1349e5dd7070Spatrick llvm::errs() << ",";
1350e5dd7070Spatrick llvm::errs() << I->getModule()->getFullModuleName();
1351e5dd7070Spatrick }
1352e5dd7070Spatrick llvm::errs() << "\n";
1353e5dd7070Spatrick }
1354e5dd7070Spatrick }
1355e5dd7070Spatrick
resolveExports(Module * Mod,bool Complain)1356e5dd7070Spatrick bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
1357e5dd7070Spatrick auto Unresolved = std::move(Mod->UnresolvedExports);
1358e5dd7070Spatrick Mod->UnresolvedExports.clear();
1359e5dd7070Spatrick for (auto &UE : Unresolved) {
1360e5dd7070Spatrick Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
1361e5dd7070Spatrick if (Export.getPointer() || Export.getInt())
1362e5dd7070Spatrick Mod->Exports.push_back(Export);
1363e5dd7070Spatrick else
1364e5dd7070Spatrick Mod->UnresolvedExports.push_back(UE);
1365e5dd7070Spatrick }
1366e5dd7070Spatrick return !Mod->UnresolvedExports.empty();
1367e5dd7070Spatrick }
1368e5dd7070Spatrick
resolveUses(Module * Mod,bool Complain)1369e5dd7070Spatrick bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
1370e5dd7070Spatrick auto Unresolved = std::move(Mod->UnresolvedDirectUses);
1371e5dd7070Spatrick Mod->UnresolvedDirectUses.clear();
1372e5dd7070Spatrick for (auto &UDU : Unresolved) {
1373e5dd7070Spatrick Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
1374e5dd7070Spatrick if (DirectUse)
1375e5dd7070Spatrick Mod->DirectUses.push_back(DirectUse);
1376e5dd7070Spatrick else
1377e5dd7070Spatrick Mod->UnresolvedDirectUses.push_back(UDU);
1378e5dd7070Spatrick }
1379e5dd7070Spatrick return !Mod->UnresolvedDirectUses.empty();
1380e5dd7070Spatrick }
1381e5dd7070Spatrick
resolveConflicts(Module * Mod,bool Complain)1382e5dd7070Spatrick bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
1383e5dd7070Spatrick auto Unresolved = std::move(Mod->UnresolvedConflicts);
1384e5dd7070Spatrick Mod->UnresolvedConflicts.clear();
1385e5dd7070Spatrick for (auto &UC : Unresolved) {
1386e5dd7070Spatrick if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1387e5dd7070Spatrick Module::Conflict Conflict;
1388e5dd7070Spatrick Conflict.Other = OtherMod;
1389e5dd7070Spatrick Conflict.Message = UC.Message;
1390e5dd7070Spatrick Mod->Conflicts.push_back(Conflict);
1391e5dd7070Spatrick } else
1392e5dd7070Spatrick Mod->UnresolvedConflicts.push_back(UC);
1393e5dd7070Spatrick }
1394e5dd7070Spatrick return !Mod->UnresolvedConflicts.empty();
1395e5dd7070Spatrick }
1396e5dd7070Spatrick
1397e5dd7070Spatrick //----------------------------------------------------------------------------//
1398e5dd7070Spatrick // Module map file parser
1399e5dd7070Spatrick //----------------------------------------------------------------------------//
1400e5dd7070Spatrick
1401e5dd7070Spatrick namespace clang {
1402e5dd7070Spatrick
1403e5dd7070Spatrick /// A token in a module map file.
1404e5dd7070Spatrick struct MMToken {
1405e5dd7070Spatrick enum TokenKind {
1406e5dd7070Spatrick Comma,
1407e5dd7070Spatrick ConfigMacros,
1408e5dd7070Spatrick Conflict,
1409e5dd7070Spatrick EndOfFile,
1410e5dd7070Spatrick HeaderKeyword,
1411e5dd7070Spatrick Identifier,
1412e5dd7070Spatrick Exclaim,
1413e5dd7070Spatrick ExcludeKeyword,
1414e5dd7070Spatrick ExplicitKeyword,
1415e5dd7070Spatrick ExportKeyword,
1416e5dd7070Spatrick ExportAsKeyword,
1417e5dd7070Spatrick ExternKeyword,
1418e5dd7070Spatrick FrameworkKeyword,
1419e5dd7070Spatrick LinkKeyword,
1420e5dd7070Spatrick ModuleKeyword,
1421e5dd7070Spatrick Period,
1422e5dd7070Spatrick PrivateKeyword,
1423e5dd7070Spatrick UmbrellaKeyword,
1424e5dd7070Spatrick UseKeyword,
1425e5dd7070Spatrick RequiresKeyword,
1426e5dd7070Spatrick Star,
1427e5dd7070Spatrick StringLiteral,
1428e5dd7070Spatrick IntegerLiteral,
1429e5dd7070Spatrick TextualKeyword,
1430e5dd7070Spatrick LBrace,
1431e5dd7070Spatrick RBrace,
1432e5dd7070Spatrick LSquare,
1433e5dd7070Spatrick RSquare
1434e5dd7070Spatrick } Kind;
1435e5dd7070Spatrick
1436a9ac8606Spatrick SourceLocation::UIntTy Location;
1437e5dd7070Spatrick unsigned StringLength;
1438e5dd7070Spatrick union {
1439e5dd7070Spatrick // If Kind != IntegerLiteral.
1440e5dd7070Spatrick const char *StringData;
1441e5dd7070Spatrick
1442e5dd7070Spatrick // If Kind == IntegerLiteral.
1443e5dd7070Spatrick uint64_t IntegerValue;
1444e5dd7070Spatrick };
1445e5dd7070Spatrick
clearclang::MMToken1446e5dd7070Spatrick void clear() {
1447e5dd7070Spatrick Kind = EndOfFile;
1448e5dd7070Spatrick Location = 0;
1449e5dd7070Spatrick StringLength = 0;
1450e5dd7070Spatrick StringData = nullptr;
1451e5dd7070Spatrick }
1452e5dd7070Spatrick
isclang::MMToken1453e5dd7070Spatrick bool is(TokenKind K) const { return Kind == K; }
1454e5dd7070Spatrick
getLocationclang::MMToken1455e5dd7070Spatrick SourceLocation getLocation() const {
1456e5dd7070Spatrick return SourceLocation::getFromRawEncoding(Location);
1457e5dd7070Spatrick }
1458e5dd7070Spatrick
getIntegerclang::MMToken1459e5dd7070Spatrick uint64_t getInteger() const {
1460e5dd7070Spatrick return Kind == IntegerLiteral ? IntegerValue : 0;
1461e5dd7070Spatrick }
1462e5dd7070Spatrick
getStringclang::MMToken1463e5dd7070Spatrick StringRef getString() const {
1464e5dd7070Spatrick return Kind == IntegerLiteral ? StringRef()
1465e5dd7070Spatrick : StringRef(StringData, StringLength);
1466e5dd7070Spatrick }
1467e5dd7070Spatrick };
1468e5dd7070Spatrick
1469e5dd7070Spatrick class ModuleMapParser {
1470e5dd7070Spatrick Lexer &L;
1471e5dd7070Spatrick SourceManager &SourceMgr;
1472e5dd7070Spatrick
1473e5dd7070Spatrick /// Default target information, used only for string literal
1474e5dd7070Spatrick /// parsing.
1475e5dd7070Spatrick const TargetInfo *Target;
1476e5dd7070Spatrick
1477e5dd7070Spatrick DiagnosticsEngine &Diags;
1478e5dd7070Spatrick ModuleMap ⤅
1479e5dd7070Spatrick
1480e5dd7070Spatrick /// The current module map file.
1481e5dd7070Spatrick const FileEntry *ModuleMapFile;
1482e5dd7070Spatrick
1483e5dd7070Spatrick /// Source location of most recent parsed module declaration
1484e5dd7070Spatrick SourceLocation CurrModuleDeclLoc;
1485e5dd7070Spatrick
1486e5dd7070Spatrick /// The directory that file names in this module map file should
1487e5dd7070Spatrick /// be resolved relative to.
1488e5dd7070Spatrick const DirectoryEntry *Directory;
1489e5dd7070Spatrick
1490e5dd7070Spatrick /// Whether this module map is in a system header directory.
1491e5dd7070Spatrick bool IsSystem;
1492e5dd7070Spatrick
1493e5dd7070Spatrick /// Whether an error occurred.
1494e5dd7070Spatrick bool HadError = false;
1495e5dd7070Spatrick
1496e5dd7070Spatrick /// Stores string data for the various string literals referenced
1497e5dd7070Spatrick /// during parsing.
1498e5dd7070Spatrick llvm::BumpPtrAllocator StringData;
1499e5dd7070Spatrick
1500e5dd7070Spatrick /// The current token.
1501e5dd7070Spatrick MMToken Tok;
1502e5dd7070Spatrick
1503e5dd7070Spatrick /// The active module.
1504e5dd7070Spatrick Module *ActiveModule = nullptr;
1505e5dd7070Spatrick
1506e5dd7070Spatrick /// Whether a module uses the 'requires excluded' hack to mark its
1507e5dd7070Spatrick /// contents as 'textual'.
1508e5dd7070Spatrick ///
1509e5dd7070Spatrick /// On older Darwin SDK versions, 'requires excluded' is used to mark the
1510e5dd7070Spatrick /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
1511e5dd7070Spatrick /// non-modular headers. For backwards compatibility, we continue to
1512e5dd7070Spatrick /// support this idiom for just these modules, and map the headers to
1513e5dd7070Spatrick /// 'textual' to match the original intent.
1514e5dd7070Spatrick llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
1515e5dd7070Spatrick
1516e5dd7070Spatrick /// Consume the current token and return its location.
1517e5dd7070Spatrick SourceLocation consumeToken();
1518e5dd7070Spatrick
1519e5dd7070Spatrick /// Skip tokens until we reach the a token with the given kind
1520e5dd7070Spatrick /// (or the end of the file).
1521e5dd7070Spatrick void skipUntil(MMToken::TokenKind K);
1522e5dd7070Spatrick
1523e5dd7070Spatrick using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
1524e5dd7070Spatrick
1525e5dd7070Spatrick bool parseModuleId(ModuleId &Id);
1526e5dd7070Spatrick void parseModuleDecl();
1527e5dd7070Spatrick void parseExternModuleDecl();
1528e5dd7070Spatrick void parseRequiresDecl();
1529e5dd7070Spatrick void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
1530e5dd7070Spatrick void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
1531e5dd7070Spatrick void parseExportDecl();
1532e5dd7070Spatrick void parseExportAsDecl();
1533e5dd7070Spatrick void parseUseDecl();
1534e5dd7070Spatrick void parseLinkDecl();
1535e5dd7070Spatrick void parseConfigMacros();
1536e5dd7070Spatrick void parseConflict();
1537e5dd7070Spatrick void parseInferredModuleDecl(bool Framework, bool Explicit);
1538e5dd7070Spatrick
1539e5dd7070Spatrick /// Private modules are canonicalized as Foo_Private. Clang provides extra
1540e5dd7070Spatrick /// module map search logic to find the appropriate private module when PCH
1541e5dd7070Spatrick /// is used with implicit module maps. Warn when private modules are written
1542e5dd7070Spatrick /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
1543e5dd7070Spatrick void diagnosePrivateModules(SourceLocation ExplicitLoc,
1544e5dd7070Spatrick SourceLocation FrameworkLoc);
1545e5dd7070Spatrick
1546e5dd7070Spatrick using Attributes = ModuleMap::Attributes;
1547e5dd7070Spatrick
1548e5dd7070Spatrick bool parseOptionalAttributes(Attributes &Attrs);
1549e5dd7070Spatrick
1550e5dd7070Spatrick public:
ModuleMapParser(Lexer & L,SourceManager & SourceMgr,const TargetInfo * Target,DiagnosticsEngine & Diags,ModuleMap & Map,const FileEntry * ModuleMapFile,const DirectoryEntry * Directory,bool IsSystem)1551e5dd7070Spatrick explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
1552e5dd7070Spatrick const TargetInfo *Target, DiagnosticsEngine &Diags,
1553e5dd7070Spatrick ModuleMap &Map, const FileEntry *ModuleMapFile,
1554e5dd7070Spatrick const DirectoryEntry *Directory, bool IsSystem)
1555e5dd7070Spatrick : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
1556e5dd7070Spatrick ModuleMapFile(ModuleMapFile), Directory(Directory),
1557e5dd7070Spatrick IsSystem(IsSystem) {
1558e5dd7070Spatrick Tok.clear();
1559e5dd7070Spatrick consumeToken();
1560e5dd7070Spatrick }
1561e5dd7070Spatrick
1562e5dd7070Spatrick bool parseModuleMapFile();
1563e5dd7070Spatrick
terminatedByDirective()1564e5dd7070Spatrick bool terminatedByDirective() { return false; }
getLocation()1565e5dd7070Spatrick SourceLocation getLocation() { return Tok.getLocation(); }
1566e5dd7070Spatrick };
1567e5dd7070Spatrick
1568e5dd7070Spatrick } // namespace clang
1569e5dd7070Spatrick
consumeToken()1570e5dd7070Spatrick SourceLocation ModuleMapParser::consumeToken() {
1571e5dd7070Spatrick SourceLocation Result = Tok.getLocation();
1572e5dd7070Spatrick
1573e5dd7070Spatrick retry:
1574e5dd7070Spatrick Tok.clear();
1575e5dd7070Spatrick Token LToken;
1576e5dd7070Spatrick L.LexFromRawLexer(LToken);
1577e5dd7070Spatrick Tok.Location = LToken.getLocation().getRawEncoding();
1578e5dd7070Spatrick switch (LToken.getKind()) {
1579e5dd7070Spatrick case tok::raw_identifier: {
1580e5dd7070Spatrick StringRef RI = LToken.getRawIdentifier();
1581e5dd7070Spatrick Tok.StringData = RI.data();
1582e5dd7070Spatrick Tok.StringLength = RI.size();
1583e5dd7070Spatrick Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
1584e5dd7070Spatrick .Case("config_macros", MMToken::ConfigMacros)
1585e5dd7070Spatrick .Case("conflict", MMToken::Conflict)
1586e5dd7070Spatrick .Case("exclude", MMToken::ExcludeKeyword)
1587e5dd7070Spatrick .Case("explicit", MMToken::ExplicitKeyword)
1588e5dd7070Spatrick .Case("export", MMToken::ExportKeyword)
1589e5dd7070Spatrick .Case("export_as", MMToken::ExportAsKeyword)
1590e5dd7070Spatrick .Case("extern", MMToken::ExternKeyword)
1591e5dd7070Spatrick .Case("framework", MMToken::FrameworkKeyword)
1592e5dd7070Spatrick .Case("header", MMToken::HeaderKeyword)
1593e5dd7070Spatrick .Case("link", MMToken::LinkKeyword)
1594e5dd7070Spatrick .Case("module", MMToken::ModuleKeyword)
1595e5dd7070Spatrick .Case("private", MMToken::PrivateKeyword)
1596e5dd7070Spatrick .Case("requires", MMToken::RequiresKeyword)
1597e5dd7070Spatrick .Case("textual", MMToken::TextualKeyword)
1598e5dd7070Spatrick .Case("umbrella", MMToken::UmbrellaKeyword)
1599e5dd7070Spatrick .Case("use", MMToken::UseKeyword)
1600e5dd7070Spatrick .Default(MMToken::Identifier);
1601e5dd7070Spatrick break;
1602e5dd7070Spatrick }
1603e5dd7070Spatrick
1604e5dd7070Spatrick case tok::comma:
1605e5dd7070Spatrick Tok.Kind = MMToken::Comma;
1606e5dd7070Spatrick break;
1607e5dd7070Spatrick
1608e5dd7070Spatrick case tok::eof:
1609e5dd7070Spatrick Tok.Kind = MMToken::EndOfFile;
1610e5dd7070Spatrick break;
1611e5dd7070Spatrick
1612e5dd7070Spatrick case tok::l_brace:
1613e5dd7070Spatrick Tok.Kind = MMToken::LBrace;
1614e5dd7070Spatrick break;
1615e5dd7070Spatrick
1616e5dd7070Spatrick case tok::l_square:
1617e5dd7070Spatrick Tok.Kind = MMToken::LSquare;
1618e5dd7070Spatrick break;
1619e5dd7070Spatrick
1620e5dd7070Spatrick case tok::period:
1621e5dd7070Spatrick Tok.Kind = MMToken::Period;
1622e5dd7070Spatrick break;
1623e5dd7070Spatrick
1624e5dd7070Spatrick case tok::r_brace:
1625e5dd7070Spatrick Tok.Kind = MMToken::RBrace;
1626e5dd7070Spatrick break;
1627e5dd7070Spatrick
1628e5dd7070Spatrick case tok::r_square:
1629e5dd7070Spatrick Tok.Kind = MMToken::RSquare;
1630e5dd7070Spatrick break;
1631e5dd7070Spatrick
1632e5dd7070Spatrick case tok::star:
1633e5dd7070Spatrick Tok.Kind = MMToken::Star;
1634e5dd7070Spatrick break;
1635e5dd7070Spatrick
1636e5dd7070Spatrick case tok::exclaim:
1637e5dd7070Spatrick Tok.Kind = MMToken::Exclaim;
1638e5dd7070Spatrick break;
1639e5dd7070Spatrick
1640e5dd7070Spatrick case tok::string_literal: {
1641e5dd7070Spatrick if (LToken.hasUDSuffix()) {
1642e5dd7070Spatrick Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
1643e5dd7070Spatrick HadError = true;
1644e5dd7070Spatrick goto retry;
1645e5dd7070Spatrick }
1646e5dd7070Spatrick
1647e5dd7070Spatrick // Parse the string literal.
1648e5dd7070Spatrick LangOptions LangOpts;
1649e5dd7070Spatrick StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
1650e5dd7070Spatrick if (StringLiteral.hadError)
1651e5dd7070Spatrick goto retry;
1652e5dd7070Spatrick
1653e5dd7070Spatrick // Copy the string literal into our string data allocator.
1654e5dd7070Spatrick unsigned Length = StringLiteral.GetStringLength();
1655e5dd7070Spatrick char *Saved = StringData.Allocate<char>(Length + 1);
1656e5dd7070Spatrick memcpy(Saved, StringLiteral.GetString().data(), Length);
1657e5dd7070Spatrick Saved[Length] = 0;
1658e5dd7070Spatrick
1659e5dd7070Spatrick // Form the token.
1660e5dd7070Spatrick Tok.Kind = MMToken::StringLiteral;
1661e5dd7070Spatrick Tok.StringData = Saved;
1662e5dd7070Spatrick Tok.StringLength = Length;
1663e5dd7070Spatrick break;
1664e5dd7070Spatrick }
1665e5dd7070Spatrick
1666e5dd7070Spatrick case tok::numeric_constant: {
1667e5dd7070Spatrick // We don't support any suffixes or other complications.
1668e5dd7070Spatrick SmallString<32> SpellingBuffer;
1669e5dd7070Spatrick SpellingBuffer.resize(LToken.getLength() + 1);
1670e5dd7070Spatrick const char *Start = SpellingBuffer.data();
1671e5dd7070Spatrick unsigned Length =
1672*12c85518Srobert Lexer::getSpelling(LToken, Start, SourceMgr, Map.LangOpts);
1673e5dd7070Spatrick uint64_t Value;
1674e5dd7070Spatrick if (StringRef(Start, Length).getAsInteger(0, Value)) {
1675e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1676e5dd7070Spatrick HadError = true;
1677e5dd7070Spatrick goto retry;
1678e5dd7070Spatrick }
1679e5dd7070Spatrick
1680e5dd7070Spatrick Tok.Kind = MMToken::IntegerLiteral;
1681e5dd7070Spatrick Tok.IntegerValue = Value;
1682e5dd7070Spatrick break;
1683e5dd7070Spatrick }
1684e5dd7070Spatrick
1685e5dd7070Spatrick case tok::comment:
1686e5dd7070Spatrick goto retry;
1687e5dd7070Spatrick
1688e5dd7070Spatrick case tok::hash:
1689e5dd7070Spatrick // A module map can be terminated prematurely by
1690e5dd7070Spatrick // #pragma clang module contents
1691e5dd7070Spatrick // When building the module, we'll treat the rest of the file as the
1692e5dd7070Spatrick // contents of the module.
1693e5dd7070Spatrick {
1694e5dd7070Spatrick auto NextIsIdent = [&](StringRef Str) -> bool {
1695e5dd7070Spatrick L.LexFromRawLexer(LToken);
1696e5dd7070Spatrick return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
1697e5dd7070Spatrick LToken.getRawIdentifier() == Str;
1698e5dd7070Spatrick };
1699e5dd7070Spatrick if (NextIsIdent("pragma") && NextIsIdent("clang") &&
1700e5dd7070Spatrick NextIsIdent("module") && NextIsIdent("contents")) {
1701e5dd7070Spatrick Tok.Kind = MMToken::EndOfFile;
1702e5dd7070Spatrick break;
1703e5dd7070Spatrick }
1704e5dd7070Spatrick }
1705*12c85518Srobert [[fallthrough]];
1706e5dd7070Spatrick
1707e5dd7070Spatrick default:
1708e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1709e5dd7070Spatrick HadError = true;
1710e5dd7070Spatrick goto retry;
1711e5dd7070Spatrick }
1712e5dd7070Spatrick
1713e5dd7070Spatrick return Result;
1714e5dd7070Spatrick }
1715e5dd7070Spatrick
skipUntil(MMToken::TokenKind K)1716e5dd7070Spatrick void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
1717e5dd7070Spatrick unsigned braceDepth = 0;
1718e5dd7070Spatrick unsigned squareDepth = 0;
1719e5dd7070Spatrick do {
1720e5dd7070Spatrick switch (Tok.Kind) {
1721e5dd7070Spatrick case MMToken::EndOfFile:
1722e5dd7070Spatrick return;
1723e5dd7070Spatrick
1724e5dd7070Spatrick case MMToken::LBrace:
1725e5dd7070Spatrick if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1726e5dd7070Spatrick return;
1727e5dd7070Spatrick
1728e5dd7070Spatrick ++braceDepth;
1729e5dd7070Spatrick break;
1730e5dd7070Spatrick
1731e5dd7070Spatrick case MMToken::LSquare:
1732e5dd7070Spatrick if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1733e5dd7070Spatrick return;
1734e5dd7070Spatrick
1735e5dd7070Spatrick ++squareDepth;
1736e5dd7070Spatrick break;
1737e5dd7070Spatrick
1738e5dd7070Spatrick case MMToken::RBrace:
1739e5dd7070Spatrick if (braceDepth > 0)
1740e5dd7070Spatrick --braceDepth;
1741e5dd7070Spatrick else if (Tok.is(K))
1742e5dd7070Spatrick return;
1743e5dd7070Spatrick break;
1744e5dd7070Spatrick
1745e5dd7070Spatrick case MMToken::RSquare:
1746e5dd7070Spatrick if (squareDepth > 0)
1747e5dd7070Spatrick --squareDepth;
1748e5dd7070Spatrick else if (Tok.is(K))
1749e5dd7070Spatrick return;
1750e5dd7070Spatrick break;
1751e5dd7070Spatrick
1752e5dd7070Spatrick default:
1753e5dd7070Spatrick if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
1754e5dd7070Spatrick return;
1755e5dd7070Spatrick break;
1756e5dd7070Spatrick }
1757e5dd7070Spatrick
1758e5dd7070Spatrick consumeToken();
1759e5dd7070Spatrick } while (true);
1760e5dd7070Spatrick }
1761e5dd7070Spatrick
1762e5dd7070Spatrick /// Parse a module-id.
1763e5dd7070Spatrick ///
1764e5dd7070Spatrick /// module-id:
1765e5dd7070Spatrick /// identifier
1766e5dd7070Spatrick /// identifier '.' module-id
1767e5dd7070Spatrick ///
1768e5dd7070Spatrick /// \returns true if an error occurred, false otherwise.
parseModuleId(ModuleId & Id)1769e5dd7070Spatrick bool ModuleMapParser::parseModuleId(ModuleId &Id) {
1770e5dd7070Spatrick Id.clear();
1771e5dd7070Spatrick do {
1772e5dd7070Spatrick if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1773ec727ea7Spatrick Id.push_back(
1774ec727ea7Spatrick std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
1775e5dd7070Spatrick consumeToken();
1776e5dd7070Spatrick } else {
1777e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1778e5dd7070Spatrick return true;
1779e5dd7070Spatrick }
1780e5dd7070Spatrick
1781e5dd7070Spatrick if (!Tok.is(MMToken::Period))
1782e5dd7070Spatrick break;
1783e5dd7070Spatrick
1784e5dd7070Spatrick consumeToken();
1785e5dd7070Spatrick } while (true);
1786e5dd7070Spatrick
1787e5dd7070Spatrick return false;
1788e5dd7070Spatrick }
1789e5dd7070Spatrick
1790e5dd7070Spatrick namespace {
1791e5dd7070Spatrick
1792e5dd7070Spatrick /// Enumerates the known attributes.
1793e5dd7070Spatrick enum AttributeKind {
1794e5dd7070Spatrick /// An unknown attribute.
1795e5dd7070Spatrick AT_unknown,
1796e5dd7070Spatrick
1797e5dd7070Spatrick /// The 'system' attribute.
1798e5dd7070Spatrick AT_system,
1799e5dd7070Spatrick
1800e5dd7070Spatrick /// The 'extern_c' attribute.
1801e5dd7070Spatrick AT_extern_c,
1802e5dd7070Spatrick
1803e5dd7070Spatrick /// The 'exhaustive' attribute.
1804e5dd7070Spatrick AT_exhaustive,
1805e5dd7070Spatrick
1806e5dd7070Spatrick /// The 'no_undeclared_includes' attribute.
1807e5dd7070Spatrick AT_no_undeclared_includes
1808e5dd7070Spatrick };
1809e5dd7070Spatrick
1810e5dd7070Spatrick } // namespace
1811e5dd7070Spatrick
1812e5dd7070Spatrick /// Private modules are canonicalized as Foo_Private. Clang provides extra
1813e5dd7070Spatrick /// module map search logic to find the appropriate private module when PCH
1814e5dd7070Spatrick /// is used with implicit module maps. Warn when private modules are written
1815e5dd7070Spatrick /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
diagnosePrivateModules(SourceLocation ExplicitLoc,SourceLocation FrameworkLoc)1816e5dd7070Spatrick void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
1817e5dd7070Spatrick SourceLocation FrameworkLoc) {
1818e5dd7070Spatrick auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
1819e5dd7070Spatrick const Module *M, SourceRange ReplLoc) {
1820e5dd7070Spatrick auto D = Diags.Report(ActiveModule->DefinitionLoc,
1821e5dd7070Spatrick diag::note_mmap_rename_top_level_private_module);
1822e5dd7070Spatrick D << BadName << M->Name;
1823e5dd7070Spatrick D << FixItHint::CreateReplacement(ReplLoc, Canonical);
1824e5dd7070Spatrick };
1825e5dd7070Spatrick
1826e5dd7070Spatrick for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
1827e5dd7070Spatrick auto const *M = E->getValue();
1828e5dd7070Spatrick if (M->Directory != ActiveModule->Directory)
1829e5dd7070Spatrick continue;
1830e5dd7070Spatrick
1831e5dd7070Spatrick SmallString<128> FullName(ActiveModule->getFullModuleName());
1832e5dd7070Spatrick if (!FullName.startswith(M->Name) && !FullName.endswith("Private"))
1833e5dd7070Spatrick continue;
1834e5dd7070Spatrick SmallString<128> FixedPrivModDecl;
1835e5dd7070Spatrick SmallString<128> Canonical(M->Name);
1836e5dd7070Spatrick Canonical.append("_Private");
1837e5dd7070Spatrick
1838e5dd7070Spatrick // Foo.Private -> Foo_Private
1839e5dd7070Spatrick if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
1840e5dd7070Spatrick M->Name == ActiveModule->Parent->Name) {
1841e5dd7070Spatrick Diags.Report(ActiveModule->DefinitionLoc,
1842e5dd7070Spatrick diag::warn_mmap_mismatched_private_submodule)
1843e5dd7070Spatrick << FullName;
1844e5dd7070Spatrick
1845e5dd7070Spatrick SourceLocation FixItInitBegin = CurrModuleDeclLoc;
1846e5dd7070Spatrick if (FrameworkLoc.isValid())
1847e5dd7070Spatrick FixItInitBegin = FrameworkLoc;
1848e5dd7070Spatrick if (ExplicitLoc.isValid())
1849e5dd7070Spatrick FixItInitBegin = ExplicitLoc;
1850e5dd7070Spatrick
1851e5dd7070Spatrick if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
1852e5dd7070Spatrick FixedPrivModDecl.append("framework ");
1853e5dd7070Spatrick FixedPrivModDecl.append("module ");
1854e5dd7070Spatrick FixedPrivModDecl.append(Canonical);
1855e5dd7070Spatrick
1856e5dd7070Spatrick GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
1857e5dd7070Spatrick SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
1858e5dd7070Spatrick continue;
1859e5dd7070Spatrick }
1860e5dd7070Spatrick
1861e5dd7070Spatrick // FooPrivate and whatnots -> Foo_Private
1862e5dd7070Spatrick if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
1863e5dd7070Spatrick ActiveModule->Name != Canonical) {
1864e5dd7070Spatrick Diags.Report(ActiveModule->DefinitionLoc,
1865e5dd7070Spatrick diag::warn_mmap_mismatched_private_module_name)
1866e5dd7070Spatrick << ActiveModule->Name;
1867e5dd7070Spatrick GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
1868e5dd7070Spatrick SourceRange(ActiveModule->DefinitionLoc));
1869e5dd7070Spatrick }
1870e5dd7070Spatrick }
1871e5dd7070Spatrick }
1872e5dd7070Spatrick
1873e5dd7070Spatrick /// Parse a module declaration.
1874e5dd7070Spatrick ///
1875e5dd7070Spatrick /// module-declaration:
1876e5dd7070Spatrick /// 'extern' 'module' module-id string-literal
1877e5dd7070Spatrick /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1878e5dd7070Spatrick /// { module-member* }
1879e5dd7070Spatrick ///
1880e5dd7070Spatrick /// module-member:
1881e5dd7070Spatrick /// requires-declaration
1882e5dd7070Spatrick /// header-declaration
1883e5dd7070Spatrick /// submodule-declaration
1884e5dd7070Spatrick /// export-declaration
1885e5dd7070Spatrick /// export-as-declaration
1886e5dd7070Spatrick /// link-declaration
1887e5dd7070Spatrick ///
1888e5dd7070Spatrick /// submodule-declaration:
1889e5dd7070Spatrick /// module-declaration
1890e5dd7070Spatrick /// inferred-submodule-declaration
parseModuleDecl()1891e5dd7070Spatrick void ModuleMapParser::parseModuleDecl() {
1892e5dd7070Spatrick assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
1893e5dd7070Spatrick Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
1894e5dd7070Spatrick if (Tok.is(MMToken::ExternKeyword)) {
1895e5dd7070Spatrick parseExternModuleDecl();
1896e5dd7070Spatrick return;
1897e5dd7070Spatrick }
1898e5dd7070Spatrick
1899e5dd7070Spatrick // Parse 'explicit' or 'framework' keyword, if present.
1900e5dd7070Spatrick SourceLocation ExplicitLoc;
1901e5dd7070Spatrick SourceLocation FrameworkLoc;
1902e5dd7070Spatrick bool Explicit = false;
1903e5dd7070Spatrick bool Framework = false;
1904e5dd7070Spatrick
1905e5dd7070Spatrick // Parse 'explicit' keyword, if present.
1906e5dd7070Spatrick if (Tok.is(MMToken::ExplicitKeyword)) {
1907e5dd7070Spatrick ExplicitLoc = consumeToken();
1908e5dd7070Spatrick Explicit = true;
1909e5dd7070Spatrick }
1910e5dd7070Spatrick
1911e5dd7070Spatrick // Parse 'framework' keyword, if present.
1912e5dd7070Spatrick if (Tok.is(MMToken::FrameworkKeyword)) {
1913e5dd7070Spatrick FrameworkLoc = consumeToken();
1914e5dd7070Spatrick Framework = true;
1915e5dd7070Spatrick }
1916e5dd7070Spatrick
1917e5dd7070Spatrick // Parse 'module' keyword.
1918e5dd7070Spatrick if (!Tok.is(MMToken::ModuleKeyword)) {
1919e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1920e5dd7070Spatrick consumeToken();
1921e5dd7070Spatrick HadError = true;
1922e5dd7070Spatrick return;
1923e5dd7070Spatrick }
1924e5dd7070Spatrick CurrModuleDeclLoc = consumeToken(); // 'module' keyword
1925e5dd7070Spatrick
1926e5dd7070Spatrick // If we have a wildcard for the module name, this is an inferred submodule.
1927e5dd7070Spatrick // Parse it.
1928e5dd7070Spatrick if (Tok.is(MMToken::Star))
1929e5dd7070Spatrick return parseInferredModuleDecl(Framework, Explicit);
1930e5dd7070Spatrick
1931e5dd7070Spatrick // Parse the module name.
1932e5dd7070Spatrick ModuleId Id;
1933e5dd7070Spatrick if (parseModuleId(Id)) {
1934e5dd7070Spatrick HadError = true;
1935e5dd7070Spatrick return;
1936e5dd7070Spatrick }
1937e5dd7070Spatrick
1938e5dd7070Spatrick if (ActiveModule) {
1939e5dd7070Spatrick if (Id.size() > 1) {
1940e5dd7070Spatrick Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1941e5dd7070Spatrick << SourceRange(Id.front().second, Id.back().second);
1942e5dd7070Spatrick
1943e5dd7070Spatrick HadError = true;
1944e5dd7070Spatrick return;
1945e5dd7070Spatrick }
1946e5dd7070Spatrick } else if (Id.size() == 1 && Explicit) {
1947e5dd7070Spatrick // Top-level modules can't be explicit.
1948e5dd7070Spatrick Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1949e5dd7070Spatrick Explicit = false;
1950e5dd7070Spatrick ExplicitLoc = SourceLocation();
1951e5dd7070Spatrick HadError = true;
1952e5dd7070Spatrick }
1953e5dd7070Spatrick
1954e5dd7070Spatrick Module *PreviousActiveModule = ActiveModule;
1955e5dd7070Spatrick if (Id.size() > 1) {
1956e5dd7070Spatrick // This module map defines a submodule. Go find the module of which it
1957e5dd7070Spatrick // is a submodule.
1958e5dd7070Spatrick ActiveModule = nullptr;
1959e5dd7070Spatrick const Module *TopLevelModule = nullptr;
1960e5dd7070Spatrick for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1961e5dd7070Spatrick if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
1962e5dd7070Spatrick if (I == 0)
1963e5dd7070Spatrick TopLevelModule = Next;
1964e5dd7070Spatrick ActiveModule = Next;
1965e5dd7070Spatrick continue;
1966e5dd7070Spatrick }
1967e5dd7070Spatrick
1968a9ac8606Spatrick Diags.Report(Id[I].second, diag::err_mmap_missing_parent_module)
1969a9ac8606Spatrick << Id[I].first << (ActiveModule != nullptr)
1970a9ac8606Spatrick << (ActiveModule
1971a9ac8606Spatrick ? ActiveModule->getTopLevelModule()->getFullModuleName()
1972a9ac8606Spatrick : "");
1973e5dd7070Spatrick HadError = true;
1974e5dd7070Spatrick }
1975e5dd7070Spatrick
1976a9ac8606Spatrick if (TopLevelModule &&
1977a9ac8606Spatrick ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
1978e5dd7070Spatrick assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
1979e5dd7070Spatrick "submodule defined in same file as 'module *' that allowed its "
1980e5dd7070Spatrick "top-level module");
1981e5dd7070Spatrick Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
1982e5dd7070Spatrick }
1983e5dd7070Spatrick }
1984e5dd7070Spatrick
1985e5dd7070Spatrick StringRef ModuleName = Id.back().first;
1986e5dd7070Spatrick SourceLocation ModuleNameLoc = Id.back().second;
1987e5dd7070Spatrick
1988e5dd7070Spatrick // Parse the optional attribute list.
1989e5dd7070Spatrick Attributes Attrs;
1990e5dd7070Spatrick if (parseOptionalAttributes(Attrs))
1991e5dd7070Spatrick return;
1992e5dd7070Spatrick
1993e5dd7070Spatrick // Parse the opening brace.
1994e5dd7070Spatrick if (!Tok.is(MMToken::LBrace)) {
1995e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1996e5dd7070Spatrick << ModuleName;
1997e5dd7070Spatrick HadError = true;
1998e5dd7070Spatrick return;
1999e5dd7070Spatrick }
2000e5dd7070Spatrick SourceLocation LBraceLoc = consumeToken();
2001e5dd7070Spatrick
2002e5dd7070Spatrick // Determine whether this (sub)module has already been defined.
2003e5dd7070Spatrick Module *ShadowingModule = nullptr;
2004e5dd7070Spatrick if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
2005e5dd7070Spatrick // We might see a (re)definition of a module that we already have a
2006e5dd7070Spatrick // definition for in two cases:
2007e5dd7070Spatrick // - If we loaded one definition from an AST file and we've just found a
2008e5dd7070Spatrick // corresponding definition in a module map file, or
2009e5dd7070Spatrick bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
2010e5dd7070Spatrick // - If we're building a (preprocessed) module and we've just loaded the
2011e5dd7070Spatrick // module map file from which it was created.
2012e5dd7070Spatrick bool ParsedAsMainInput =
2013e5dd7070Spatrick Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
2014e5dd7070Spatrick Map.LangOpts.CurrentModule == ModuleName &&
2015e5dd7070Spatrick SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
2016e5dd7070Spatrick SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
2017e5dd7070Spatrick if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
2018e5dd7070Spatrick // Skip the module definition.
2019e5dd7070Spatrick skipUntil(MMToken::RBrace);
2020e5dd7070Spatrick if (Tok.is(MMToken::RBrace))
2021e5dd7070Spatrick consumeToken();
2022e5dd7070Spatrick else {
2023e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2024e5dd7070Spatrick Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2025e5dd7070Spatrick HadError = true;
2026e5dd7070Spatrick }
2027e5dd7070Spatrick return;
2028e5dd7070Spatrick }
2029e5dd7070Spatrick
2030e5dd7070Spatrick if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
2031e5dd7070Spatrick ShadowingModule = Existing;
2032e5dd7070Spatrick } else {
2033e5dd7070Spatrick // This is not a shawdowed module decl, it is an illegal redefinition.
2034e5dd7070Spatrick Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
2035e5dd7070Spatrick << ModuleName;
2036e5dd7070Spatrick Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
2037e5dd7070Spatrick
2038e5dd7070Spatrick // Skip the module definition.
2039e5dd7070Spatrick skipUntil(MMToken::RBrace);
2040e5dd7070Spatrick if (Tok.is(MMToken::RBrace))
2041e5dd7070Spatrick consumeToken();
2042e5dd7070Spatrick
2043e5dd7070Spatrick HadError = true;
2044e5dd7070Spatrick return;
2045e5dd7070Spatrick }
2046e5dd7070Spatrick }
2047e5dd7070Spatrick
2048e5dd7070Spatrick // Start defining this module.
2049e5dd7070Spatrick if (ShadowingModule) {
2050e5dd7070Spatrick ActiveModule =
2051e5dd7070Spatrick Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
2052e5dd7070Spatrick } else {
2053e5dd7070Spatrick ActiveModule =
2054e5dd7070Spatrick Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
2055e5dd7070Spatrick .first;
2056e5dd7070Spatrick }
2057e5dd7070Spatrick
2058e5dd7070Spatrick ActiveModule->DefinitionLoc = ModuleNameLoc;
2059e5dd7070Spatrick if (Attrs.IsSystem || IsSystem)
2060e5dd7070Spatrick ActiveModule->IsSystem = true;
2061e5dd7070Spatrick if (Attrs.IsExternC)
2062e5dd7070Spatrick ActiveModule->IsExternC = true;
2063*12c85518Srobert if (Attrs.NoUndeclaredIncludes)
2064e5dd7070Spatrick ActiveModule->NoUndeclaredIncludes = true;
2065e5dd7070Spatrick ActiveModule->Directory = Directory;
2066e5dd7070Spatrick
2067e5dd7070Spatrick StringRef MapFileName(ModuleMapFile->getName());
2068e5dd7070Spatrick if (MapFileName.endswith("module.private.modulemap") ||
2069e5dd7070Spatrick MapFileName.endswith("module_private.map")) {
2070e5dd7070Spatrick ActiveModule->ModuleMapIsPrivate = true;
2071e5dd7070Spatrick }
2072e5dd7070Spatrick
2073e5dd7070Spatrick // Private modules named as FooPrivate, Foo.Private or similar are likely a
2074e5dd7070Spatrick // user error; provide warnings, notes and fixits to direct users to use
2075e5dd7070Spatrick // Foo_Private instead.
2076e5dd7070Spatrick SourceLocation StartLoc =
2077e5dd7070Spatrick SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
2078e5dd7070Spatrick if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
2079e5dd7070Spatrick !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
2080e5dd7070Spatrick StartLoc) &&
2081e5dd7070Spatrick !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
2082e5dd7070Spatrick StartLoc) &&
2083e5dd7070Spatrick ActiveModule->ModuleMapIsPrivate)
2084e5dd7070Spatrick diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
2085e5dd7070Spatrick
2086e5dd7070Spatrick bool Done = false;
2087e5dd7070Spatrick do {
2088e5dd7070Spatrick switch (Tok.Kind) {
2089e5dd7070Spatrick case MMToken::EndOfFile:
2090e5dd7070Spatrick case MMToken::RBrace:
2091e5dd7070Spatrick Done = true;
2092e5dd7070Spatrick break;
2093e5dd7070Spatrick
2094e5dd7070Spatrick case MMToken::ConfigMacros:
2095e5dd7070Spatrick parseConfigMacros();
2096e5dd7070Spatrick break;
2097e5dd7070Spatrick
2098e5dd7070Spatrick case MMToken::Conflict:
2099e5dd7070Spatrick parseConflict();
2100e5dd7070Spatrick break;
2101e5dd7070Spatrick
2102e5dd7070Spatrick case MMToken::ExplicitKeyword:
2103e5dd7070Spatrick case MMToken::ExternKeyword:
2104e5dd7070Spatrick case MMToken::FrameworkKeyword:
2105e5dd7070Spatrick case MMToken::ModuleKeyword:
2106e5dd7070Spatrick parseModuleDecl();
2107e5dd7070Spatrick break;
2108e5dd7070Spatrick
2109e5dd7070Spatrick case MMToken::ExportKeyword:
2110e5dd7070Spatrick parseExportDecl();
2111e5dd7070Spatrick break;
2112e5dd7070Spatrick
2113e5dd7070Spatrick case MMToken::ExportAsKeyword:
2114e5dd7070Spatrick parseExportAsDecl();
2115e5dd7070Spatrick break;
2116e5dd7070Spatrick
2117e5dd7070Spatrick case MMToken::UseKeyword:
2118e5dd7070Spatrick parseUseDecl();
2119e5dd7070Spatrick break;
2120e5dd7070Spatrick
2121e5dd7070Spatrick case MMToken::RequiresKeyword:
2122e5dd7070Spatrick parseRequiresDecl();
2123e5dd7070Spatrick break;
2124e5dd7070Spatrick
2125e5dd7070Spatrick case MMToken::TextualKeyword:
2126e5dd7070Spatrick parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
2127e5dd7070Spatrick break;
2128e5dd7070Spatrick
2129e5dd7070Spatrick case MMToken::UmbrellaKeyword: {
2130e5dd7070Spatrick SourceLocation UmbrellaLoc = consumeToken();
2131e5dd7070Spatrick if (Tok.is(MMToken::HeaderKeyword))
2132e5dd7070Spatrick parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
2133e5dd7070Spatrick else
2134e5dd7070Spatrick parseUmbrellaDirDecl(UmbrellaLoc);
2135e5dd7070Spatrick break;
2136e5dd7070Spatrick }
2137e5dd7070Spatrick
2138e5dd7070Spatrick case MMToken::ExcludeKeyword:
2139e5dd7070Spatrick parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
2140e5dd7070Spatrick break;
2141e5dd7070Spatrick
2142e5dd7070Spatrick case MMToken::PrivateKeyword:
2143e5dd7070Spatrick parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
2144e5dd7070Spatrick break;
2145e5dd7070Spatrick
2146e5dd7070Spatrick case MMToken::HeaderKeyword:
2147e5dd7070Spatrick parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
2148e5dd7070Spatrick break;
2149e5dd7070Spatrick
2150e5dd7070Spatrick case MMToken::LinkKeyword:
2151e5dd7070Spatrick parseLinkDecl();
2152e5dd7070Spatrick break;
2153e5dd7070Spatrick
2154e5dd7070Spatrick default:
2155e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
2156e5dd7070Spatrick consumeToken();
2157e5dd7070Spatrick break;
2158e5dd7070Spatrick }
2159e5dd7070Spatrick } while (!Done);
2160e5dd7070Spatrick
2161e5dd7070Spatrick if (Tok.is(MMToken::RBrace))
2162e5dd7070Spatrick consumeToken();
2163e5dd7070Spatrick else {
2164e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2165e5dd7070Spatrick Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2166e5dd7070Spatrick HadError = true;
2167e5dd7070Spatrick }
2168e5dd7070Spatrick
2169e5dd7070Spatrick // If the active module is a top-level framework, and there are no link
2170e5dd7070Spatrick // libraries, automatically link against the framework.
2171e5dd7070Spatrick if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
2172e5dd7070Spatrick ActiveModule->LinkLibraries.empty()) {
2173e5dd7070Spatrick inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
2174e5dd7070Spatrick }
2175e5dd7070Spatrick
2176e5dd7070Spatrick // If the module meets all requirements but is still unavailable, mark the
2177e5dd7070Spatrick // whole tree as unavailable to prevent it from building.
2178ec727ea7Spatrick if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
2179e5dd7070Spatrick ActiveModule->Parent) {
2180ec727ea7Spatrick ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false);
2181e5dd7070Spatrick ActiveModule->getTopLevelModule()->MissingHeaders.append(
2182e5dd7070Spatrick ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
2183e5dd7070Spatrick }
2184e5dd7070Spatrick
2185e5dd7070Spatrick // We're done parsing this module. Pop back to the previous module.
2186e5dd7070Spatrick ActiveModule = PreviousActiveModule;
2187e5dd7070Spatrick }
2188e5dd7070Spatrick
2189e5dd7070Spatrick /// Parse an extern module declaration.
2190e5dd7070Spatrick ///
2191e5dd7070Spatrick /// extern module-declaration:
2192e5dd7070Spatrick /// 'extern' 'module' module-id string-literal
parseExternModuleDecl()2193e5dd7070Spatrick void ModuleMapParser::parseExternModuleDecl() {
2194e5dd7070Spatrick assert(Tok.is(MMToken::ExternKeyword));
2195e5dd7070Spatrick SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
2196e5dd7070Spatrick
2197e5dd7070Spatrick // Parse 'module' keyword.
2198e5dd7070Spatrick if (!Tok.is(MMToken::ModuleKeyword)) {
2199e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
2200e5dd7070Spatrick consumeToken();
2201e5dd7070Spatrick HadError = true;
2202e5dd7070Spatrick return;
2203e5dd7070Spatrick }
2204e5dd7070Spatrick consumeToken(); // 'module' keyword
2205e5dd7070Spatrick
2206e5dd7070Spatrick // Parse the module name.
2207e5dd7070Spatrick ModuleId Id;
2208e5dd7070Spatrick if (parseModuleId(Id)) {
2209e5dd7070Spatrick HadError = true;
2210e5dd7070Spatrick return;
2211e5dd7070Spatrick }
2212e5dd7070Spatrick
2213e5dd7070Spatrick // Parse the referenced module map file name.
2214e5dd7070Spatrick if (!Tok.is(MMToken::StringLiteral)) {
2215e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
2216e5dd7070Spatrick HadError = true;
2217e5dd7070Spatrick return;
2218e5dd7070Spatrick }
2219ec727ea7Spatrick std::string FileName = std::string(Tok.getString());
2220e5dd7070Spatrick consumeToken(); // filename
2221e5dd7070Spatrick
2222e5dd7070Spatrick StringRef FileNameRef = FileName;
2223e5dd7070Spatrick SmallString<128> ModuleMapFileName;
2224e5dd7070Spatrick if (llvm::sys::path::is_relative(FileNameRef)) {
2225e5dd7070Spatrick ModuleMapFileName += Directory->getName();
2226e5dd7070Spatrick llvm::sys::path::append(ModuleMapFileName, FileName);
2227e5dd7070Spatrick FileNameRef = ModuleMapFileName;
2228e5dd7070Spatrick }
2229e5dd7070Spatrick if (auto File = SourceMgr.getFileManager().getFile(FileNameRef))
2230e5dd7070Spatrick Map.parseModuleMapFile(
2231*12c85518Srobert *File, IsSystem,
2232e5dd7070Spatrick Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
2233e5dd7070Spatrick ? Directory
2234e5dd7070Spatrick : (*File)->getDir(),
2235e5dd7070Spatrick FileID(), nullptr, ExternLoc);
2236e5dd7070Spatrick }
2237e5dd7070Spatrick
2238e5dd7070Spatrick /// Whether to add the requirement \p Feature to the module \p M.
2239e5dd7070Spatrick ///
2240e5dd7070Spatrick /// This preserves backwards compatibility for two hacks in the Darwin system
2241e5dd7070Spatrick /// module map files:
2242e5dd7070Spatrick ///
2243e5dd7070Spatrick /// 1. The use of 'requires excluded' to make headers non-modular, which
2244e5dd7070Spatrick /// should really be mapped to 'textual' now that we have this feature. We
2245e5dd7070Spatrick /// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
2246e5dd7070Spatrick /// true. Later, this bit will be used to map all the headers inside this
2247e5dd7070Spatrick /// module to 'textual'.
2248e5dd7070Spatrick ///
2249e5dd7070Spatrick /// This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
2250e5dd7070Spatrick ///
2251e5dd7070Spatrick /// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement
2252e5dd7070Spatrick /// was never correct and causes issues now that we check it, so drop it.
shouldAddRequirement(Module * M,StringRef Feature,bool & IsRequiresExcludedHack)2253e5dd7070Spatrick static bool shouldAddRequirement(Module *M, StringRef Feature,
2254e5dd7070Spatrick bool &IsRequiresExcludedHack) {
2255e5dd7070Spatrick if (Feature == "excluded" &&
2256e5dd7070Spatrick (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
2257e5dd7070Spatrick M->fullModuleNameIs({"Tcl", "Private"}))) {
2258e5dd7070Spatrick IsRequiresExcludedHack = true;
2259e5dd7070Spatrick return false;
2260e5dd7070Spatrick } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
2261e5dd7070Spatrick return false;
2262e5dd7070Spatrick }
2263e5dd7070Spatrick
2264e5dd7070Spatrick return true;
2265e5dd7070Spatrick }
2266e5dd7070Spatrick
2267e5dd7070Spatrick /// Parse a requires declaration.
2268e5dd7070Spatrick ///
2269e5dd7070Spatrick /// requires-declaration:
2270e5dd7070Spatrick /// 'requires' feature-list
2271e5dd7070Spatrick ///
2272e5dd7070Spatrick /// feature-list:
2273e5dd7070Spatrick /// feature ',' feature-list
2274e5dd7070Spatrick /// feature
2275e5dd7070Spatrick ///
2276e5dd7070Spatrick /// feature:
2277e5dd7070Spatrick /// '!'[opt] identifier
parseRequiresDecl()2278e5dd7070Spatrick void ModuleMapParser::parseRequiresDecl() {
2279e5dd7070Spatrick assert(Tok.is(MMToken::RequiresKeyword));
2280e5dd7070Spatrick
2281e5dd7070Spatrick // Parse 'requires' keyword.
2282e5dd7070Spatrick consumeToken();
2283e5dd7070Spatrick
2284e5dd7070Spatrick // Parse the feature-list.
2285e5dd7070Spatrick do {
2286e5dd7070Spatrick bool RequiredState = true;
2287e5dd7070Spatrick if (Tok.is(MMToken::Exclaim)) {
2288e5dd7070Spatrick RequiredState = false;
2289e5dd7070Spatrick consumeToken();
2290e5dd7070Spatrick }
2291e5dd7070Spatrick
2292e5dd7070Spatrick if (!Tok.is(MMToken::Identifier)) {
2293e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
2294e5dd7070Spatrick HadError = true;
2295e5dd7070Spatrick return;
2296e5dd7070Spatrick }
2297e5dd7070Spatrick
2298e5dd7070Spatrick // Consume the feature name.
2299ec727ea7Spatrick std::string Feature = std::string(Tok.getString());
2300e5dd7070Spatrick consumeToken();
2301e5dd7070Spatrick
2302e5dd7070Spatrick bool IsRequiresExcludedHack = false;
2303e5dd7070Spatrick bool ShouldAddRequirement =
2304e5dd7070Spatrick shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
2305e5dd7070Spatrick
2306e5dd7070Spatrick if (IsRequiresExcludedHack)
2307e5dd7070Spatrick UsesRequiresExcludedHack.insert(ActiveModule);
2308e5dd7070Spatrick
2309e5dd7070Spatrick if (ShouldAddRequirement) {
2310e5dd7070Spatrick // Add this feature.
2311e5dd7070Spatrick ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
2312e5dd7070Spatrick *Map.Target);
2313e5dd7070Spatrick }
2314e5dd7070Spatrick
2315e5dd7070Spatrick if (!Tok.is(MMToken::Comma))
2316e5dd7070Spatrick break;
2317e5dd7070Spatrick
2318e5dd7070Spatrick // Consume the comma.
2319e5dd7070Spatrick consumeToken();
2320e5dd7070Spatrick } while (true);
2321e5dd7070Spatrick }
2322e5dd7070Spatrick
2323e5dd7070Spatrick /// Parse a header declaration.
2324e5dd7070Spatrick ///
2325e5dd7070Spatrick /// header-declaration:
2326e5dd7070Spatrick /// 'textual'[opt] 'header' string-literal
2327e5dd7070Spatrick /// 'private' 'textual'[opt] 'header' string-literal
2328e5dd7070Spatrick /// 'exclude' 'header' string-literal
2329e5dd7070Spatrick /// 'umbrella' 'header' string-literal
2330e5dd7070Spatrick ///
2331e5dd7070Spatrick /// FIXME: Support 'private textual header'.
parseHeaderDecl(MMToken::TokenKind LeadingToken,SourceLocation LeadingLoc)2332e5dd7070Spatrick void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
2333e5dd7070Spatrick SourceLocation LeadingLoc) {
2334e5dd7070Spatrick // We've already consumed the first token.
2335e5dd7070Spatrick ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
2336*12c85518Srobert
2337e5dd7070Spatrick if (LeadingToken == MMToken::PrivateKeyword) {
2338e5dd7070Spatrick Role = ModuleMap::PrivateHeader;
2339e5dd7070Spatrick // 'private' may optionally be followed by 'textual'.
2340e5dd7070Spatrick if (Tok.is(MMToken::TextualKeyword)) {
2341e5dd7070Spatrick LeadingToken = Tok.Kind;
2342e5dd7070Spatrick consumeToken();
2343e5dd7070Spatrick }
2344*12c85518Srobert } else if (LeadingToken == MMToken::ExcludeKeyword) {
2345*12c85518Srobert Role = ModuleMap::ExcludedHeader;
2346e5dd7070Spatrick }
2347e5dd7070Spatrick
2348e5dd7070Spatrick if (LeadingToken == MMToken::TextualKeyword)
2349e5dd7070Spatrick Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
2350e5dd7070Spatrick
2351e5dd7070Spatrick if (UsesRequiresExcludedHack.count(ActiveModule)) {
2352e5dd7070Spatrick // Mark this header 'textual' (see doc comment for
2353e5dd7070Spatrick // Module::UsesRequiresExcludedHack).
2354e5dd7070Spatrick Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
2355e5dd7070Spatrick }
2356e5dd7070Spatrick
2357e5dd7070Spatrick if (LeadingToken != MMToken::HeaderKeyword) {
2358e5dd7070Spatrick if (!Tok.is(MMToken::HeaderKeyword)) {
2359e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2360e5dd7070Spatrick << (LeadingToken == MMToken::PrivateKeyword ? "private" :
2361e5dd7070Spatrick LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
2362e5dd7070Spatrick LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
2363e5dd7070Spatrick return;
2364e5dd7070Spatrick }
2365e5dd7070Spatrick consumeToken();
2366e5dd7070Spatrick }
2367e5dd7070Spatrick
2368e5dd7070Spatrick // Parse the header name.
2369e5dd7070Spatrick if (!Tok.is(MMToken::StringLiteral)) {
2370e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2371e5dd7070Spatrick << "header";
2372e5dd7070Spatrick HadError = true;
2373e5dd7070Spatrick return;
2374e5dd7070Spatrick }
2375e5dd7070Spatrick Module::UnresolvedHeaderDirective Header;
2376ec727ea7Spatrick Header.FileName = std::string(Tok.getString());
2377e5dd7070Spatrick Header.FileNameLoc = consumeToken();
2378e5dd7070Spatrick Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
2379*12c85518Srobert Header.Kind = Map.headerRoleToKind(Role);
2380e5dd7070Spatrick
2381e5dd7070Spatrick // Check whether we already have an umbrella.
2382e5dd7070Spatrick if (Header.IsUmbrella && ActiveModule->Umbrella) {
2383e5dd7070Spatrick Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2384e5dd7070Spatrick << ActiveModule->getFullModuleName();
2385e5dd7070Spatrick HadError = true;
2386e5dd7070Spatrick return;
2387e5dd7070Spatrick }
2388e5dd7070Spatrick
2389e5dd7070Spatrick // If we were given stat information, parse it so we can skip looking for
2390e5dd7070Spatrick // the file.
2391e5dd7070Spatrick if (Tok.is(MMToken::LBrace)) {
2392e5dd7070Spatrick SourceLocation LBraceLoc = consumeToken();
2393e5dd7070Spatrick
2394e5dd7070Spatrick while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
2395e5dd7070Spatrick enum Attribute { Size, ModTime, Unknown };
2396e5dd7070Spatrick StringRef Str = Tok.getString();
2397e5dd7070Spatrick SourceLocation Loc = consumeToken();
2398e5dd7070Spatrick switch (llvm::StringSwitch<Attribute>(Str)
2399e5dd7070Spatrick .Case("size", Size)
2400e5dd7070Spatrick .Case("mtime", ModTime)
2401e5dd7070Spatrick .Default(Unknown)) {
2402e5dd7070Spatrick case Size:
2403e5dd7070Spatrick if (Header.Size)
2404e5dd7070Spatrick Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2405e5dd7070Spatrick if (!Tok.is(MMToken::IntegerLiteral)) {
2406e5dd7070Spatrick Diags.Report(Tok.getLocation(),
2407e5dd7070Spatrick diag::err_mmap_invalid_header_attribute_value) << Str;
2408e5dd7070Spatrick skipUntil(MMToken::RBrace);
2409e5dd7070Spatrick break;
2410e5dd7070Spatrick }
2411e5dd7070Spatrick Header.Size = Tok.getInteger();
2412e5dd7070Spatrick consumeToken();
2413e5dd7070Spatrick break;
2414e5dd7070Spatrick
2415e5dd7070Spatrick case ModTime:
2416e5dd7070Spatrick if (Header.ModTime)
2417e5dd7070Spatrick Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2418e5dd7070Spatrick if (!Tok.is(MMToken::IntegerLiteral)) {
2419e5dd7070Spatrick Diags.Report(Tok.getLocation(),
2420e5dd7070Spatrick diag::err_mmap_invalid_header_attribute_value) << Str;
2421e5dd7070Spatrick skipUntil(MMToken::RBrace);
2422e5dd7070Spatrick break;
2423e5dd7070Spatrick }
2424e5dd7070Spatrick Header.ModTime = Tok.getInteger();
2425e5dd7070Spatrick consumeToken();
2426e5dd7070Spatrick break;
2427e5dd7070Spatrick
2428e5dd7070Spatrick case Unknown:
2429e5dd7070Spatrick Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
2430e5dd7070Spatrick skipUntil(MMToken::RBrace);
2431e5dd7070Spatrick break;
2432e5dd7070Spatrick }
2433e5dd7070Spatrick }
2434e5dd7070Spatrick
2435e5dd7070Spatrick if (Tok.is(MMToken::RBrace))
2436e5dd7070Spatrick consumeToken();
2437e5dd7070Spatrick else {
2438e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2439e5dd7070Spatrick Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2440e5dd7070Spatrick HadError = true;
2441e5dd7070Spatrick }
2442e5dd7070Spatrick }
2443e5dd7070Spatrick
2444e5dd7070Spatrick bool NeedsFramework = false;
2445e5dd7070Spatrick Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
2446e5dd7070Spatrick
2447e5dd7070Spatrick if (NeedsFramework && ActiveModule)
2448e5dd7070Spatrick Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
2449e5dd7070Spatrick << ActiveModule->getFullModuleName()
2450e5dd7070Spatrick << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
2451e5dd7070Spatrick }
2452e5dd7070Spatrick
compareModuleHeaders(const Module::Header * A,const Module::Header * B)2453e5dd7070Spatrick static int compareModuleHeaders(const Module::Header *A,
2454e5dd7070Spatrick const Module::Header *B) {
2455e5dd7070Spatrick return A->NameAsWritten.compare(B->NameAsWritten);
2456e5dd7070Spatrick }
2457e5dd7070Spatrick
2458e5dd7070Spatrick /// Parse an umbrella directory declaration.
2459e5dd7070Spatrick ///
2460e5dd7070Spatrick /// umbrella-dir-declaration:
2461e5dd7070Spatrick /// umbrella string-literal
parseUmbrellaDirDecl(SourceLocation UmbrellaLoc)2462e5dd7070Spatrick void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
2463e5dd7070Spatrick // Parse the directory name.
2464e5dd7070Spatrick if (!Tok.is(MMToken::StringLiteral)) {
2465e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2466e5dd7070Spatrick << "umbrella";
2467e5dd7070Spatrick HadError = true;
2468e5dd7070Spatrick return;
2469e5dd7070Spatrick }
2470e5dd7070Spatrick
2471ec727ea7Spatrick std::string DirName = std::string(Tok.getString());
2472a9ac8606Spatrick std::string DirNameAsWritten = DirName;
2473e5dd7070Spatrick SourceLocation DirNameLoc = consumeToken();
2474e5dd7070Spatrick
2475e5dd7070Spatrick // Check whether we already have an umbrella.
2476e5dd7070Spatrick if (ActiveModule->Umbrella) {
2477e5dd7070Spatrick Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
2478e5dd7070Spatrick << ActiveModule->getFullModuleName();
2479e5dd7070Spatrick HadError = true;
2480e5dd7070Spatrick return;
2481e5dd7070Spatrick }
2482e5dd7070Spatrick
2483e5dd7070Spatrick // Look for this file.
2484e5dd7070Spatrick const DirectoryEntry *Dir = nullptr;
2485e5dd7070Spatrick if (llvm::sys::path::is_absolute(DirName)) {
2486e5dd7070Spatrick if (auto D = SourceMgr.getFileManager().getDirectory(DirName))
2487e5dd7070Spatrick Dir = *D;
2488e5dd7070Spatrick } else {
2489e5dd7070Spatrick SmallString<128> PathName;
2490e5dd7070Spatrick PathName = Directory->getName();
2491e5dd7070Spatrick llvm::sys::path::append(PathName, DirName);
2492e5dd7070Spatrick if (auto D = SourceMgr.getFileManager().getDirectory(PathName))
2493e5dd7070Spatrick Dir = *D;
2494e5dd7070Spatrick }
2495e5dd7070Spatrick
2496e5dd7070Spatrick if (!Dir) {
2497e5dd7070Spatrick Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
2498e5dd7070Spatrick << DirName;
2499e5dd7070Spatrick return;
2500e5dd7070Spatrick }
2501e5dd7070Spatrick
2502e5dd7070Spatrick if (UsesRequiresExcludedHack.count(ActiveModule)) {
2503e5dd7070Spatrick // Mark this header 'textual' (see doc comment for
2504e5dd7070Spatrick // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
2505e5dd7070Spatrick // directory is relatively expensive, in practice this only applies to the
2506e5dd7070Spatrick // uncommonly used Tcl module on Darwin platforms.
2507e5dd7070Spatrick std::error_code EC;
2508e5dd7070Spatrick SmallVector<Module::Header, 6> Headers;
2509e5dd7070Spatrick llvm::vfs::FileSystem &FS =
2510e5dd7070Spatrick SourceMgr.getFileManager().getVirtualFileSystem();
2511e5dd7070Spatrick for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
2512e5dd7070Spatrick I != E && !EC; I.increment(EC)) {
2513*12c85518Srobert if (auto FE = SourceMgr.getFileManager().getOptionalFileRef(I->path())) {
2514*12c85518Srobert Module::Header Header = {"", std::string(I->path()), FE};
2515e5dd7070Spatrick Headers.push_back(std::move(Header));
2516e5dd7070Spatrick }
2517e5dd7070Spatrick }
2518e5dd7070Spatrick
2519e5dd7070Spatrick // Sort header paths so that the pcm doesn't depend on iteration order.
2520e5dd7070Spatrick llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
2521e5dd7070Spatrick
2522e5dd7070Spatrick for (auto &Header : Headers)
2523e5dd7070Spatrick Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
2524e5dd7070Spatrick return;
2525e5dd7070Spatrick }
2526e5dd7070Spatrick
2527e5dd7070Spatrick if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
2528e5dd7070Spatrick Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
2529e5dd7070Spatrick << OwningModule->getFullModuleName();
2530e5dd7070Spatrick HadError = true;
2531e5dd7070Spatrick return;
2532e5dd7070Spatrick }
2533e5dd7070Spatrick
2534e5dd7070Spatrick // Record this umbrella directory.
2535a9ac8606Spatrick Map.setUmbrellaDir(ActiveModule, Dir, DirNameAsWritten, DirName);
2536e5dd7070Spatrick }
2537e5dd7070Spatrick
2538e5dd7070Spatrick /// Parse a module export declaration.
2539e5dd7070Spatrick ///
2540e5dd7070Spatrick /// export-declaration:
2541e5dd7070Spatrick /// 'export' wildcard-module-id
2542e5dd7070Spatrick ///
2543e5dd7070Spatrick /// wildcard-module-id:
2544e5dd7070Spatrick /// identifier
2545e5dd7070Spatrick /// '*'
2546e5dd7070Spatrick /// identifier '.' wildcard-module-id
parseExportDecl()2547e5dd7070Spatrick void ModuleMapParser::parseExportDecl() {
2548e5dd7070Spatrick assert(Tok.is(MMToken::ExportKeyword));
2549e5dd7070Spatrick SourceLocation ExportLoc = consumeToken();
2550e5dd7070Spatrick
2551e5dd7070Spatrick // Parse the module-id with an optional wildcard at the end.
2552e5dd7070Spatrick ModuleId ParsedModuleId;
2553e5dd7070Spatrick bool Wildcard = false;
2554e5dd7070Spatrick do {
2555e5dd7070Spatrick // FIXME: Support string-literal module names here.
2556e5dd7070Spatrick if (Tok.is(MMToken::Identifier)) {
2557ec727ea7Spatrick ParsedModuleId.push_back(
2558ec727ea7Spatrick std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
2559e5dd7070Spatrick consumeToken();
2560e5dd7070Spatrick
2561e5dd7070Spatrick if (Tok.is(MMToken::Period)) {
2562e5dd7070Spatrick consumeToken();
2563e5dd7070Spatrick continue;
2564e5dd7070Spatrick }
2565e5dd7070Spatrick
2566e5dd7070Spatrick break;
2567e5dd7070Spatrick }
2568e5dd7070Spatrick
2569e5dd7070Spatrick if(Tok.is(MMToken::Star)) {
2570e5dd7070Spatrick Wildcard = true;
2571e5dd7070Spatrick consumeToken();
2572e5dd7070Spatrick break;
2573e5dd7070Spatrick }
2574e5dd7070Spatrick
2575e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
2576e5dd7070Spatrick HadError = true;
2577e5dd7070Spatrick return;
2578e5dd7070Spatrick } while (true);
2579e5dd7070Spatrick
2580e5dd7070Spatrick Module::UnresolvedExportDecl Unresolved = {
2581e5dd7070Spatrick ExportLoc, ParsedModuleId, Wildcard
2582e5dd7070Spatrick };
2583e5dd7070Spatrick ActiveModule->UnresolvedExports.push_back(Unresolved);
2584e5dd7070Spatrick }
2585e5dd7070Spatrick
2586e5dd7070Spatrick /// Parse a module export_as declaration.
2587e5dd7070Spatrick ///
2588e5dd7070Spatrick /// export-as-declaration:
2589e5dd7070Spatrick /// 'export_as' identifier
parseExportAsDecl()2590e5dd7070Spatrick void ModuleMapParser::parseExportAsDecl() {
2591e5dd7070Spatrick assert(Tok.is(MMToken::ExportAsKeyword));
2592e5dd7070Spatrick consumeToken();
2593e5dd7070Spatrick
2594e5dd7070Spatrick if (!Tok.is(MMToken::Identifier)) {
2595e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
2596e5dd7070Spatrick HadError = true;
2597e5dd7070Spatrick return;
2598e5dd7070Spatrick }
2599e5dd7070Spatrick
2600e5dd7070Spatrick if (ActiveModule->Parent) {
2601e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
2602e5dd7070Spatrick consumeToken();
2603e5dd7070Spatrick return;
2604e5dd7070Spatrick }
2605e5dd7070Spatrick
2606e5dd7070Spatrick if (!ActiveModule->ExportAsModule.empty()) {
2607e5dd7070Spatrick if (ActiveModule->ExportAsModule == Tok.getString()) {
2608e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
2609e5dd7070Spatrick << ActiveModule->Name << Tok.getString();
2610e5dd7070Spatrick } else {
2611e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
2612e5dd7070Spatrick << ActiveModule->Name << ActiveModule->ExportAsModule
2613e5dd7070Spatrick << Tok.getString();
2614e5dd7070Spatrick }
2615e5dd7070Spatrick }
2616e5dd7070Spatrick
2617ec727ea7Spatrick ActiveModule->ExportAsModule = std::string(Tok.getString());
2618e5dd7070Spatrick Map.addLinkAsDependency(ActiveModule);
2619e5dd7070Spatrick
2620e5dd7070Spatrick consumeToken();
2621e5dd7070Spatrick }
2622e5dd7070Spatrick
2623e5dd7070Spatrick /// Parse a module use declaration.
2624e5dd7070Spatrick ///
2625e5dd7070Spatrick /// use-declaration:
2626e5dd7070Spatrick /// 'use' wildcard-module-id
parseUseDecl()2627e5dd7070Spatrick void ModuleMapParser::parseUseDecl() {
2628e5dd7070Spatrick assert(Tok.is(MMToken::UseKeyword));
2629e5dd7070Spatrick auto KWLoc = consumeToken();
2630e5dd7070Spatrick // Parse the module-id.
2631e5dd7070Spatrick ModuleId ParsedModuleId;
2632e5dd7070Spatrick parseModuleId(ParsedModuleId);
2633e5dd7070Spatrick
2634e5dd7070Spatrick if (ActiveModule->Parent)
2635e5dd7070Spatrick Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
2636e5dd7070Spatrick else
2637e5dd7070Spatrick ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
2638e5dd7070Spatrick }
2639e5dd7070Spatrick
2640e5dd7070Spatrick /// Parse a link declaration.
2641e5dd7070Spatrick ///
2642e5dd7070Spatrick /// module-declaration:
2643e5dd7070Spatrick /// 'link' 'framework'[opt] string-literal
parseLinkDecl()2644e5dd7070Spatrick void ModuleMapParser::parseLinkDecl() {
2645e5dd7070Spatrick assert(Tok.is(MMToken::LinkKeyword));
2646e5dd7070Spatrick SourceLocation LinkLoc = consumeToken();
2647e5dd7070Spatrick
2648e5dd7070Spatrick // Parse the optional 'framework' keyword.
2649e5dd7070Spatrick bool IsFramework = false;
2650e5dd7070Spatrick if (Tok.is(MMToken::FrameworkKeyword)) {
2651e5dd7070Spatrick consumeToken();
2652e5dd7070Spatrick IsFramework = true;
2653e5dd7070Spatrick }
2654e5dd7070Spatrick
2655e5dd7070Spatrick // Parse the library name
2656e5dd7070Spatrick if (!Tok.is(MMToken::StringLiteral)) {
2657e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
2658e5dd7070Spatrick << IsFramework << SourceRange(LinkLoc);
2659e5dd7070Spatrick HadError = true;
2660e5dd7070Spatrick return;
2661e5dd7070Spatrick }
2662e5dd7070Spatrick
2663ec727ea7Spatrick std::string LibraryName = std::string(Tok.getString());
2664e5dd7070Spatrick consumeToken();
2665e5dd7070Spatrick ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
2666e5dd7070Spatrick IsFramework));
2667e5dd7070Spatrick }
2668e5dd7070Spatrick
2669e5dd7070Spatrick /// Parse a configuration macro declaration.
2670e5dd7070Spatrick ///
2671e5dd7070Spatrick /// module-declaration:
2672e5dd7070Spatrick /// 'config_macros' attributes[opt] config-macro-list?
2673e5dd7070Spatrick ///
2674e5dd7070Spatrick /// config-macro-list:
2675e5dd7070Spatrick /// identifier (',' identifier)?
parseConfigMacros()2676e5dd7070Spatrick void ModuleMapParser::parseConfigMacros() {
2677e5dd7070Spatrick assert(Tok.is(MMToken::ConfigMacros));
2678e5dd7070Spatrick SourceLocation ConfigMacrosLoc = consumeToken();
2679e5dd7070Spatrick
2680e5dd7070Spatrick // Only top-level modules can have configuration macros.
2681e5dd7070Spatrick if (ActiveModule->Parent) {
2682e5dd7070Spatrick Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
2683e5dd7070Spatrick }
2684e5dd7070Spatrick
2685e5dd7070Spatrick // Parse the optional attributes.
2686e5dd7070Spatrick Attributes Attrs;
2687e5dd7070Spatrick if (parseOptionalAttributes(Attrs))
2688e5dd7070Spatrick return;
2689e5dd7070Spatrick
2690e5dd7070Spatrick if (Attrs.IsExhaustive && !ActiveModule->Parent) {
2691e5dd7070Spatrick ActiveModule->ConfigMacrosExhaustive = true;
2692e5dd7070Spatrick }
2693e5dd7070Spatrick
2694e5dd7070Spatrick // If we don't have an identifier, we're done.
2695e5dd7070Spatrick // FIXME: Support macros with the same name as a keyword here.
2696e5dd7070Spatrick if (!Tok.is(MMToken::Identifier))
2697e5dd7070Spatrick return;
2698e5dd7070Spatrick
2699e5dd7070Spatrick // Consume the first identifier.
2700e5dd7070Spatrick if (!ActiveModule->Parent) {
2701e5dd7070Spatrick ActiveModule->ConfigMacros.push_back(Tok.getString().str());
2702e5dd7070Spatrick }
2703e5dd7070Spatrick consumeToken();
2704e5dd7070Spatrick
2705e5dd7070Spatrick do {
2706e5dd7070Spatrick // If there's a comma, consume it.
2707e5dd7070Spatrick if (!Tok.is(MMToken::Comma))
2708e5dd7070Spatrick break;
2709e5dd7070Spatrick consumeToken();
2710e5dd7070Spatrick
2711e5dd7070Spatrick // We expect to see a macro name here.
2712e5dd7070Spatrick // FIXME: Support macros with the same name as a keyword here.
2713e5dd7070Spatrick if (!Tok.is(MMToken::Identifier)) {
2714e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
2715e5dd7070Spatrick break;
2716e5dd7070Spatrick }
2717e5dd7070Spatrick
2718e5dd7070Spatrick // Consume the macro name.
2719e5dd7070Spatrick if (!ActiveModule->Parent) {
2720e5dd7070Spatrick ActiveModule->ConfigMacros.push_back(Tok.getString().str());
2721e5dd7070Spatrick }
2722e5dd7070Spatrick consumeToken();
2723e5dd7070Spatrick } while (true);
2724e5dd7070Spatrick }
2725e5dd7070Spatrick
2726e5dd7070Spatrick /// Format a module-id into a string.
formatModuleId(const ModuleId & Id)2727e5dd7070Spatrick static std::string formatModuleId(const ModuleId &Id) {
2728e5dd7070Spatrick std::string result;
2729e5dd7070Spatrick {
2730e5dd7070Spatrick llvm::raw_string_ostream OS(result);
2731e5dd7070Spatrick
2732e5dd7070Spatrick for (unsigned I = 0, N = Id.size(); I != N; ++I) {
2733e5dd7070Spatrick if (I)
2734e5dd7070Spatrick OS << ".";
2735e5dd7070Spatrick OS << Id[I].first;
2736e5dd7070Spatrick }
2737e5dd7070Spatrick }
2738e5dd7070Spatrick
2739e5dd7070Spatrick return result;
2740e5dd7070Spatrick }
2741e5dd7070Spatrick
2742e5dd7070Spatrick /// Parse a conflict declaration.
2743e5dd7070Spatrick ///
2744e5dd7070Spatrick /// module-declaration:
2745e5dd7070Spatrick /// 'conflict' module-id ',' string-literal
parseConflict()2746e5dd7070Spatrick void ModuleMapParser::parseConflict() {
2747e5dd7070Spatrick assert(Tok.is(MMToken::Conflict));
2748e5dd7070Spatrick SourceLocation ConflictLoc = consumeToken();
2749e5dd7070Spatrick Module::UnresolvedConflict Conflict;
2750e5dd7070Spatrick
2751e5dd7070Spatrick // Parse the module-id.
2752e5dd7070Spatrick if (parseModuleId(Conflict.Id))
2753e5dd7070Spatrick return;
2754e5dd7070Spatrick
2755e5dd7070Spatrick // Parse the ','.
2756e5dd7070Spatrick if (!Tok.is(MMToken::Comma)) {
2757e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
2758e5dd7070Spatrick << SourceRange(ConflictLoc);
2759e5dd7070Spatrick return;
2760e5dd7070Spatrick }
2761e5dd7070Spatrick consumeToken();
2762e5dd7070Spatrick
2763e5dd7070Spatrick // Parse the message.
2764e5dd7070Spatrick if (!Tok.is(MMToken::StringLiteral)) {
2765e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
2766e5dd7070Spatrick << formatModuleId(Conflict.Id);
2767e5dd7070Spatrick return;
2768e5dd7070Spatrick }
2769e5dd7070Spatrick Conflict.Message = Tok.getString().str();
2770e5dd7070Spatrick consumeToken();
2771e5dd7070Spatrick
2772e5dd7070Spatrick // Add this unresolved conflict.
2773e5dd7070Spatrick ActiveModule->UnresolvedConflicts.push_back(Conflict);
2774e5dd7070Spatrick }
2775e5dd7070Spatrick
2776e5dd7070Spatrick /// Parse an inferred module declaration (wildcard modules).
2777e5dd7070Spatrick ///
2778e5dd7070Spatrick /// module-declaration:
2779e5dd7070Spatrick /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
2780e5dd7070Spatrick /// { inferred-module-member* }
2781e5dd7070Spatrick ///
2782e5dd7070Spatrick /// inferred-module-member:
2783e5dd7070Spatrick /// 'export' '*'
2784e5dd7070Spatrick /// 'exclude' identifier
parseInferredModuleDecl(bool Framework,bool Explicit)2785e5dd7070Spatrick void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
2786e5dd7070Spatrick assert(Tok.is(MMToken::Star));
2787e5dd7070Spatrick SourceLocation StarLoc = consumeToken();
2788e5dd7070Spatrick bool Failed = false;
2789e5dd7070Spatrick
2790e5dd7070Spatrick // Inferred modules must be submodules.
2791e5dd7070Spatrick if (!ActiveModule && !Framework) {
2792e5dd7070Spatrick Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
2793e5dd7070Spatrick Failed = true;
2794e5dd7070Spatrick }
2795e5dd7070Spatrick
2796e5dd7070Spatrick if (ActiveModule) {
2797e5dd7070Spatrick // Inferred modules must have umbrella directories.
2798e5dd7070Spatrick if (!Failed && ActiveModule->IsAvailable &&
2799e5dd7070Spatrick !ActiveModule->getUmbrellaDir()) {
2800e5dd7070Spatrick Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
2801e5dd7070Spatrick Failed = true;
2802e5dd7070Spatrick }
2803e5dd7070Spatrick
2804e5dd7070Spatrick // Check for redefinition of an inferred module.
2805e5dd7070Spatrick if (!Failed && ActiveModule->InferSubmodules) {
2806e5dd7070Spatrick Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2807e5dd7070Spatrick if (ActiveModule->InferredSubmoduleLoc.isValid())
2808e5dd7070Spatrick Diags.Report(ActiveModule->InferredSubmoduleLoc,
2809e5dd7070Spatrick diag::note_mmap_prev_definition);
2810e5dd7070Spatrick Failed = true;
2811e5dd7070Spatrick }
2812e5dd7070Spatrick
2813e5dd7070Spatrick // Check for the 'framework' keyword, which is not permitted here.
2814e5dd7070Spatrick if (Framework) {
2815e5dd7070Spatrick Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
2816e5dd7070Spatrick Framework = false;
2817e5dd7070Spatrick }
2818e5dd7070Spatrick } else if (Explicit) {
2819e5dd7070Spatrick Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
2820e5dd7070Spatrick Explicit = false;
2821e5dd7070Spatrick }
2822e5dd7070Spatrick
2823e5dd7070Spatrick // If there were any problems with this inferred submodule, skip its body.
2824e5dd7070Spatrick if (Failed) {
2825e5dd7070Spatrick if (Tok.is(MMToken::LBrace)) {
2826e5dd7070Spatrick consumeToken();
2827e5dd7070Spatrick skipUntil(MMToken::RBrace);
2828e5dd7070Spatrick if (Tok.is(MMToken::RBrace))
2829e5dd7070Spatrick consumeToken();
2830e5dd7070Spatrick }
2831e5dd7070Spatrick HadError = true;
2832e5dd7070Spatrick return;
2833e5dd7070Spatrick }
2834e5dd7070Spatrick
2835e5dd7070Spatrick // Parse optional attributes.
2836e5dd7070Spatrick Attributes Attrs;
2837e5dd7070Spatrick if (parseOptionalAttributes(Attrs))
2838e5dd7070Spatrick return;
2839e5dd7070Spatrick
2840e5dd7070Spatrick if (ActiveModule) {
2841e5dd7070Spatrick // Note that we have an inferred submodule.
2842e5dd7070Spatrick ActiveModule->InferSubmodules = true;
2843e5dd7070Spatrick ActiveModule->InferredSubmoduleLoc = StarLoc;
2844e5dd7070Spatrick ActiveModule->InferExplicitSubmodules = Explicit;
2845e5dd7070Spatrick } else {
2846e5dd7070Spatrick // We'll be inferring framework modules for this directory.
2847e5dd7070Spatrick Map.InferredDirectories[Directory].InferModules = true;
2848e5dd7070Spatrick Map.InferredDirectories[Directory].Attrs = Attrs;
2849e5dd7070Spatrick Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
2850e5dd7070Spatrick // FIXME: Handle the 'framework' keyword.
2851e5dd7070Spatrick }
2852e5dd7070Spatrick
2853e5dd7070Spatrick // Parse the opening brace.
2854e5dd7070Spatrick if (!Tok.is(MMToken::LBrace)) {
2855e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
2856e5dd7070Spatrick HadError = true;
2857e5dd7070Spatrick return;
2858e5dd7070Spatrick }
2859e5dd7070Spatrick SourceLocation LBraceLoc = consumeToken();
2860e5dd7070Spatrick
2861e5dd7070Spatrick // Parse the body of the inferred submodule.
2862e5dd7070Spatrick bool Done = false;
2863e5dd7070Spatrick do {
2864e5dd7070Spatrick switch (Tok.Kind) {
2865e5dd7070Spatrick case MMToken::EndOfFile:
2866e5dd7070Spatrick case MMToken::RBrace:
2867e5dd7070Spatrick Done = true;
2868e5dd7070Spatrick break;
2869e5dd7070Spatrick
2870e5dd7070Spatrick case MMToken::ExcludeKeyword:
2871e5dd7070Spatrick if (ActiveModule) {
2872e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2873e5dd7070Spatrick << (ActiveModule != nullptr);
2874e5dd7070Spatrick consumeToken();
2875e5dd7070Spatrick break;
2876e5dd7070Spatrick }
2877e5dd7070Spatrick
2878e5dd7070Spatrick consumeToken();
2879e5dd7070Spatrick // FIXME: Support string-literal module names here.
2880e5dd7070Spatrick if (!Tok.is(MMToken::Identifier)) {
2881e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
2882e5dd7070Spatrick break;
2883e5dd7070Spatrick }
2884e5dd7070Spatrick
2885ec727ea7Spatrick Map.InferredDirectories[Directory].ExcludedModules.push_back(
2886ec727ea7Spatrick std::string(Tok.getString()));
2887e5dd7070Spatrick consumeToken();
2888e5dd7070Spatrick break;
2889e5dd7070Spatrick
2890e5dd7070Spatrick case MMToken::ExportKeyword:
2891e5dd7070Spatrick if (!ActiveModule) {
2892e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2893e5dd7070Spatrick << (ActiveModule != nullptr);
2894e5dd7070Spatrick consumeToken();
2895e5dd7070Spatrick break;
2896e5dd7070Spatrick }
2897e5dd7070Spatrick
2898e5dd7070Spatrick consumeToken();
2899e5dd7070Spatrick if (Tok.is(MMToken::Star))
2900e5dd7070Spatrick ActiveModule->InferExportWildcard = true;
2901e5dd7070Spatrick else
2902e5dd7070Spatrick Diags.Report(Tok.getLocation(),
2903e5dd7070Spatrick diag::err_mmap_expected_export_wildcard);
2904e5dd7070Spatrick consumeToken();
2905e5dd7070Spatrick break;
2906e5dd7070Spatrick
2907e5dd7070Spatrick case MMToken::ExplicitKeyword:
2908e5dd7070Spatrick case MMToken::ModuleKeyword:
2909e5dd7070Spatrick case MMToken::HeaderKeyword:
2910e5dd7070Spatrick case MMToken::PrivateKeyword:
2911e5dd7070Spatrick case MMToken::UmbrellaKeyword:
2912e5dd7070Spatrick default:
2913e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2914e5dd7070Spatrick << (ActiveModule != nullptr);
2915e5dd7070Spatrick consumeToken();
2916e5dd7070Spatrick break;
2917e5dd7070Spatrick }
2918e5dd7070Spatrick } while (!Done);
2919e5dd7070Spatrick
2920e5dd7070Spatrick if (Tok.is(MMToken::RBrace))
2921e5dd7070Spatrick consumeToken();
2922e5dd7070Spatrick else {
2923e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2924e5dd7070Spatrick Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2925e5dd7070Spatrick HadError = true;
2926e5dd7070Spatrick }
2927e5dd7070Spatrick }
2928e5dd7070Spatrick
2929e5dd7070Spatrick /// Parse optional attributes.
2930e5dd7070Spatrick ///
2931e5dd7070Spatrick /// attributes:
2932e5dd7070Spatrick /// attribute attributes
2933e5dd7070Spatrick /// attribute
2934e5dd7070Spatrick ///
2935e5dd7070Spatrick /// attribute:
2936e5dd7070Spatrick /// [ identifier ]
2937e5dd7070Spatrick ///
2938e5dd7070Spatrick /// \param Attrs Will be filled in with the parsed attributes.
2939e5dd7070Spatrick ///
2940e5dd7070Spatrick /// \returns true if an error occurred, false otherwise.
parseOptionalAttributes(Attributes & Attrs)2941e5dd7070Spatrick bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
2942e5dd7070Spatrick bool HadError = false;
2943e5dd7070Spatrick
2944e5dd7070Spatrick while (Tok.is(MMToken::LSquare)) {
2945e5dd7070Spatrick // Consume the '['.
2946e5dd7070Spatrick SourceLocation LSquareLoc = consumeToken();
2947e5dd7070Spatrick
2948e5dd7070Spatrick // Check whether we have an attribute name here.
2949e5dd7070Spatrick if (!Tok.is(MMToken::Identifier)) {
2950e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
2951e5dd7070Spatrick skipUntil(MMToken::RSquare);
2952e5dd7070Spatrick if (Tok.is(MMToken::RSquare))
2953e5dd7070Spatrick consumeToken();
2954e5dd7070Spatrick HadError = true;
2955e5dd7070Spatrick }
2956e5dd7070Spatrick
2957e5dd7070Spatrick // Decode the attribute name.
2958e5dd7070Spatrick AttributeKind Attribute
2959e5dd7070Spatrick = llvm::StringSwitch<AttributeKind>(Tok.getString())
2960e5dd7070Spatrick .Case("exhaustive", AT_exhaustive)
2961e5dd7070Spatrick .Case("extern_c", AT_extern_c)
2962e5dd7070Spatrick .Case("no_undeclared_includes", AT_no_undeclared_includes)
2963e5dd7070Spatrick .Case("system", AT_system)
2964e5dd7070Spatrick .Default(AT_unknown);
2965e5dd7070Spatrick switch (Attribute) {
2966e5dd7070Spatrick case AT_unknown:
2967e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
2968e5dd7070Spatrick << Tok.getString();
2969e5dd7070Spatrick break;
2970e5dd7070Spatrick
2971e5dd7070Spatrick case AT_system:
2972e5dd7070Spatrick Attrs.IsSystem = true;
2973e5dd7070Spatrick break;
2974e5dd7070Spatrick
2975e5dd7070Spatrick case AT_extern_c:
2976e5dd7070Spatrick Attrs.IsExternC = true;
2977e5dd7070Spatrick break;
2978e5dd7070Spatrick
2979e5dd7070Spatrick case AT_exhaustive:
2980e5dd7070Spatrick Attrs.IsExhaustive = true;
2981e5dd7070Spatrick break;
2982e5dd7070Spatrick
2983e5dd7070Spatrick case AT_no_undeclared_includes:
2984e5dd7070Spatrick Attrs.NoUndeclaredIncludes = true;
2985e5dd7070Spatrick break;
2986e5dd7070Spatrick }
2987e5dd7070Spatrick consumeToken();
2988e5dd7070Spatrick
2989e5dd7070Spatrick // Consume the ']'.
2990e5dd7070Spatrick if (!Tok.is(MMToken::RSquare)) {
2991e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
2992e5dd7070Spatrick Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
2993e5dd7070Spatrick skipUntil(MMToken::RSquare);
2994e5dd7070Spatrick HadError = true;
2995e5dd7070Spatrick }
2996e5dd7070Spatrick
2997e5dd7070Spatrick if (Tok.is(MMToken::RSquare))
2998e5dd7070Spatrick consumeToken();
2999e5dd7070Spatrick }
3000e5dd7070Spatrick
3001e5dd7070Spatrick return HadError;
3002e5dd7070Spatrick }
3003e5dd7070Spatrick
3004e5dd7070Spatrick /// Parse a module map file.
3005e5dd7070Spatrick ///
3006e5dd7070Spatrick /// module-map-file:
3007e5dd7070Spatrick /// module-declaration*
parseModuleMapFile()3008e5dd7070Spatrick bool ModuleMapParser::parseModuleMapFile() {
3009e5dd7070Spatrick do {
3010e5dd7070Spatrick switch (Tok.Kind) {
3011e5dd7070Spatrick case MMToken::EndOfFile:
3012e5dd7070Spatrick return HadError;
3013e5dd7070Spatrick
3014e5dd7070Spatrick case MMToken::ExplicitKeyword:
3015e5dd7070Spatrick case MMToken::ExternKeyword:
3016e5dd7070Spatrick case MMToken::ModuleKeyword:
3017e5dd7070Spatrick case MMToken::FrameworkKeyword:
3018e5dd7070Spatrick parseModuleDecl();
3019e5dd7070Spatrick break;
3020e5dd7070Spatrick
3021e5dd7070Spatrick case MMToken::Comma:
3022e5dd7070Spatrick case MMToken::ConfigMacros:
3023e5dd7070Spatrick case MMToken::Conflict:
3024e5dd7070Spatrick case MMToken::Exclaim:
3025e5dd7070Spatrick case MMToken::ExcludeKeyword:
3026e5dd7070Spatrick case MMToken::ExportKeyword:
3027e5dd7070Spatrick case MMToken::ExportAsKeyword:
3028e5dd7070Spatrick case MMToken::HeaderKeyword:
3029e5dd7070Spatrick case MMToken::Identifier:
3030e5dd7070Spatrick case MMToken::LBrace:
3031e5dd7070Spatrick case MMToken::LinkKeyword:
3032e5dd7070Spatrick case MMToken::LSquare:
3033e5dd7070Spatrick case MMToken::Period:
3034e5dd7070Spatrick case MMToken::PrivateKeyword:
3035e5dd7070Spatrick case MMToken::RBrace:
3036e5dd7070Spatrick case MMToken::RSquare:
3037e5dd7070Spatrick case MMToken::RequiresKeyword:
3038e5dd7070Spatrick case MMToken::Star:
3039e5dd7070Spatrick case MMToken::StringLiteral:
3040e5dd7070Spatrick case MMToken::IntegerLiteral:
3041e5dd7070Spatrick case MMToken::TextualKeyword:
3042e5dd7070Spatrick case MMToken::UmbrellaKeyword:
3043e5dd7070Spatrick case MMToken::UseKeyword:
3044e5dd7070Spatrick Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
3045e5dd7070Spatrick HadError = true;
3046e5dd7070Spatrick consumeToken();
3047e5dd7070Spatrick break;
3048e5dd7070Spatrick }
3049e5dd7070Spatrick } while (true);
3050e5dd7070Spatrick }
3051e5dd7070Spatrick
parseModuleMapFile(const FileEntry * File,bool IsSystem,const DirectoryEntry * Dir,FileID ID,unsigned * Offset,SourceLocation ExternModuleLoc)3052e5dd7070Spatrick bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
3053e5dd7070Spatrick const DirectoryEntry *Dir, FileID ID,
3054e5dd7070Spatrick unsigned *Offset,
3055e5dd7070Spatrick SourceLocation ExternModuleLoc) {
3056e5dd7070Spatrick assert(Target && "Missing target information");
3057e5dd7070Spatrick llvm::DenseMap<const FileEntry *, bool>::iterator Known
3058e5dd7070Spatrick = ParsedModuleMap.find(File);
3059e5dd7070Spatrick if (Known != ParsedModuleMap.end())
3060e5dd7070Spatrick return Known->second;
3061e5dd7070Spatrick
3062e5dd7070Spatrick // If the module map file wasn't already entered, do so now.
3063e5dd7070Spatrick if (ID.isInvalid()) {
3064e5dd7070Spatrick auto FileCharacter =
3065e5dd7070Spatrick IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
3066e5dd7070Spatrick ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
3067e5dd7070Spatrick }
3068e5dd7070Spatrick
3069e5dd7070Spatrick assert(Target && "Missing target information");
3070*12c85518Srobert std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
3071e5dd7070Spatrick if (!Buffer)
3072e5dd7070Spatrick return ParsedModuleMap[File] = true;
3073e5dd7070Spatrick assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
3074e5dd7070Spatrick "invalid buffer offset");
3075e5dd7070Spatrick
3076e5dd7070Spatrick // Parse this module map file.
3077e5dd7070Spatrick Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
3078e5dd7070Spatrick Buffer->getBufferStart(),
3079e5dd7070Spatrick Buffer->getBufferStart() + (Offset ? *Offset : 0),
3080e5dd7070Spatrick Buffer->getBufferEnd());
3081e5dd7070Spatrick SourceLocation Start = L.getSourceLocation();
3082e5dd7070Spatrick ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
3083e5dd7070Spatrick IsSystem);
3084e5dd7070Spatrick bool Result = Parser.parseModuleMapFile();
3085e5dd7070Spatrick ParsedModuleMap[File] = Result;
3086e5dd7070Spatrick
3087e5dd7070Spatrick if (Offset) {
3088e5dd7070Spatrick auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
3089e5dd7070Spatrick assert(Loc.first == ID && "stopped in a different file?");
3090e5dd7070Spatrick *Offset = Loc.second;
3091e5dd7070Spatrick }
3092e5dd7070Spatrick
3093e5dd7070Spatrick // Notify callbacks that we parsed it.
3094e5dd7070Spatrick for (const auto &Cb : Callbacks)
3095e5dd7070Spatrick Cb->moduleMapFileRead(Start, *File, IsSystem);
3096e5dd7070Spatrick
3097e5dd7070Spatrick return Result;
3098e5dd7070Spatrick }
3099