1461a67faSDimitry Andric //===- ModuleMap.cpp - Describe the layout of modules ---------------------===//
2dbe13110SDimitry Andric //
322989816SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
422989816SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
522989816SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6dbe13110SDimitry Andric //
7dbe13110SDimitry Andric //===----------------------------------------------------------------------===//
8dbe13110SDimitry Andric //
9dbe13110SDimitry Andric // This file defines the ModuleMap implementation, which describes the layout
10dbe13110SDimitry Andric // of a module as it relates to headers.
11dbe13110SDimitry Andric //
12dbe13110SDimitry Andric //===----------------------------------------------------------------------===//
13461a67faSDimitry Andric
14dbe13110SDimitry Andric #include "clang/Lex/ModuleMap.h"
15809500fcSDimitry Andric #include "clang/Basic/CharInfo.h"
16dbe13110SDimitry Andric #include "clang/Basic/Diagnostic.h"
17dbe13110SDimitry Andric #include "clang/Basic/FileManager.h"
18461a67faSDimitry Andric #include "clang/Basic/LLVM.h"
19461a67faSDimitry Andric #include "clang/Basic/LangOptions.h"
20461a67faSDimitry Andric #include "clang/Basic/Module.h"
21461a67faSDimitry Andric #include "clang/Basic/SourceLocation.h"
22461a67faSDimitry Andric #include "clang/Basic/SourceManager.h"
23dbe13110SDimitry Andric #include "clang/Basic/TargetInfo.h"
24809500fcSDimitry Andric #include "clang/Lex/HeaderSearch.h"
2506d4ba38SDimitry Andric #include "clang/Lex/HeaderSearchOptions.h"
26809500fcSDimitry Andric #include "clang/Lex/LexDiagnostic.h"
27809500fcSDimitry Andric #include "clang/Lex/Lexer.h"
28809500fcSDimitry Andric #include "clang/Lex/LiteralSupport.h"
29461a67faSDimitry Andric #include "clang/Lex/Token.h"
30461a67faSDimitry Andric #include "llvm/ADT/DenseMap.h"
31461a67faSDimitry Andric #include "llvm/ADT/STLExtras.h"
32461a67faSDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
33461a67faSDimitry Andric #include "llvm/ADT/SmallString.h"
34461a67faSDimitry Andric #include "llvm/ADT/SmallVector.h"
35461a67faSDimitry Andric #include "llvm/ADT/StringMap.h"
36809500fcSDimitry Andric #include "llvm/ADT/StringRef.h"
37809500fcSDimitry Andric #include "llvm/ADT/StringSwitch.h"
38dbe13110SDimitry Andric #include "llvm/Support/Allocator.h"
39461a67faSDimitry Andric #include "llvm/Support/Compiler.h"
40461a67faSDimitry Andric #include "llvm/Support/ErrorHandling.h"
41461a67faSDimitry Andric #include "llvm/Support/MemoryBuffer.h"
42bfef3995SDimitry Andric #include "llvm/Support/Path.h"
43676fbe81SDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
44dbe13110SDimitry Andric #include "llvm/Support/raw_ostream.h"
45461a67faSDimitry Andric #include <algorithm>
46461a67faSDimitry Andric #include <cassert>
47461a67faSDimitry Andric #include <cstdint>
48461a67faSDimitry Andric #include <cstring>
49e3b55780SDimitry Andric #include <optional>
50461a67faSDimitry Andric #include <string>
51461a67faSDimitry Andric #include <system_error>
52461a67faSDimitry Andric #include <utility>
53461a67faSDimitry Andric
54dbe13110SDimitry Andric using namespace clang;
55dbe13110SDimitry Andric
anchor()56676fbe81SDimitry Andric void ModuleMapCallbacks::anchor() {}
57676fbe81SDimitry Andric
resolveLinkAsDependencies(Module * Mod)5848675466SDimitry Andric void ModuleMap::resolveLinkAsDependencies(Module *Mod) {
5948675466SDimitry Andric auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name);
6048675466SDimitry Andric if (PendingLinkAs != PendingLinkAsModule.end()) {
6148675466SDimitry Andric for (auto &Name : PendingLinkAs->second) {
6248675466SDimitry Andric auto *M = findModule(Name.getKey());
6348675466SDimitry Andric if (M)
6448675466SDimitry Andric M->UseExportAsModuleLinkName = true;
6548675466SDimitry Andric }
6648675466SDimitry Andric }
6748675466SDimitry Andric }
6848675466SDimitry Andric
addLinkAsDependency(Module * Mod)6948675466SDimitry Andric void ModuleMap::addLinkAsDependency(Module *Mod) {
7048675466SDimitry Andric if (findModule(Mod->ExportAsModule))
7148675466SDimitry Andric Mod->UseExportAsModuleLinkName = true;
7248675466SDimitry Andric else
7348675466SDimitry Andric PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name);
7448675466SDimitry Andric }
7548675466SDimitry Andric
headerRoleToKind(ModuleHeaderRole Role)76551c6985SDimitry Andric Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
77551c6985SDimitry Andric switch ((int)Role) {
78551c6985SDimitry Andric case NormalHeader:
79551c6985SDimitry Andric return Module::HK_Normal;
80551c6985SDimitry Andric case PrivateHeader:
81551c6985SDimitry Andric return Module::HK_Private;
82551c6985SDimitry Andric case TextualHeader:
83551c6985SDimitry Andric return Module::HK_Textual;
84551c6985SDimitry Andric case PrivateHeader | TextualHeader:
85551c6985SDimitry Andric return Module::HK_PrivateTextual;
86e3b55780SDimitry Andric case ExcludedHeader:
87e3b55780SDimitry Andric return Module::HK_Excluded;
88551c6985SDimitry Andric }
89e3b55780SDimitry Andric llvm_unreachable("unknown header role");
90551c6985SDimitry Andric }
91551c6985SDimitry Andric
92551c6985SDimitry Andric ModuleMap::ModuleHeaderRole
headerKindToRole(Module::HeaderKind Kind)93551c6985SDimitry Andric ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
94551c6985SDimitry Andric switch ((int)Kind) {
95551c6985SDimitry Andric case Module::HK_Normal:
96551c6985SDimitry Andric return NormalHeader;
97551c6985SDimitry Andric case Module::HK_Private:
98551c6985SDimitry Andric return PrivateHeader;
99551c6985SDimitry Andric case Module::HK_Textual:
100551c6985SDimitry Andric return TextualHeader;
101551c6985SDimitry Andric case Module::HK_PrivateTextual:
102551c6985SDimitry Andric return ModuleHeaderRole(PrivateHeader | TextualHeader);
103551c6985SDimitry Andric case Module::HK_Excluded:
104e3b55780SDimitry Andric return ExcludedHeader;
105551c6985SDimitry Andric }
106551c6985SDimitry Andric llvm_unreachable("unknown header kind");
107551c6985SDimitry Andric }
108551c6985SDimitry Andric
isModular(ModuleHeaderRole Role)109e3b55780SDimitry Andric bool ModuleMap::isModular(ModuleHeaderRole Role) {
110e3b55780SDimitry Andric return !(Role & (ModuleMap::TextualHeader | ModuleMap::ExcludedHeader));
111e3b55780SDimitry Andric }
112e3b55780SDimitry Andric
113dbe13110SDimitry Andric Module::ExportDecl
resolveExport(Module * Mod,const Module::UnresolvedExportDecl & Unresolved,bool Complain) const114dbe13110SDimitry Andric ModuleMap::resolveExport(Module *Mod,
115dbe13110SDimitry Andric const Module::UnresolvedExportDecl &Unresolved,
116809500fcSDimitry Andric bool Complain) const {
117dbe13110SDimitry Andric // We may have just a wildcard.
118dbe13110SDimitry Andric if (Unresolved.Id.empty()) {
119dbe13110SDimitry Andric assert(Unresolved.Wildcard && "Invalid unresolved export");
1209f4dbff6SDimitry Andric return Module::ExportDecl(nullptr, true);
121dbe13110SDimitry Andric }
122dbe13110SDimitry Andric
123809500fcSDimitry Andric // Resolve the module-id.
124809500fcSDimitry Andric Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
125809500fcSDimitry Andric if (!Context)
126461a67faSDimitry Andric return {};
127809500fcSDimitry Andric
128809500fcSDimitry Andric return Module::ExportDecl(Context, Unresolved.Wildcard);
129809500fcSDimitry Andric }
130809500fcSDimitry Andric
resolveModuleId(const ModuleId & Id,Module * Mod,bool Complain) const131809500fcSDimitry Andric Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
132809500fcSDimitry Andric bool Complain) const {
133dbe13110SDimitry Andric // Find the starting module.
134809500fcSDimitry Andric Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
135dbe13110SDimitry Andric if (!Context) {
136dbe13110SDimitry Andric if (Complain)
1379f4dbff6SDimitry Andric Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
138809500fcSDimitry Andric << Id[0].first << Mod->getFullModuleName();
139dbe13110SDimitry Andric
1409f4dbff6SDimitry Andric return nullptr;
141dbe13110SDimitry Andric }
142dbe13110SDimitry Andric
143dbe13110SDimitry Andric // Dig into the module path.
144809500fcSDimitry Andric for (unsigned I = 1, N = Id.size(); I != N; ++I) {
145809500fcSDimitry Andric Module *Sub = lookupModuleQualified(Id[I].first, Context);
146dbe13110SDimitry Andric if (!Sub) {
147dbe13110SDimitry Andric if (Complain)
1489f4dbff6SDimitry Andric Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
149809500fcSDimitry Andric << Id[I].first << Context->getFullModuleName()
150809500fcSDimitry Andric << SourceRange(Id[0].second, Id[I-1].second);
151dbe13110SDimitry Andric
1529f4dbff6SDimitry Andric return nullptr;
153dbe13110SDimitry Andric }
154dbe13110SDimitry Andric
155dbe13110SDimitry Andric Context = Sub;
156dbe13110SDimitry Andric }
157dbe13110SDimitry Andric
158809500fcSDimitry Andric return Context;
159dbe13110SDimitry Andric }
160dbe13110SDimitry Andric
16148675466SDimitry Andric /// Append to \p Paths the set of paths needed to get to the
162b5aee35cSDimitry Andric /// subframework in which the given module lives.
appendSubframeworkPaths(Module * Mod,SmallVectorImpl<char> & Path)163b5aee35cSDimitry Andric static void appendSubframeworkPaths(Module *Mod,
164b5aee35cSDimitry Andric SmallVectorImpl<char> &Path) {
165b5aee35cSDimitry Andric // Collect the framework names from the given module to the top-level module.
166b5aee35cSDimitry Andric SmallVector<StringRef, 2> Paths;
167b5aee35cSDimitry Andric for (; Mod; Mod = Mod->Parent) {
168b5aee35cSDimitry Andric if (Mod->IsFramework)
169b5aee35cSDimitry Andric Paths.push_back(Mod->Name);
170b5aee35cSDimitry Andric }
171b5aee35cSDimitry Andric
172b5aee35cSDimitry Andric if (Paths.empty())
173b5aee35cSDimitry Andric return;
174b5aee35cSDimitry Andric
175b5aee35cSDimitry Andric // Add Frameworks/Name.framework for each subframework.
176c0981da4SDimitry Andric for (StringRef Framework : llvm::drop_begin(llvm::reverse(Paths)))
177c0981da4SDimitry Andric llvm::sys::path::append(Path, "Frameworks", Framework + ".framework");
178b5aee35cSDimitry Andric }
179b5aee35cSDimitry Andric
findHeader(Module * M,const Module::UnresolvedHeaderDirective & Header,SmallVectorImpl<char> & RelativePathName,bool & NeedsFramework)180e3b55780SDimitry Andric OptionalFileEntryRef ModuleMap::findHeader(
18148675466SDimitry Andric Module *M, const Module::UnresolvedHeaderDirective &Header,
18248675466SDimitry Andric SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) {
18348675466SDimitry Andric // Search for the header file within the module's home directory.
1847fa27ce4SDimitry Andric auto Directory = M->Directory;
18548675466SDimitry Andric SmallString<128> FullPathName(Directory->getName());
18648675466SDimitry Andric
187e3b55780SDimitry Andric auto GetFile = [&](StringRef Filename) -> OptionalFileEntryRef {
188b60736ecSDimitry Andric auto File =
189b60736ecSDimitry Andric expectedToOptional(SourceMgr.getFileManager().getFileRef(Filename));
190b60736ecSDimitry Andric if (!File || (Header.Size && File->getSize() != *Header.Size) ||
191b60736ecSDimitry Andric (Header.ModTime && File->getModificationTime() != *Header.ModTime))
192e3b55780SDimitry Andric return std::nullopt;
193519fc96cSDimitry Andric return *File;
194551c6985SDimitry Andric };
195551c6985SDimitry Andric
196e3b55780SDimitry Andric auto GetFrameworkFile = [&]() -> OptionalFileEntryRef {
197b5aee35cSDimitry Andric unsigned FullPathLength = FullPathName.size();
198b5aee35cSDimitry Andric appendSubframeworkPaths(M, RelativePathName);
199b5aee35cSDimitry Andric unsigned RelativePathLength = RelativePathName.size();
200b5aee35cSDimitry Andric
201b5aee35cSDimitry Andric // Check whether this file is in the public headers.
202b5aee35cSDimitry Andric llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
203b5aee35cSDimitry Andric llvm::sys::path::append(FullPathName, RelativePathName);
204b60736ecSDimitry Andric if (auto File = GetFile(FullPathName))
205b5aee35cSDimitry Andric return File;
206b5aee35cSDimitry Andric
207b5aee35cSDimitry Andric // Check whether this file is in the private headers.
208b5aee35cSDimitry Andric // Ideally, private modules in the form 'FrameworkName.Private' should
209b5aee35cSDimitry Andric // be defined as 'module FrameworkName.Private', and not as
210b5aee35cSDimitry Andric // 'framework module FrameworkName.Private', since a 'Private.Framework'
211b5aee35cSDimitry Andric // does not usually exist. However, since both are currently widely used
212b5aee35cSDimitry Andric // for private modules, make sure we find the right path in both cases.
213b5aee35cSDimitry Andric if (M->IsFramework && M->Name == "Private")
214b5aee35cSDimitry Andric RelativePathName.clear();
215b5aee35cSDimitry Andric else
216b5aee35cSDimitry Andric RelativePathName.resize(RelativePathLength);
217b5aee35cSDimitry Andric FullPathName.resize(FullPathLength);
218b5aee35cSDimitry Andric llvm::sys::path::append(RelativePathName, "PrivateHeaders",
219b5aee35cSDimitry Andric Header.FileName);
220b5aee35cSDimitry Andric llvm::sys::path::append(FullPathName, RelativePathName);
221551c6985SDimitry Andric return GetFile(FullPathName);
22248675466SDimitry Andric };
22348675466SDimitry Andric
22448675466SDimitry Andric if (llvm::sys::path::is_absolute(Header.FileName)) {
22548675466SDimitry Andric RelativePathName.clear();
22648675466SDimitry Andric RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
22748675466SDimitry Andric return GetFile(Header.FileName);
228b5aee35cSDimitry Andric }
229b5aee35cSDimitry Andric
23048675466SDimitry Andric if (M->isPartOfFramework())
23148675466SDimitry Andric return GetFrameworkFile();
23248675466SDimitry Andric
233b5aee35cSDimitry Andric // Lookup for normal headers.
234b5aee35cSDimitry Andric llvm::sys::path::append(RelativePathName, Header.FileName);
235b5aee35cSDimitry Andric llvm::sys::path::append(FullPathName, RelativePathName);
236b60736ecSDimitry Andric auto NormalHdrFile = GetFile(FullPathName);
23748675466SDimitry Andric
238312c0ed1SDimitry Andric if (!NormalHdrFile && Directory->getName().ends_with(".framework")) {
23948675466SDimitry Andric // The lack of 'framework' keyword in a module declaration it's a simple
24048675466SDimitry Andric // mistake we can diagnose when the header exists within the proper
24148675466SDimitry Andric // framework style path.
24248675466SDimitry Andric FullPathName.assign(Directory->getName());
24348675466SDimitry Andric RelativePathName.clear();
24448675466SDimitry Andric if (GetFrameworkFile()) {
24548675466SDimitry Andric Diags.Report(Header.FileNameLoc,
24648675466SDimitry Andric diag::warn_mmap_incomplete_framework_module_declaration)
24748675466SDimitry Andric << Header.FileName << M->getFullModuleName();
24848675466SDimitry Andric NeedsFramework = true;
24948675466SDimitry Andric }
250e3b55780SDimitry Andric return std::nullopt;
25148675466SDimitry Andric }
25248675466SDimitry Andric
25348675466SDimitry Andric return NormalHdrFile;
254b5aee35cSDimitry Andric }
255b5aee35cSDimitry Andric
256b1c73532SDimitry Andric /// Determine whether the given file name is the name of a builtin
257b1c73532SDimitry Andric /// header, supplied by Clang to replace, override, or augment existing system
258b1c73532SDimitry Andric /// headers.
isBuiltinHeaderName(StringRef FileName)259b1c73532SDimitry Andric static bool isBuiltinHeaderName(StringRef FileName) {
260b1c73532SDimitry Andric return llvm::StringSwitch<bool>(FileName)
261b1c73532SDimitry Andric .Case("float.h", true)
262b1c73532SDimitry Andric .Case("iso646.h", true)
263b1c73532SDimitry Andric .Case("limits.h", true)
264b1c73532SDimitry Andric .Case("stdalign.h", true)
265b1c73532SDimitry Andric .Case("stdarg.h", true)
266b1c73532SDimitry Andric .Case("stdatomic.h", true)
267b1c73532SDimitry Andric .Case("stdbool.h", true)
268b1c73532SDimitry Andric .Case("stddef.h", true)
269b1c73532SDimitry Andric .Case("stdint.h", true)
270b1c73532SDimitry Andric .Case("tgmath.h", true)
271b1c73532SDimitry Andric .Case("unwind.h", true)
272b1c73532SDimitry Andric .Default(false);
273b1c73532SDimitry Andric }
274b1c73532SDimitry Andric
275b1c73532SDimitry Andric /// Determine whether the given module name is the name of a builtin
276b1c73532SDimitry Andric /// module that is cyclic with a system module on some platforms.
isBuiltInModuleName(StringRef ModuleName)277b1c73532SDimitry Andric static bool isBuiltInModuleName(StringRef ModuleName) {
278b1c73532SDimitry Andric return llvm::StringSwitch<bool>(ModuleName)
279b1c73532SDimitry Andric .Case("_Builtin_float", true)
280b1c73532SDimitry Andric .Case("_Builtin_inttypes", true)
281b1c73532SDimitry Andric .Case("_Builtin_iso646", true)
282b1c73532SDimitry Andric .Case("_Builtin_limits", true)
283b1c73532SDimitry Andric .Case("_Builtin_stdalign", true)
284b1c73532SDimitry Andric .Case("_Builtin_stdarg", true)
285b1c73532SDimitry Andric .Case("_Builtin_stdatomic", true)
286b1c73532SDimitry Andric .Case("_Builtin_stdbool", true)
287b1c73532SDimitry Andric .Case("_Builtin_stddef", true)
288b1c73532SDimitry Andric .Case("_Builtin_stdint", true)
289b1c73532SDimitry Andric .Case("_Builtin_stdnoreturn", true)
290b1c73532SDimitry Andric .Case("_Builtin_tgmath", true)
291b1c73532SDimitry Andric .Case("_Builtin_unwind", true)
292b1c73532SDimitry Andric .Default(false);
293b1c73532SDimitry Andric }
294b1c73532SDimitry Andric
resolveHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header,bool & NeedsFramework)295551c6985SDimitry Andric void ModuleMap::resolveHeader(Module *Mod,
29648675466SDimitry Andric const Module::UnresolvedHeaderDirective &Header,
29748675466SDimitry Andric bool &NeedsFramework) {
298551c6985SDimitry Andric SmallString<128> RelativePathName;
299e3b55780SDimitry Andric if (OptionalFileEntryRef File =
30048675466SDimitry Andric findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
301551c6985SDimitry Andric if (Header.IsUmbrella) {
302b60736ecSDimitry Andric const DirectoryEntry *UmbrellaDir = &File->getDir().getDirEntry();
303551c6985SDimitry Andric if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
304551c6985SDimitry Andric Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
305551c6985SDimitry Andric << UmbrellaMod->getFullModuleName();
306551c6985SDimitry Andric else
307551c6985SDimitry Andric // Record this umbrella header.
3087fa27ce4SDimitry Andric setUmbrellaHeaderAsWritten(Mod, *File, Header.FileName,
3097fa27ce4SDimitry Andric RelativePathName.str());
310551c6985SDimitry Andric } else {
3114df029ccSDimitry Andric Module::Header H = {Header.FileName, std::string(RelativePathName),
312344a3780SDimitry Andric *File};
313551c6985SDimitry Andric addHeader(Mod, H, headerKindToRole(Header.Kind));
314551c6985SDimitry Andric }
315551c6985SDimitry Andric } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
316551c6985SDimitry Andric // There's a builtin header but no corresponding on-disk header. Assume
317551c6985SDimitry Andric // this was supposed to modularize the builtin header alone.
318551c6985SDimitry Andric } else if (Header.Kind == Module::HK_Excluded) {
319551c6985SDimitry Andric // Ignore missing excluded header files. They're optional anyway.
320551c6985SDimitry Andric } else {
321551c6985SDimitry Andric // If we find a module that has a missing header, we mark this module as
322551c6985SDimitry Andric // unavailable and store the header directive for displaying diagnostics.
323551c6985SDimitry Andric Mod->MissingHeaders.push_back(Header);
324551c6985SDimitry Andric // A missing header with stat information doesn't make the module
325551c6985SDimitry Andric // unavailable; this keeps our behavior consistent as headers are lazily
326551c6985SDimitry Andric // resolved. (Such a module still can't be built though, except from
327551c6985SDimitry Andric // preprocessed source.)
328551c6985SDimitry Andric if (!Header.Size && !Header.ModTime)
329cfca06d7SDimitry Andric Mod->markUnavailable(/*Unimportable=*/false);
330551c6985SDimitry Andric }
331551c6985SDimitry Andric }
332551c6985SDimitry Andric
resolveAsBuiltinHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header)333551c6985SDimitry Andric bool ModuleMap::resolveAsBuiltinHeader(
334551c6985SDimitry Andric Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
335551c6985SDimitry Andric if (Header.Kind == Module::HK_Excluded ||
336551c6985SDimitry Andric llvm::sys::path::is_absolute(Header.FileName) ||
337551c6985SDimitry Andric Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
338551c6985SDimitry Andric !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
339b1c73532SDimitry Andric !LangOpts.BuiltinHeadersInSystemModules || !isBuiltinHeaderName(Header.FileName))
340551c6985SDimitry Andric return false;
341b5aee35cSDimitry Andric
342b5aee35cSDimitry Andric // This is a system module with a top-level header. This header
343b5aee35cSDimitry Andric // may have a counterpart (or replacement) in the set of headers
344b5aee35cSDimitry Andric // supplied by Clang. Find that builtin header.
345551c6985SDimitry Andric SmallString<128> Path;
346551c6985SDimitry Andric llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
347e3b55780SDimitry Andric auto File = SourceMgr.getFileManager().getOptionalFileRef(Path);
348551c6985SDimitry Andric if (!File)
349551c6985SDimitry Andric return false;
350551c6985SDimitry Andric
351b1c73532SDimitry Andric Module::Header H = {Header.FileName, Header.FileName, *File};
352551c6985SDimitry Andric auto Role = headerKindToRole(Header.Kind);
353551c6985SDimitry Andric addHeader(Mod, H, Role);
354551c6985SDimitry Andric return true;
355b5aee35cSDimitry Andric }
356b5aee35cSDimitry Andric
ModuleMap(SourceManager & SourceMgr,DiagnosticsEngine & Diags,const LangOptions & LangOpts,const TargetInfo * Target,HeaderSearch & HeaderInfo)3579f4dbff6SDimitry Andric ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
358809500fcSDimitry Andric const LangOptions &LangOpts, const TargetInfo *Target,
359809500fcSDimitry Andric HeaderSearch &HeaderInfo)
3609f4dbff6SDimitry Andric : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
361461a67faSDimitry Andric HeaderInfo(HeaderInfo) {
3625e20cdd8SDimitry Andric MMapLangOpts.LineComment = true;
3635e20cdd8SDimitry Andric }
364dbe13110SDimitry Andric
~ModuleMap()365dbe13110SDimitry Andric ModuleMap::~ModuleMap() {
3662b6b257fSDimitry Andric for (auto &M : Modules)
3672b6b257fSDimitry Andric delete M.getValue();
36848675466SDimitry Andric for (auto *M : ShadowModules)
36948675466SDimitry Andric delete M;
370dbe13110SDimitry Andric }
371dbe13110SDimitry Andric
setTarget(const TargetInfo & Target)372dbe13110SDimitry Andric void ModuleMap::setTarget(const TargetInfo &Target) {
373dbe13110SDimitry Andric assert((!this->Target || this->Target == &Target) &&
374dbe13110SDimitry Andric "Improper target override");
375dbe13110SDimitry Andric this->Target = &Target;
376dbe13110SDimitry Andric }
377dbe13110SDimitry Andric
37848675466SDimitry Andric /// "Sanitize" a filename so that it can be used as an identifier.
sanitizeFilenameAsIdentifier(StringRef Name,SmallVectorImpl<char> & Buffer)37913cc256eSDimitry Andric static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
38013cc256eSDimitry Andric SmallVectorImpl<char> &Buffer) {
38113cc256eSDimitry Andric if (Name.empty())
38213cc256eSDimitry Andric return Name;
38313cc256eSDimitry Andric
384c0981da4SDimitry Andric if (!isValidAsciiIdentifier(Name)) {
38513cc256eSDimitry Andric // If we don't already have something with the form of an identifier,
38613cc256eSDimitry Andric // create a buffer with the sanitized name.
38713cc256eSDimitry Andric Buffer.clear();
388809500fcSDimitry Andric if (isDigit(Name[0]))
38913cc256eSDimitry Andric Buffer.push_back('_');
39013cc256eSDimitry Andric Buffer.reserve(Buffer.size() + Name.size());
39113cc256eSDimitry Andric for (unsigned I = 0, N = Name.size(); I != N; ++I) {
392c0981da4SDimitry Andric if (isAsciiIdentifierContinue(Name[I]))
39313cc256eSDimitry Andric Buffer.push_back(Name[I]);
39413cc256eSDimitry Andric else
39513cc256eSDimitry Andric Buffer.push_back('_');
39613cc256eSDimitry Andric }
39713cc256eSDimitry Andric
39813cc256eSDimitry Andric Name = StringRef(Buffer.data(), Buffer.size());
39913cc256eSDimitry Andric }
40013cc256eSDimitry Andric
40113cc256eSDimitry Andric while (llvm::StringSwitch<bool>(Name)
40213cc256eSDimitry Andric #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
40313cc256eSDimitry Andric #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
40413cc256eSDimitry Andric #include "clang/Basic/TokenKinds.def"
40513cc256eSDimitry Andric .Default(false)) {
40613cc256eSDimitry Andric if (Name.data() != Buffer.data())
40713cc256eSDimitry Andric Buffer.append(Name.begin(), Name.end());
40813cc256eSDimitry Andric Buffer.push_back('_');
40913cc256eSDimitry Andric Name = StringRef(Buffer.data(), Buffer.size());
41013cc256eSDimitry Andric }
41113cc256eSDimitry Andric
41213cc256eSDimitry Andric return Name;
41313cc256eSDimitry Andric }
41413cc256eSDimitry Andric
isBuiltinHeader(FileEntryRef File)415b1c73532SDimitry Andric bool ModuleMap::isBuiltinHeader(FileEntryRef File) {
416b1c73532SDimitry Andric return File.getDir() == BuiltinIncludeDir && LangOpts.BuiltinHeadersInSystemModules &&
417b1c73532SDimitry Andric isBuiltinHeaderName(llvm::sys::path::filename(File.getName()));
4186a037251SDimitry Andric }
4196a037251SDimitry Andric
shouldImportRelativeToBuiltinIncludeDir(StringRef FileName,Module * Module) const420b1c73532SDimitry Andric bool ModuleMap::shouldImportRelativeToBuiltinIncludeDir(StringRef FileName,
421b1c73532SDimitry Andric Module *Module) const {
422b1c73532SDimitry Andric return LangOpts.BuiltinHeadersInSystemModules && BuiltinIncludeDir &&
423b1c73532SDimitry Andric Module->IsSystem && !Module->isPartOfFramework() &&
424b1c73532SDimitry Andric isBuiltinHeaderName(FileName);
425cfca06d7SDimitry Andric }
426cfca06d7SDimitry Andric
findKnownHeader(FileEntryRef File)427b1c73532SDimitry Andric ModuleMap::HeadersMap::iterator ModuleMap::findKnownHeader(FileEntryRef File) {
428551c6985SDimitry Andric resolveHeaderDirectives(File);
42913cc256eSDimitry Andric HeadersMap::iterator Known = Headers.find(File);
4302e645aa5SDimitry Andric if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
431cfca06d7SDimitry Andric Known == Headers.end() && ModuleMap::isBuiltinHeader(File)) {
432bfef3995SDimitry Andric HeaderInfo.loadTopLevelSystemModules();
4339f4dbff6SDimitry Andric return Headers.find(File);
4349f4dbff6SDimitry Andric }
4359f4dbff6SDimitry Andric return Known;
4366a037251SDimitry Andric }
4376a037251SDimitry Andric
findHeaderInUmbrellaDirs(FileEntryRef File,SmallVectorImpl<DirectoryEntryRef> & IntermediateDirs)4387fa27ce4SDimitry Andric ModuleMap::KnownHeader ModuleMap::findHeaderInUmbrellaDirs(
4397fa27ce4SDimitry Andric FileEntryRef File, SmallVectorImpl<DirectoryEntryRef> &IntermediateDirs) {
4402e645aa5SDimitry Andric if (UmbrellaDirs.empty())
441461a67faSDimitry Andric return {};
4422e645aa5SDimitry Andric
4437fa27ce4SDimitry Andric OptionalDirectoryEntryRef Dir = File.getDir();
444809500fcSDimitry Andric
445809500fcSDimitry Andric // Note: as an egregious but useful hack we use the real path here, because
446809500fcSDimitry Andric // frameworks moving from top-level frameworks to embedded frameworks tend
447809500fcSDimitry Andric // to be symlinked from the top-level location to the embedded location,
448809500fcSDimitry Andric // and we need to resolve lookups as if we had found the embedded location.
4497fa27ce4SDimitry Andric StringRef DirName = SourceMgr.getFileManager().getCanonicalName(*Dir);
450dbe13110SDimitry Andric
451dbe13110SDimitry Andric // Keep walking up the directory hierarchy, looking for a directory with
452dbe13110SDimitry Andric // an umbrella header.
453dbe13110SDimitry Andric do {
4547fa27ce4SDimitry Andric auto KnownDir = UmbrellaDirs.find(*Dir);
4559f4dbff6SDimitry Andric if (KnownDir != UmbrellaDirs.end())
4569f4dbff6SDimitry Andric return KnownHeader(KnownDir->second, NormalHeader);
4579f4dbff6SDimitry Andric
4587fa27ce4SDimitry Andric IntermediateDirs.push_back(*Dir);
4599f4dbff6SDimitry Andric
4609f4dbff6SDimitry Andric // Retrieve our parent path.
4619f4dbff6SDimitry Andric DirName = llvm::sys::path::parent_path(DirName);
4629f4dbff6SDimitry Andric if (DirName.empty())
4639f4dbff6SDimitry Andric break;
4649f4dbff6SDimitry Andric
4659f4dbff6SDimitry Andric // Resolve the parent path to a directory entry.
4667fa27ce4SDimitry Andric Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
4679f4dbff6SDimitry Andric } while (Dir);
468461a67faSDimitry Andric return {};
4699f4dbff6SDimitry Andric }
4709f4dbff6SDimitry Andric
violatesPrivateInclude(Module * RequestingModule,const FileEntry * IncFileEnt,ModuleMap::KnownHeader Header)4719f4dbff6SDimitry Andric static bool violatesPrivateInclude(Module *RequestingModule,
4729f4dbff6SDimitry Andric const FileEntry *IncFileEnt,
4732b6b257fSDimitry Andric ModuleMap::KnownHeader Header) {
4749f4dbff6SDimitry Andric #ifndef NDEBUG
4752b6b257fSDimitry Andric if (Header.getRole() & ModuleMap::PrivateHeader) {
4769f4dbff6SDimitry Andric // Check for consistency between the module header role
4779f4dbff6SDimitry Andric // as obtained from the lookup and as obtained from the module.
4789f4dbff6SDimitry Andric // This check is not cheap, so enable it only for debugging.
47906d4ba38SDimitry Andric bool IsPrivate = false;
4805e20cdd8SDimitry Andric SmallVectorImpl<Module::Header> *HeaderList[] = {
4812b6b257fSDimitry Andric &Header.getModule()->Headers[Module::HK_Private],
4822b6b257fSDimitry Andric &Header.getModule()->Headers[Module::HK_PrivateTextual]};
4835e20cdd8SDimitry Andric for (auto *Hs : HeaderList)
4844b4fe385SDimitry Andric IsPrivate |= llvm::any_of(
4854b4fe385SDimitry Andric *Hs, [&](const Module::Header &H) { return H.Entry == IncFileEnt; });
4862b6b257fSDimitry Andric assert(IsPrivate && "inconsistent headers and roles");
4875e20cdd8SDimitry Andric }
4889f4dbff6SDimitry Andric #endif
4892b6b257fSDimitry Andric return !Header.isAccessibleFrom(RequestingModule);
4909f4dbff6SDimitry Andric }
4919f4dbff6SDimitry Andric
getTopLevelOrNull(Module * M)4929f4dbff6SDimitry Andric static Module *getTopLevelOrNull(Module *M) {
4939f4dbff6SDimitry Andric return M ? M->getTopLevelModule() : nullptr;
4949f4dbff6SDimitry Andric }
4959f4dbff6SDimitry Andric
diagnoseHeaderInclusion(Module * RequestingModule,bool RequestingModuleIsModuleInterface,SourceLocation FilenameLoc,StringRef Filename,FileEntryRef File)4969f4dbff6SDimitry Andric void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
4972b6b257fSDimitry Andric bool RequestingModuleIsModuleInterface,
4989f4dbff6SDimitry Andric SourceLocation FilenameLoc,
499145449b1SDimitry Andric StringRef Filename, FileEntryRef File) {
5009f4dbff6SDimitry Andric // No errors for indirect modules. This may be a bit of a problem for modules
5019f4dbff6SDimitry Andric // with no source files.
5029f4dbff6SDimitry Andric if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
5039f4dbff6SDimitry Andric return;
5049f4dbff6SDimitry Andric
505551c6985SDimitry Andric if (RequestingModule) {
5069f4dbff6SDimitry Andric resolveUses(RequestingModule, /*Complain=*/false);
507e3b55780SDimitry Andric resolveHeaderDirectives(RequestingModule, /*File=*/std::nullopt);
508551c6985SDimitry Andric }
5099f4dbff6SDimitry Andric
5109f4dbff6SDimitry Andric bool Excluded = false;
5119f4dbff6SDimitry Andric Module *Private = nullptr;
5129f4dbff6SDimitry Andric Module *NotUsed = nullptr;
5139f4dbff6SDimitry Andric
5149f4dbff6SDimitry Andric HeadersMap::iterator Known = findKnownHeader(File);
5159f4dbff6SDimitry Andric if (Known != Headers.end()) {
5169f4dbff6SDimitry Andric for (const KnownHeader &Header : Known->second) {
517e3b55780SDimitry Andric // Excluded headers don't really belong to a module.
518e3b55780SDimitry Andric if (Header.getRole() == ModuleMap::ExcludedHeader) {
519e3b55780SDimitry Andric Excluded = true;
520e3b55780SDimitry Andric continue;
521e3b55780SDimitry Andric }
522e3b55780SDimitry Andric
5239f4dbff6SDimitry Andric // Remember private headers for later printing of a diagnostic.
5242b6b257fSDimitry Andric if (violatesPrivateInclude(RequestingModule, File, Header)) {
5259f4dbff6SDimitry Andric Private = Header.getModule();
5269f4dbff6SDimitry Andric continue;
5279f4dbff6SDimitry Andric }
5289f4dbff6SDimitry Andric
5299f4dbff6SDimitry Andric // If uses need to be specified explicitly, we are only allowed to return
5309f4dbff6SDimitry Andric // modules that are explicitly used by the requesting module.
5319f4dbff6SDimitry Andric if (RequestingModule && LangOpts.ModulesDeclUse &&
5325e20cdd8SDimitry Andric !RequestingModule->directlyUses(Header.getModule())) {
5339f4dbff6SDimitry Andric NotUsed = Header.getModule();
5349f4dbff6SDimitry Andric continue;
5359f4dbff6SDimitry Andric }
5369f4dbff6SDimitry Andric
5379f4dbff6SDimitry Andric // We have found a module that we can happily use.
5389f4dbff6SDimitry Andric return;
5399f4dbff6SDimitry Andric }
54006d4ba38SDimitry Andric
54106d4ba38SDimitry Andric Excluded = true;
5429f4dbff6SDimitry Andric }
5439f4dbff6SDimitry Andric
5449f4dbff6SDimitry Andric // We have found a header, but it is private.
5459f4dbff6SDimitry Andric if (Private) {
5465e20cdd8SDimitry Andric Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
5479f4dbff6SDimitry Andric << Filename;
5489f4dbff6SDimitry Andric return;
5499f4dbff6SDimitry Andric }
5509f4dbff6SDimitry Andric
5519f4dbff6SDimitry Andric // We have found a module, but we don't use it.
5529f4dbff6SDimitry Andric if (NotUsed) {
5537fa27ce4SDimitry Andric Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module_indirect)
5547fa27ce4SDimitry Andric << RequestingModule->getTopLevelModule()->Name << Filename
5557fa27ce4SDimitry Andric << NotUsed->Name;
5569f4dbff6SDimitry Andric return;
5579f4dbff6SDimitry Andric }
5589f4dbff6SDimitry Andric
5599f4dbff6SDimitry Andric if (Excluded || isHeaderInUmbrellaDirs(File))
5609f4dbff6SDimitry Andric return;
5619f4dbff6SDimitry Andric
5629f4dbff6SDimitry Andric // At this point, only non-modular includes remain.
5639f4dbff6SDimitry Andric
564676fbe81SDimitry Andric if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
5655e20cdd8SDimitry Andric Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
56648675466SDimitry Andric << RequestingModule->getTopLevelModule()->Name << Filename;
567bab175ecSDimitry Andric } else if (RequestingModule && RequestingModuleIsModuleInterface &&
568bab175ecSDimitry Andric LangOpts.isCompilingModule()) {
569bab175ecSDimitry Andric // Do not diagnose when we are not compiling a module.
5709f4dbff6SDimitry Andric diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
5719f4dbff6SDimitry Andric diag::warn_non_modular_include_in_framework_module :
5729f4dbff6SDimitry Andric diag::warn_non_modular_include_in_module;
573bab175ecSDimitry Andric Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
574145449b1SDimitry Andric << File.getName();
5759f4dbff6SDimitry Andric }
5769f4dbff6SDimitry Andric }
5779f4dbff6SDimitry Andric
isBetterKnownHeader(const ModuleMap::KnownHeader & New,const ModuleMap::KnownHeader & Old)5785e20cdd8SDimitry Andric static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
5795e20cdd8SDimitry Andric const ModuleMap::KnownHeader &Old) {
58045b53394SDimitry Andric // Prefer available modules.
581cfca06d7SDimitry Andric // FIXME: Considering whether the module is available rather than merely
582cfca06d7SDimitry Andric // importable is non-hermetic and can result in surprising behavior for
583cfca06d7SDimitry Andric // prebuilt modules. Consider only checking for importability here.
58445b53394SDimitry Andric if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
58545b53394SDimitry Andric return true;
58645b53394SDimitry Andric
5875e20cdd8SDimitry Andric // Prefer a public header over a private header.
5885e20cdd8SDimitry Andric if ((New.getRole() & ModuleMap::PrivateHeader) !=
5895e20cdd8SDimitry Andric (Old.getRole() & ModuleMap::PrivateHeader))
5905e20cdd8SDimitry Andric return !(New.getRole() & ModuleMap::PrivateHeader);
5915e20cdd8SDimitry Andric
5925e20cdd8SDimitry Andric // Prefer a non-textual header over a textual header.
5935e20cdd8SDimitry Andric if ((New.getRole() & ModuleMap::TextualHeader) !=
5945e20cdd8SDimitry Andric (Old.getRole() & ModuleMap::TextualHeader))
5955e20cdd8SDimitry Andric return !(New.getRole() & ModuleMap::TextualHeader);
5965e20cdd8SDimitry Andric
597e3b55780SDimitry Andric // Prefer a non-excluded header over an excluded header.
598e3b55780SDimitry Andric if ((New.getRole() == ModuleMap::ExcludedHeader) !=
599e3b55780SDimitry Andric (Old.getRole() == ModuleMap::ExcludedHeader))
600e3b55780SDimitry Andric return New.getRole() != ModuleMap::ExcludedHeader;
601e3b55780SDimitry Andric
6025e20cdd8SDimitry Andric // Don't have a reason to choose between these. Just keep the first one.
6035e20cdd8SDimitry Andric return false;
6045e20cdd8SDimitry Andric }
6055e20cdd8SDimitry Andric
findModuleForHeader(FileEntryRef File,bool AllowTextual,bool AllowExcluded)6067fa27ce4SDimitry Andric ModuleMap::KnownHeader ModuleMap::findModuleForHeader(FileEntryRef File,
607e3b55780SDimitry Andric bool AllowTextual,
608e3b55780SDimitry Andric bool AllowExcluded) {
60906d4ba38SDimitry Andric auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
610bab175ecSDimitry Andric if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
611461a67faSDimitry Andric return {};
61206d4ba38SDimitry Andric return R;
61306d4ba38SDimitry Andric };
61406d4ba38SDimitry Andric
6152e645aa5SDimitry Andric HeadersMap::iterator Known = findKnownHeader(File);
6169f4dbff6SDimitry Andric if (Known != Headers.end()) {
61706d4ba38SDimitry Andric ModuleMap::KnownHeader Result;
6189f4dbff6SDimitry Andric // Iterate over all modules that 'File' is part of to find the best fit.
6192e645aa5SDimitry Andric for (KnownHeader &H : Known->second) {
620e3b55780SDimitry Andric // Cannot use a module if the header is excluded in it.
621e3b55780SDimitry Andric if (!AllowExcluded && H.getRole() == ModuleMap::ExcludedHeader)
622e3b55780SDimitry Andric continue;
6232b6b257fSDimitry Andric // Prefer a header from the source module over all others.
6242b6b257fSDimitry Andric if (H.getModule()->getTopLevelModule() == SourceModule)
625c192b3dcSDimitry Andric return MakeResult(H);
6262e645aa5SDimitry Andric if (!Result || isBetterKnownHeader(H, Result))
6272e645aa5SDimitry Andric Result = H;
6289f4dbff6SDimitry Andric }
62906d4ba38SDimitry Andric return MakeResult(Result);
6309f4dbff6SDimitry Andric }
6319f4dbff6SDimitry Andric
63245b53394SDimitry Andric return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
63345b53394SDimitry Andric }
63445b53394SDimitry Andric
63545b53394SDimitry Andric ModuleMap::KnownHeader
findOrCreateModuleForHeaderInUmbrellaDir(FileEntryRef File)6367fa27ce4SDimitry Andric ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(FileEntryRef File) {
63745b53394SDimitry Andric assert(!Headers.count(File) && "already have a module for this header");
63845b53394SDimitry Andric
6397fa27ce4SDimitry Andric SmallVector<DirectoryEntryRef, 2> SkippedDirs;
6409f4dbff6SDimitry Andric KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
6419f4dbff6SDimitry Andric if (H) {
6429f4dbff6SDimitry Andric Module *Result = H.getModule();
643dbe13110SDimitry Andric
644dbe13110SDimitry Andric // Search up the module stack until we find a module with an umbrella
645dbe13110SDimitry Andric // directory.
646dbe13110SDimitry Andric Module *UmbrellaModule = Result;
6477fa27ce4SDimitry Andric while (!UmbrellaModule->getEffectiveUmbrellaDir() && UmbrellaModule->Parent)
648dbe13110SDimitry Andric UmbrellaModule = UmbrellaModule->Parent;
649dbe13110SDimitry Andric
650dbe13110SDimitry Andric if (UmbrellaModule->InferSubmodules) {
651ac9a064cSDimitry Andric FileID UmbrellaModuleMap = getModuleMapFileIDForUniquing(UmbrellaModule);
65206d4ba38SDimitry Andric
653dbe13110SDimitry Andric // Infer submodules for each of the directories we found between
654dbe13110SDimitry Andric // the directory of the umbrella header and the directory where
655dbe13110SDimitry Andric // the actual header is located.
656dbe13110SDimitry Andric bool Explicit = UmbrellaModule->InferExplicitSubmodules;
657dbe13110SDimitry Andric
6587fa27ce4SDimitry Andric for (DirectoryEntryRef SkippedDir : llvm::reverse(SkippedDirs)) {
659dbe13110SDimitry Andric // Find or create the module that corresponds to this directory name.
66013cc256eSDimitry Andric SmallString<32> NameBuf;
66113cc256eSDimitry Andric StringRef Name = sanitizeFilenameAsIdentifier(
6627fa27ce4SDimitry Andric llvm::sys::path::stem(SkippedDir.getName()), NameBuf);
66306d4ba38SDimitry Andric Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
66406d4ba38SDimitry Andric Explicit).first;
66506d4ba38SDimitry Andric InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
6669f4dbff6SDimitry Andric Result->IsInferred = true;
667dbe13110SDimitry Andric
668dbe13110SDimitry Andric // Associate the module and the directory.
669c0981da4SDimitry Andric UmbrellaDirs[SkippedDir] = Result;
670dbe13110SDimitry Andric
671dbe13110SDimitry Andric // If inferred submodules export everything they import, add a
672dbe13110SDimitry Andric // wildcard to the set of exports.
673dbe13110SDimitry Andric if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
6749f4dbff6SDimitry Andric Result->Exports.push_back(Module::ExportDecl(nullptr, true));
675dbe13110SDimitry Andric }
676dbe13110SDimitry Andric
677dbe13110SDimitry Andric // Infer a submodule with the same name as this header file.
67813cc256eSDimitry Andric SmallString<32> NameBuf;
67913cc256eSDimitry Andric StringRef Name = sanitizeFilenameAsIdentifier(
6807fa27ce4SDimitry Andric llvm::sys::path::stem(File.getName()), NameBuf);
68106d4ba38SDimitry Andric Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
68206d4ba38SDimitry Andric Explicit).first;
68306d4ba38SDimitry Andric InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
6849f4dbff6SDimitry Andric Result->IsInferred = true;
685809500fcSDimitry Andric Result->addTopHeader(File);
686dbe13110SDimitry Andric
687dbe13110SDimitry Andric // If inferred submodules export everything they import, add a
688dbe13110SDimitry Andric // wildcard to the set of exports.
689dbe13110SDimitry Andric if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
6909f4dbff6SDimitry Andric Result->Exports.push_back(Module::ExportDecl(nullptr, true));
691dbe13110SDimitry Andric } else {
692dbe13110SDimitry Andric // Record each of the directories we stepped through as being part of
693dbe13110SDimitry Andric // the module we found, since the umbrella header covers them all.
694dbe13110SDimitry Andric for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
695dbe13110SDimitry Andric UmbrellaDirs[SkippedDirs[I]] = Result;
696dbe13110SDimitry Andric }
697dbe13110SDimitry Andric
69845b53394SDimitry Andric KnownHeader Header(Result, NormalHeader);
69945b53394SDimitry Andric Headers[File].push_back(Header);
70045b53394SDimitry Andric return Header;
701dbe13110SDimitry Andric }
702dbe13110SDimitry Andric
703461a67faSDimitry Andric return {};
704dbe13110SDimitry Andric }
705dbe13110SDimitry Andric
70645b53394SDimitry Andric ArrayRef<ModuleMap::KnownHeader>
findAllModulesForHeader(FileEntryRef File)7077fa27ce4SDimitry Andric ModuleMap::findAllModulesForHeader(FileEntryRef File) {
708cfca06d7SDimitry Andric HeadersMap::iterator Known = findKnownHeader(File);
709cfca06d7SDimitry Andric if (Known != Headers.end())
710cfca06d7SDimitry Andric return Known->second;
711cfca06d7SDimitry Andric
712cfca06d7SDimitry Andric if (findOrCreateModuleForHeaderInUmbrellaDir(File))
713cfca06d7SDimitry Andric return Headers.find(File)->second;
714cfca06d7SDimitry Andric
715e3b55780SDimitry Andric return std::nullopt;
716cfca06d7SDimitry Andric }
717cfca06d7SDimitry Andric
718cfca06d7SDimitry Andric ArrayRef<ModuleMap::KnownHeader>
findResolvedModulesForHeader(FileEntryRef File) const719b1c73532SDimitry Andric ModuleMap::findResolvedModulesForHeader(FileEntryRef File) const {
720cfca06d7SDimitry Andric // FIXME: Is this necessary?
721551c6985SDimitry Andric resolveHeaderDirectives(File);
72245b53394SDimitry Andric auto It = Headers.find(File);
72345b53394SDimitry Andric if (It == Headers.end())
724e3b55780SDimitry Andric return std::nullopt;
72545b53394SDimitry Andric return It->second;
72645b53394SDimitry Andric }
72745b53394SDimitry Andric
isHeaderInUnavailableModule(FileEntryRef Header) const7287fa27ce4SDimitry Andric bool ModuleMap::isHeaderInUnavailableModule(FileEntryRef Header) const {
7299f4dbff6SDimitry Andric return isHeaderUnavailableInModule(Header, nullptr);
7309f4dbff6SDimitry Andric }
7319f4dbff6SDimitry Andric
isHeaderUnavailableInModule(FileEntryRef Header,const Module * RequestingModule) const7327fa27ce4SDimitry Andric bool ModuleMap::isHeaderUnavailableInModule(
7337fa27ce4SDimitry Andric FileEntryRef Header, const Module *RequestingModule) const {
734551c6985SDimitry Andric resolveHeaderDirectives(Header);
735809500fcSDimitry Andric HeadersMap::const_iterator Known = Headers.find(Header);
736bfef3995SDimitry Andric if (Known != Headers.end()) {
737bfef3995SDimitry Andric for (SmallVectorImpl<KnownHeader>::const_iterator
738bfef3995SDimitry Andric I = Known->second.begin(),
739bfef3995SDimitry Andric E = Known->second.end();
740bfef3995SDimitry Andric I != E; ++I) {
741d2e0a8ddSDimitry Andric
742e3b55780SDimitry Andric if (I->getRole() == ModuleMap::ExcludedHeader)
743e3b55780SDimitry Andric continue;
744e3b55780SDimitry Andric
745d2e0a8ddSDimitry Andric if (I->isAvailable() &&
746d2e0a8ddSDimitry Andric (!RequestingModule ||
747d2e0a8ddSDimitry Andric I->getModule()->isSubModuleOf(RequestingModule))) {
748d2e0a8ddSDimitry Andric // When no requesting module is available, the caller is looking if a
749d2e0a8ddSDimitry Andric // header is part a module by only looking into the module map. This is
750d2e0a8ddSDimitry Andric // done by warn_uncovered_module_header checks; don't consider textual
751d2e0a8ddSDimitry Andric // headers part of it in this mode, otherwise we get misleading warnings
752d2e0a8ddSDimitry Andric // that a umbrella header is not including a textual header.
753d2e0a8ddSDimitry Andric if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
754d2e0a8ddSDimitry Andric continue;
755bfef3995SDimitry Andric return false;
756bfef3995SDimitry Andric }
757d2e0a8ddSDimitry Andric }
758bfef3995SDimitry Andric return true;
759bfef3995SDimitry Andric }
760dbe13110SDimitry Andric
7617fa27ce4SDimitry Andric OptionalDirectoryEntryRef Dir = Header.getDir();
7627fa27ce4SDimitry Andric SmallVector<DirectoryEntryRef, 2> SkippedDirs;
763dbe13110SDimitry Andric StringRef DirName = Dir->getName();
764dbe13110SDimitry Andric
7659f4dbff6SDimitry Andric auto IsUnavailable = [&](const Module *M) {
7669f4dbff6SDimitry Andric return !M->isAvailable() && (!RequestingModule ||
7679f4dbff6SDimitry Andric M->isSubModuleOf(RequestingModule));
7689f4dbff6SDimitry Andric };
7699f4dbff6SDimitry Andric
770dbe13110SDimitry Andric // Keep walking up the directory hierarchy, looking for a directory with
771dbe13110SDimitry Andric // an umbrella header.
772dbe13110SDimitry Andric do {
7737fa27ce4SDimitry Andric auto KnownDir = UmbrellaDirs.find(*Dir);
774dbe13110SDimitry Andric if (KnownDir != UmbrellaDirs.end()) {
775dbe13110SDimitry Andric Module *Found = KnownDir->second;
7769f4dbff6SDimitry Andric if (IsUnavailable(Found))
777dbe13110SDimitry Andric return true;
778dbe13110SDimitry Andric
779dbe13110SDimitry Andric // Search up the module stack until we find a module with an umbrella
780dbe13110SDimitry Andric // directory.
781dbe13110SDimitry Andric Module *UmbrellaModule = Found;
7827fa27ce4SDimitry Andric while (!UmbrellaModule->getEffectiveUmbrellaDir() &&
7837fa27ce4SDimitry Andric UmbrellaModule->Parent)
784dbe13110SDimitry Andric UmbrellaModule = UmbrellaModule->Parent;
785dbe13110SDimitry Andric
786dbe13110SDimitry Andric if (UmbrellaModule->InferSubmodules) {
7877fa27ce4SDimitry Andric for (DirectoryEntryRef SkippedDir : llvm::reverse(SkippedDirs)) {
788dbe13110SDimitry Andric // Find or create the module that corresponds to this directory name.
78913cc256eSDimitry Andric SmallString<32> NameBuf;
79013cc256eSDimitry Andric StringRef Name = sanitizeFilenameAsIdentifier(
7917fa27ce4SDimitry Andric llvm::sys::path::stem(SkippedDir.getName()), NameBuf);
792dbe13110SDimitry Andric Found = lookupModuleQualified(Name, Found);
793dbe13110SDimitry Andric if (!Found)
794dbe13110SDimitry Andric return false;
7959f4dbff6SDimitry Andric if (IsUnavailable(Found))
796dbe13110SDimitry Andric return true;
797dbe13110SDimitry Andric }
798dbe13110SDimitry Andric
799dbe13110SDimitry Andric // Infer a submodule with the same name as this header file.
80013cc256eSDimitry Andric SmallString<32> NameBuf;
80113cc256eSDimitry Andric StringRef Name = sanitizeFilenameAsIdentifier(
8027fa27ce4SDimitry Andric llvm::sys::path::stem(Header.getName()),
80313cc256eSDimitry Andric NameBuf);
804dbe13110SDimitry Andric Found = lookupModuleQualified(Name, Found);
805dbe13110SDimitry Andric if (!Found)
806dbe13110SDimitry Andric return false;
807dbe13110SDimitry Andric }
808dbe13110SDimitry Andric
8099f4dbff6SDimitry Andric return IsUnavailable(Found);
810dbe13110SDimitry Andric }
811dbe13110SDimitry Andric
8127fa27ce4SDimitry Andric SkippedDirs.push_back(*Dir);
813dbe13110SDimitry Andric
814dbe13110SDimitry Andric // Retrieve our parent path.
815dbe13110SDimitry Andric DirName = llvm::sys::path::parent_path(DirName);
816dbe13110SDimitry Andric if (DirName.empty())
817dbe13110SDimitry Andric break;
818dbe13110SDimitry Andric
819dbe13110SDimitry Andric // Resolve the parent path to a directory entry.
8207fa27ce4SDimitry Andric Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
821dbe13110SDimitry Andric } while (Dir);
822dbe13110SDimitry Andric
823dbe13110SDimitry Andric return false;
824dbe13110SDimitry Andric }
825dbe13110SDimitry Andric
findModule(StringRef Name) const826809500fcSDimitry Andric Module *ModuleMap::findModule(StringRef Name) const {
827809500fcSDimitry Andric llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
828dbe13110SDimitry Andric if (Known != Modules.end())
829dbe13110SDimitry Andric return Known->getValue();
830dbe13110SDimitry Andric
8319f4dbff6SDimitry Andric return nullptr;
832dbe13110SDimitry Andric }
833dbe13110SDimitry Andric
lookupModuleUnqualified(StringRef Name,Module * Context) const834809500fcSDimitry Andric Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
835809500fcSDimitry Andric Module *Context) const {
836dbe13110SDimitry Andric for(; Context; Context = Context->Parent) {
837dbe13110SDimitry Andric if (Module *Sub = lookupModuleQualified(Name, Context))
838dbe13110SDimitry Andric return Sub;
839dbe13110SDimitry Andric }
840dbe13110SDimitry Andric
841dbe13110SDimitry Andric return findModule(Name);
842dbe13110SDimitry Andric }
843dbe13110SDimitry Andric
lookupModuleQualified(StringRef Name,Module * Context) const844809500fcSDimitry Andric Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
845dbe13110SDimitry Andric if (!Context)
846dbe13110SDimitry Andric return findModule(Name);
847dbe13110SDimitry Andric
848dbe13110SDimitry Andric return Context->findSubmodule(Name);
849dbe13110SDimitry Andric }
850dbe13110SDimitry Andric
findOrCreateModule(StringRef Name,Module * Parent,bool IsFramework,bool IsExplicit)8517442d6faSDimitry Andric std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
8527442d6faSDimitry Andric Module *Parent,
8537442d6faSDimitry Andric bool IsFramework,
854dbe13110SDimitry Andric bool IsExplicit) {
855dbe13110SDimitry Andric // Try to find an existing module with this name.
856dbe13110SDimitry Andric if (Module *Sub = lookupModuleQualified(Name, Parent))
857dbe13110SDimitry Andric return std::make_pair(Sub, false);
858dbe13110SDimitry Andric
859dbe13110SDimitry Andric // Create a new module with this name.
8607442d6faSDimitry Andric Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
8617442d6faSDimitry Andric IsExplicit, NumCreatedModules++);
862bfef3995SDimitry Andric if (!Parent) {
8632b6b257fSDimitry Andric if (LangOpts.CurrentModule == Name)
8642b6b257fSDimitry Andric SourceModule = Result;
865dbe13110SDimitry Andric Modules[Name] = Result;
86648675466SDimitry Andric ModuleScopeIDs[Result] = CurrentModuleScopeID;
867bfef3995SDimitry Andric }
868dbe13110SDimitry Andric return std::make_pair(Result, true);
869dbe13110SDimitry Andric }
870dbe13110SDimitry Andric
createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,Module * Parent)87177fc4c14SDimitry Andric Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
87277fc4c14SDimitry Andric Module *Parent) {
87377fc4c14SDimitry Andric auto *Result = new Module("<global>", Loc, Parent, /*IsFramework*/ false,
87477fc4c14SDimitry Andric /*IsExplicit*/ true, NumCreatedModules++);
8757fa27ce4SDimitry Andric Result->Kind = Module::ExplicitGlobalModuleFragment;
87677fc4c14SDimitry Andric // If the created module isn't owned by a parent, send it to PendingSubmodules
87777fc4c14SDimitry Andric // to wait for its parent.
87877fc4c14SDimitry Andric if (!Result->Parent)
87977fc4c14SDimitry Andric PendingSubmodules.emplace_back(Result);
88077fc4c14SDimitry Andric return Result;
881461a67faSDimitry Andric }
882461a67faSDimitry Andric
883b1c73532SDimitry Andric Module *
createImplicitGlobalModuleFragmentForModuleUnit(SourceLocation Loc,Module * Parent)884b1c73532SDimitry Andric ModuleMap::createImplicitGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
885b1c73532SDimitry Andric Module *Parent) {
8867fa27ce4SDimitry Andric assert(Parent && "We should only create an implicit global module fragment "
8877fa27ce4SDimitry Andric "in a module purview");
8887fa27ce4SDimitry Andric // Note: Here the `IsExplicit` parameter refers to the semantics in clang
8897fa27ce4SDimitry Andric // modules. All the non-explicit submodules in clang modules will be exported
8907fa27ce4SDimitry Andric // too. Here we simplify the implementation by using the concept.
891b1c73532SDimitry Andric auto *Result =
892b1c73532SDimitry Andric new Module("<implicit global>", Loc, Parent, /*IsFramework=*/false,
893b1c73532SDimitry Andric /*IsExplicit=*/false, NumCreatedModules++);
8947fa27ce4SDimitry Andric Result->Kind = Module::ImplicitGlobalModuleFragment;
8957fa27ce4SDimitry Andric return Result;
8967fa27ce4SDimitry Andric }
8977fa27ce4SDimitry Andric
89822989816SDimitry Andric Module *
createPrivateModuleFragmentForInterfaceUnit(Module * Parent,SourceLocation Loc)89922989816SDimitry Andric ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
90022989816SDimitry Andric SourceLocation Loc) {
90122989816SDimitry Andric auto *Result =
90222989816SDimitry Andric new Module("<private>", Loc, Parent, /*IsFramework*/ false,
90322989816SDimitry Andric /*IsExplicit*/ true, NumCreatedModules++);
90422989816SDimitry Andric Result->Kind = Module::PrivateModuleFragment;
90522989816SDimitry Andric return Result;
90622989816SDimitry Andric }
90722989816SDimitry Andric
createModuleUnitWithKind(SourceLocation Loc,StringRef Name,Module::ModuleKind Kind)9087fa27ce4SDimitry Andric Module *ModuleMap::createModuleUnitWithKind(SourceLocation Loc, StringRef Name,
9097fa27ce4SDimitry Andric Module::ModuleKind Kind) {
9107fa27ce4SDimitry Andric auto *Result =
9117fa27ce4SDimitry Andric new Module(Name, Loc, nullptr, /*IsFramework*/ false,
9127fa27ce4SDimitry Andric /*IsExplicit*/ false, NumCreatedModules++);
9137fa27ce4SDimitry Andric Result->Kind = Kind;
9147fa27ce4SDimitry Andric
9157fa27ce4SDimitry Andric // Reparent any current global module fragment as a submodule of this module.
9167fa27ce4SDimitry Andric for (auto &Submodule : PendingSubmodules) {
9177fa27ce4SDimitry Andric Submodule->setParent(Result);
9187fa27ce4SDimitry Andric Submodule.release(); // now owned by parent
9197fa27ce4SDimitry Andric }
9207fa27ce4SDimitry Andric PendingSubmodules.clear();
9217fa27ce4SDimitry Andric return Result;
9227fa27ce4SDimitry Andric }
9237fa27ce4SDimitry Andric
createModuleForInterfaceUnit(SourceLocation Loc,StringRef Name)924bab175ecSDimitry Andric Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
925e3b55780SDimitry Andric StringRef Name) {
926bab175ecSDimitry Andric assert(LangOpts.CurrentModule == Name && "module name mismatch");
927bab175ecSDimitry Andric assert(!Modules[Name] && "redefining existing module");
928bab175ecSDimitry Andric
929bab175ecSDimitry Andric auto *Result =
9307fa27ce4SDimitry Andric createModuleUnitWithKind(Loc, Name, Module::ModuleInterfaceUnit);
931bab175ecSDimitry Andric Modules[Name] = SourceModule = Result;
932bab175ecSDimitry Andric
933bab175ecSDimitry Andric // Mark the main source file as being within the newly-created module so that
934bab175ecSDimitry Andric // declarations and macros are properly visibility-restricted to it.
935b1c73532SDimitry Andric auto MainFile = SourceMgr.getFileEntryRefForID(SourceMgr.getMainFileID());
936bab175ecSDimitry Andric assert(MainFile && "no input file for module interface");
937b1c73532SDimitry Andric Headers[*MainFile].push_back(KnownHeader(Result, PrivateHeader));
938bab175ecSDimitry Andric
939bab175ecSDimitry Andric return Result;
940bab175ecSDimitry Andric }
941bab175ecSDimitry Andric
createModuleForImplementationUnit(SourceLocation Loc,StringRef Name)9427fa27ce4SDimitry Andric Module *ModuleMap::createModuleForImplementationUnit(SourceLocation Loc,
9437fa27ce4SDimitry Andric StringRef Name) {
9447fa27ce4SDimitry Andric assert(LangOpts.CurrentModule == Name && "module name mismatch");
9457fa27ce4SDimitry Andric // The interface for this implementation must exist and be loaded.
9467fa27ce4SDimitry Andric assert(Modules[Name] && Modules[Name]->Kind == Module::ModuleInterfaceUnit &&
9477fa27ce4SDimitry Andric "creating implementation module without an interface");
9487fa27ce4SDimitry Andric
9497fa27ce4SDimitry Andric // Create an entry in the modules map to own the implementation unit module.
9507fa27ce4SDimitry Andric // User module names must not start with a period (so that this cannot clash
9517fa27ce4SDimitry Andric // with any legal user-defined module name).
9527fa27ce4SDimitry Andric StringRef IName = ".ImplementationUnit";
9537fa27ce4SDimitry Andric assert(!Modules[IName] && "multiple implementation units?");
9547fa27ce4SDimitry Andric
9557fa27ce4SDimitry Andric auto *Result =
9567fa27ce4SDimitry Andric createModuleUnitWithKind(Loc, Name, Module::ModuleImplementationUnit);
9577fa27ce4SDimitry Andric Modules[IName] = SourceModule = Result;
9587fa27ce4SDimitry Andric
9597fa27ce4SDimitry Andric // Check that the main file is present.
9607fa27ce4SDimitry Andric assert(SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()) &&
9617fa27ce4SDimitry Andric "no input file for module implementation");
9627fa27ce4SDimitry Andric
9637fa27ce4SDimitry Andric return Result;
9647fa27ce4SDimitry Andric }
9657fa27ce4SDimitry Andric
createHeaderUnit(SourceLocation Loc,StringRef Name,Module::Header H)966145449b1SDimitry Andric Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name,
967145449b1SDimitry Andric Module::Header H) {
968145449b1SDimitry Andric assert(LangOpts.CurrentModule == Name && "module name mismatch");
969145449b1SDimitry Andric assert(!Modules[Name] && "redefining existing module");
970145449b1SDimitry Andric
971145449b1SDimitry Andric auto *Result = new Module(Name, Loc, nullptr, /*IsFramework*/ false,
972145449b1SDimitry Andric /*IsExplicit*/ false, NumCreatedModules++);
973145449b1SDimitry Andric Result->Kind = Module::ModuleHeaderUnit;
974145449b1SDimitry Andric Modules[Name] = SourceModule = Result;
975145449b1SDimitry Andric addHeader(Result, H, NormalHeader);
976145449b1SDimitry Andric return Result;
977145449b1SDimitry Andric }
978145449b1SDimitry Andric
97948675466SDimitry Andric /// For a framework module, infer the framework against which we
980809500fcSDimitry Andric /// should link.
inferFrameworkLink(Module * Mod)9817fa27ce4SDimitry Andric static void inferFrameworkLink(Module *Mod) {
982809500fcSDimitry Andric assert(Mod->IsFramework && "Can only infer linking for framework modules");
983809500fcSDimitry Andric assert(!Mod->isSubFramework() &&
984809500fcSDimitry Andric "Can only infer linking for top-level frameworks");
985809500fcSDimitry Andric
986aca2e42cSDimitry Andric StringRef FrameworkName(Mod->Name);
987aca2e42cSDimitry Andric FrameworkName.consume_back("_Private");
988aca2e42cSDimitry Andric Mod->LinkLibraries.push_back(Module::LinkLibrary(FrameworkName.str(),
989809500fcSDimitry Andric /*IsFramework=*/true));
990809500fcSDimitry Andric }
991809500fcSDimitry Andric
inferFrameworkModule(DirectoryEntryRef FrameworkDir,bool IsSystem,Module * Parent)9927fa27ce4SDimitry Andric Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
993c192b3dcSDimitry Andric bool IsSystem, Module *Parent) {
99406d4ba38SDimitry Andric Attributes Attrs;
99506d4ba38SDimitry Andric Attrs.IsSystem = IsSystem;
996c192b3dcSDimitry Andric return inferFrameworkModule(FrameworkDir, Attrs, Parent);
99706d4ba38SDimitry Andric }
99806d4ba38SDimitry Andric
inferFrameworkModule(DirectoryEntryRef FrameworkDir,Attributes Attrs,Module * Parent)9997fa27ce4SDimitry Andric Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
100006d4ba38SDimitry Andric Attributes Attrs, Module *Parent) {
1001c192b3dcSDimitry Andric // Note: as an egregious but useful hack we use the real path here, because
1002c192b3dcSDimitry Andric // we might be looking at an embedded framework that symlinks out to a
1003c192b3dcSDimitry Andric // top-level framework, and we need to infer as if we were naming the
1004c192b3dcSDimitry Andric // top-level framework.
1005c192b3dcSDimitry Andric StringRef FrameworkDirName =
1006c192b3dcSDimitry Andric SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
1007c192b3dcSDimitry Andric
1008c192b3dcSDimitry Andric // In case this is a case-insensitive filesystem, use the canonical
1009c192b3dcSDimitry Andric // directory name as the ModuleName, since modules are case-sensitive.
1010c192b3dcSDimitry Andric // FIXME: we should be able to give a fix-it hint for the correct spelling.
1011c192b3dcSDimitry Andric SmallString<32> ModuleNameStorage;
1012c192b3dcSDimitry Andric StringRef ModuleName = sanitizeFilenameAsIdentifier(
1013c192b3dcSDimitry Andric llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
101406d4ba38SDimitry Andric
1015dbe13110SDimitry Andric // Check whether we've already found this module.
1016dbe13110SDimitry Andric if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
1017dbe13110SDimitry Andric return Mod;
1018dbe13110SDimitry Andric
1019bfef3995SDimitry Andric FileManager &FileMgr = SourceMgr.getFileManager();
1020dbe13110SDimitry Andric
102113cc256eSDimitry Andric // If the framework has a parent path from which we're allowed to infer
102213cc256eSDimitry Andric // a framework module, do so.
1023ac9a064cSDimitry Andric FileID ModuleMapFID;
102413cc256eSDimitry Andric if (!Parent) {
1025809500fcSDimitry Andric // Determine whether we're allowed to infer a module map.
102613cc256eSDimitry Andric bool canInfer = false;
1027809500fcSDimitry Andric if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
102813cc256eSDimitry Andric // Figure out the parent path.
1029809500fcSDimitry Andric StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
10307fa27ce4SDimitry Andric if (auto ParentDir = FileMgr.getOptionalDirectoryRef(Parent)) {
103113cc256eSDimitry Andric // Check whether we have already looked into the parent directory
103213cc256eSDimitry Andric // for a module map.
1033809500fcSDimitry Andric llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
1034519fc96cSDimitry Andric inferred = InferredDirectories.find(*ParentDir);
103513cc256eSDimitry Andric if (inferred == InferredDirectories.end()) {
103613cc256eSDimitry Andric // We haven't looked here before. Load a module map, if there is
103713cc256eSDimitry Andric // one.
1038312c0ed1SDimitry Andric bool IsFrameworkDir = Parent.ends_with(".framework");
10397fa27ce4SDimitry Andric if (OptionalFileEntryRef ModMapFile =
1040519fc96cSDimitry Andric HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) {
10417fa27ce4SDimitry Andric parseModuleMapFile(*ModMapFile, Attrs.IsSystem, *ParentDir);
1042519fc96cSDimitry Andric inferred = InferredDirectories.find(*ParentDir);
104313cc256eSDimitry Andric }
104413cc256eSDimitry Andric
104513cc256eSDimitry Andric if (inferred == InferredDirectories.end())
104613cc256eSDimitry Andric inferred = InferredDirectories.insert(
1047519fc96cSDimitry Andric std::make_pair(*ParentDir, InferredDirectory())).first;
104813cc256eSDimitry Andric }
104913cc256eSDimitry Andric
105013cc256eSDimitry Andric if (inferred->second.InferModules) {
105113cc256eSDimitry Andric // We're allowed to infer for this directory, but make sure it's okay
105213cc256eSDimitry Andric // to infer this particular module.
1053809500fcSDimitry Andric StringRef Name = llvm::sys::path::stem(FrameworkDirName);
1054c0981da4SDimitry Andric canInfer =
1055c0981da4SDimitry Andric !llvm::is_contained(inferred->second.ExcludedModules, Name);
105613cc256eSDimitry Andric
105706d4ba38SDimitry Andric Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
105806d4ba38SDimitry Andric Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
105906d4ba38SDimitry Andric Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
1060bab175ecSDimitry Andric Attrs.NoUndeclaredIncludes |=
1061bab175ecSDimitry Andric inferred->second.Attrs.NoUndeclaredIncludes;
1062ac9a064cSDimitry Andric ModuleMapFID = inferred->second.ModuleMapFID;
106313cc256eSDimitry Andric }
106413cc256eSDimitry Andric }
106513cc256eSDimitry Andric }
106613cc256eSDimitry Andric
106713cc256eSDimitry Andric // If we're not allowed to infer a framework module, don't.
106813cc256eSDimitry Andric if (!canInfer)
10699f4dbff6SDimitry Andric return nullptr;
1070e3b55780SDimitry Andric } else {
1071ac9a064cSDimitry Andric ModuleMapFID = getModuleMapFileIDForUniquing(Parent);
1072e3b55780SDimitry Andric }
107313cc256eSDimitry Andric
1074dbe13110SDimitry Andric // Look for an umbrella header.
10757fa27ce4SDimitry Andric SmallString<128> UmbrellaName = FrameworkDir.getName();
1076bfef3995SDimitry Andric llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
1077e3b55780SDimitry Andric auto UmbrellaHeader = FileMgr.getOptionalFileRef(UmbrellaName);
1078dbe13110SDimitry Andric
1079dbe13110SDimitry Andric // FIXME: If there's no umbrella header, we could probably scan the
1080dbe13110SDimitry Andric // framework to load *everything*. But, it's not clear that this is a good
1081dbe13110SDimitry Andric // idea.
1082dbe13110SDimitry Andric if (!UmbrellaHeader)
10839f4dbff6SDimitry Andric return nullptr;
1084dbe13110SDimitry Andric
108506d4ba38SDimitry Andric Module *Result = new Module(ModuleName, SourceLocation(), Parent,
10865e20cdd8SDimitry Andric /*IsFramework=*/true, /*IsExplicit=*/false,
10875e20cdd8SDimitry Andric NumCreatedModules++);
1088ac9a064cSDimitry Andric InferredModuleAllowedBy[Result] = ModuleMapFID;
108906d4ba38SDimitry Andric Result->IsInferred = true;
10902b6b257fSDimitry Andric if (!Parent) {
10912b6b257fSDimitry Andric if (LangOpts.CurrentModule == ModuleName)
1092bfef3995SDimitry Andric SourceModule = Result;
10932b6b257fSDimitry Andric Modules[ModuleName] = Result;
109448675466SDimitry Andric ModuleScopeIDs[Result] = CurrentModuleScopeID;
1095bfef3995SDimitry Andric }
109606d4ba38SDimitry Andric
109706d4ba38SDimitry Andric Result->IsSystem |= Attrs.IsSystem;
109806d4ba38SDimitry Andric Result->IsExternC |= Attrs.IsExternC;
109906d4ba38SDimitry Andric Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
1100bab175ecSDimitry Andric Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
11015e20cdd8SDimitry Andric Result->Directory = FrameworkDir;
1102dbe13110SDimitry Andric
1103344a3780SDimitry Andric // Chop off the first framework bit, as that is implied.
1104344a3780SDimitry Andric StringRef RelativePath = UmbrellaName.str().substr(
1105344a3780SDimitry Andric Result->getTopLevelModule()->Directory->getName().size());
1106344a3780SDimitry Andric RelativePath = llvm::sys::path::relative_path(RelativePath);
1107344a3780SDimitry Andric
1108dbe13110SDimitry Andric // umbrella header "umbrella-header-name"
11097fa27ce4SDimitry Andric setUmbrellaHeaderAsWritten(Result, *UmbrellaHeader, ModuleName + ".h",
11107fa27ce4SDimitry Andric RelativePath);
1111dbe13110SDimitry Andric
1112dbe13110SDimitry Andric // export *
11139f4dbff6SDimitry Andric Result->Exports.push_back(Module::ExportDecl(nullptr, true));
1114dbe13110SDimitry Andric
1115dbe13110SDimitry Andric // module * { export * }
1116dbe13110SDimitry Andric Result->InferSubmodules = true;
1117dbe13110SDimitry Andric Result->InferExportWildcard = true;
1118dbe13110SDimitry Andric
1119dbe13110SDimitry Andric // Look for subframeworks.
11209f4dbff6SDimitry Andric std::error_code EC;
11217fa27ce4SDimitry Andric SmallString<128> SubframeworksDirName = FrameworkDir.getName();
1122dbe13110SDimitry Andric llvm::sys::path::append(SubframeworksDirName, "Frameworks");
1123bfef3995SDimitry Andric llvm::sys::path::native(SubframeworksDirName);
112422989816SDimitry Andric llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
1125676fbe81SDimitry Andric for (llvm::vfs::directory_iterator
1126676fbe81SDimitry Andric Dir = FS.dir_begin(SubframeworksDirName, EC),
11272b6b257fSDimitry Andric DirEnd;
1128dbe13110SDimitry Andric Dir != DirEnd && !EC; Dir.increment(EC)) {
1129312c0ed1SDimitry Andric if (!StringRef(Dir->path()).ends_with(".framework"))
1130dbe13110SDimitry Andric continue;
1131dbe13110SDimitry Andric
11327fa27ce4SDimitry Andric if (auto SubframeworkDir = FileMgr.getOptionalDirectoryRef(Dir->path())) {
113313cc256eSDimitry Andric // Note: as an egregious but useful hack, we use the real path here and
113413cc256eSDimitry Andric // check whether it is actually a subdirectory of the parent directory.
113513cc256eSDimitry Andric // This will not be the case if the 'subframework' is actually a symlink
113613cc256eSDimitry Andric // out to a top-level framework.
1137519fc96cSDimitry Andric StringRef SubframeworkDirName =
1138519fc96cSDimitry Andric FileMgr.getCanonicalName(*SubframeworkDir);
113913cc256eSDimitry Andric bool FoundParent = false;
114013cc256eSDimitry Andric do {
114113cc256eSDimitry Andric // Get the parent directory name.
114213cc256eSDimitry Andric SubframeworkDirName
114313cc256eSDimitry Andric = llvm::sys::path::parent_path(SubframeworkDirName);
114413cc256eSDimitry Andric if (SubframeworkDirName.empty())
114513cc256eSDimitry Andric break;
114613cc256eSDimitry Andric
1147519fc96cSDimitry Andric if (auto SubDir = FileMgr.getDirectory(SubframeworkDirName)) {
1148519fc96cSDimitry Andric if (*SubDir == FrameworkDir) {
114913cc256eSDimitry Andric FoundParent = true;
115013cc256eSDimitry Andric break;
115113cc256eSDimitry Andric }
1152519fc96cSDimitry Andric }
115313cc256eSDimitry Andric } while (true);
115413cc256eSDimitry Andric
115513cc256eSDimitry Andric if (!FoundParent)
115613cc256eSDimitry Andric continue;
115713cc256eSDimitry Andric
1158dbe13110SDimitry Andric // FIXME: Do we want to warn about subframeworks without umbrella headers?
1159519fc96cSDimitry Andric inferFrameworkModule(*SubframeworkDir, Attrs, Result);
1160dbe13110SDimitry Andric }
1161dbe13110SDimitry Andric }
1162dbe13110SDimitry Andric
1163809500fcSDimitry Andric // If the module is a top-level framework, automatically link against the
1164809500fcSDimitry Andric // framework.
11657fa27ce4SDimitry Andric if (!Result->isSubFramework())
11667fa27ce4SDimitry Andric inferFrameworkLink(Result);
1167809500fcSDimitry Andric
1168dbe13110SDimitry Andric return Result;
1169dbe13110SDimitry Andric }
1170dbe13110SDimitry Andric
createShadowedModule(StringRef Name,bool IsFramework,Module * ShadowingModule)117148675466SDimitry Andric Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
117248675466SDimitry Andric Module *ShadowingModule) {
117348675466SDimitry Andric
117448675466SDimitry Andric // Create a new module with this name.
117548675466SDimitry Andric Module *Result =
117648675466SDimitry Andric new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
117748675466SDimitry Andric /*IsExplicit=*/false, NumCreatedModules++);
117848675466SDimitry Andric Result->ShadowingModule = ShadowingModule;
1179cfca06d7SDimitry Andric Result->markUnavailable(/*Unimportable*/true);
118048675466SDimitry Andric ModuleScopeIDs[Result] = CurrentModuleScopeID;
118148675466SDimitry Andric ShadowModules.push_back(Result);
118248675466SDimitry Andric
118348675466SDimitry Andric return Result;
118448675466SDimitry Andric }
118548675466SDimitry Andric
setUmbrellaHeaderAsWritten(Module * Mod,FileEntryRef UmbrellaHeader,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)11867fa27ce4SDimitry Andric void ModuleMap::setUmbrellaHeaderAsWritten(
1187e3b55780SDimitry Andric Module *Mod, FileEntryRef UmbrellaHeader, const Twine &NameAsWritten,
1188344a3780SDimitry Andric const Twine &PathRelativeToRootModuleDirectory) {
1189bfef3995SDimitry Andric Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
11907fa27ce4SDimitry Andric Mod->Umbrella = UmbrellaHeader;
11915e20cdd8SDimitry Andric Mod->UmbrellaAsWritten = NameAsWritten.str();
1192344a3780SDimitry Andric Mod->UmbrellaRelativeToRootModuleDirectory =
1193344a3780SDimitry Andric PathRelativeToRootModuleDirectory.str();
1194e3b55780SDimitry Andric UmbrellaDirs[UmbrellaHeader.getDir()] = Mod;
11952b6b257fSDimitry Andric
11962b6b257fSDimitry Andric // Notify callbacks that we just added a new header.
11972b6b257fSDimitry Andric for (const auto &Cb : Callbacks)
11987fa27ce4SDimitry Andric Cb->moduleMapAddUmbrellaHeader(UmbrellaHeader);
1199dbe13110SDimitry Andric }
1200dbe13110SDimitry Andric
setUmbrellaDirAsWritten(Module * Mod,DirectoryEntryRef UmbrellaDir,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)12017fa27ce4SDimitry Andric void ModuleMap::setUmbrellaDirAsWritten(
12027fa27ce4SDimitry Andric Module *Mod, DirectoryEntryRef UmbrellaDir, const Twine &NameAsWritten,
1203344a3780SDimitry Andric const Twine &PathRelativeToRootModuleDirectory) {
1204344a3780SDimitry Andric Mod->Umbrella = UmbrellaDir;
12055e20cdd8SDimitry Andric Mod->UmbrellaAsWritten = NameAsWritten.str();
1206344a3780SDimitry Andric Mod->UmbrellaRelativeToRootModuleDirectory =
1207344a3780SDimitry Andric PathRelativeToRootModuleDirectory.str();
1208dbe13110SDimitry Andric UmbrellaDirs[UmbrellaDir] = Mod;
1209dbe13110SDimitry Andric }
1210dbe13110SDimitry Andric
addUnresolvedHeader(Module * Mod,Module::UnresolvedHeaderDirective Header,bool & NeedsFramework)1211551c6985SDimitry Andric void ModuleMap::addUnresolvedHeader(Module *Mod,
121248675466SDimitry Andric Module::UnresolvedHeaderDirective Header,
121348675466SDimitry Andric bool &NeedsFramework) {
1214551c6985SDimitry Andric // If there is a builtin counterpart to this file, add it now so it can
1215551c6985SDimitry Andric // wrap the system header.
1216551c6985SDimitry Andric if (resolveAsBuiltinHeader(Mod, Header)) {
1217551c6985SDimitry Andric // If we have both a builtin and system version of the file, the
1218551c6985SDimitry Andric // builtin version may want to inject macros into the system header, so
1219551c6985SDimitry Andric // force the system header to be treated as a textual header in this
1220551c6985SDimitry Andric // case.
1221551c6985SDimitry Andric Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
1222551c6985SDimitry Andric headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
1223551c6985SDimitry Andric Header.HasBuiltinHeader = true;
1224809500fcSDimitry Andric }
1225551c6985SDimitry Andric
1226551c6985SDimitry Andric // If possible, don't stat the header until we need to. This requires the
1227551c6985SDimitry Andric // user to have provided us with some stat information about the file.
1228551c6985SDimitry Andric // FIXME: Add support for lazily stat'ing umbrella headers and excluded
1229551c6985SDimitry Andric // headers.
1230551c6985SDimitry Andric if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
1231551c6985SDimitry Andric Header.Kind != Module::HK_Excluded) {
1232551c6985SDimitry Andric // We expect more variation in mtime than size, so if we're given both,
1233551c6985SDimitry Andric // use the mtime as the key.
1234551c6985SDimitry Andric if (Header.ModTime)
1235551c6985SDimitry Andric LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
1236551c6985SDimitry Andric else
1237551c6985SDimitry Andric LazyHeadersBySize[*Header.Size].push_back(Mod);
1238551c6985SDimitry Andric Mod->UnresolvedHeaders.push_back(Header);
1239551c6985SDimitry Andric return;
1240551c6985SDimitry Andric }
1241551c6985SDimitry Andric
1242551c6985SDimitry Andric // We don't have stat information or can't defer looking this file up.
1243551c6985SDimitry Andric // Perform the lookup now.
124448675466SDimitry Andric resolveHeader(Mod, Header, NeedsFramework);
1245551c6985SDimitry Andric }
1246551c6985SDimitry Andric
resolveHeaderDirectives(const FileEntry * File) const1247551c6985SDimitry Andric void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
1248551c6985SDimitry Andric auto BySize = LazyHeadersBySize.find(File->getSize());
1249551c6985SDimitry Andric if (BySize != LazyHeadersBySize.end()) {
1250551c6985SDimitry Andric for (auto *M : BySize->second)
1251145449b1SDimitry Andric resolveHeaderDirectives(M, File);
1252551c6985SDimitry Andric LazyHeadersBySize.erase(BySize);
1253551c6985SDimitry Andric }
1254551c6985SDimitry Andric
1255551c6985SDimitry Andric auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
1256551c6985SDimitry Andric if (ByModTime != LazyHeadersByModTime.end()) {
1257551c6985SDimitry Andric for (auto *M : ByModTime->second)
1258145449b1SDimitry Andric resolveHeaderDirectives(M, File);
1259551c6985SDimitry Andric LazyHeadersByModTime.erase(ByModTime);
1260551c6985SDimitry Andric }
1261551c6985SDimitry Andric }
1262551c6985SDimitry Andric
resolveHeaderDirectives(Module * Mod,std::optional<const FileEntry * > File) const1263145449b1SDimitry Andric void ModuleMap::resolveHeaderDirectives(
1264e3b55780SDimitry Andric Module *Mod, std::optional<const FileEntry *> File) const {
126548675466SDimitry Andric bool NeedsFramework = false;
1266145449b1SDimitry Andric SmallVector<Module::UnresolvedHeaderDirective, 1> NewHeaders;
1267e3b55780SDimitry Andric const auto Size = File ? (*File)->getSize() : 0;
1268e3b55780SDimitry Andric const auto ModTime = File ? (*File)->getModificationTime() : 0;
1269145449b1SDimitry Andric
1270145449b1SDimitry Andric for (auto &Header : Mod->UnresolvedHeaders) {
1271145449b1SDimitry Andric if (File && ((Header.ModTime && Header.ModTime != ModTime) ||
1272145449b1SDimitry Andric (Header.Size && Header.Size != Size)))
1273145449b1SDimitry Andric NewHeaders.push_back(Header);
1274145449b1SDimitry Andric else
1275551c6985SDimitry Andric // This operation is logically const; we're just changing how we represent
1276551c6985SDimitry Andric // the header information for this file.
127748675466SDimitry Andric const_cast<ModuleMap *>(this)->resolveHeader(Mod, Header, NeedsFramework);
1278145449b1SDimitry Andric }
1279145449b1SDimitry Andric Mod->UnresolvedHeaders.swap(NewHeaders);
128006d4ba38SDimitry Andric }
128106d4ba38SDimitry Andric
addHeader(Module * Mod,Module::Header Header,ModuleHeaderRole Role,bool Imported)128206d4ba38SDimitry Andric void ModuleMap::addHeader(Module *Mod, Module::Header Header,
128345b53394SDimitry Andric ModuleHeaderRole Role, bool Imported) {
128445b53394SDimitry Andric KnownHeader KH(Mod, Role);
128545b53394SDimitry Andric
128645b53394SDimitry Andric // Only add each header to the headers list once.
128745b53394SDimitry Andric // FIXME: Should we diagnose if a header is listed twice in the
128845b53394SDimitry Andric // same module definition?
128945b53394SDimitry Andric auto &HeaderList = Headers[Header.Entry];
1290c0981da4SDimitry Andric if (llvm::is_contained(HeaderList, KH))
129145b53394SDimitry Andric return;
129245b53394SDimitry Andric
129345b53394SDimitry Andric HeaderList.push_back(KH);
1294bab175ecSDimitry Andric Mod->Headers[headerRoleToKind(Role)].push_back(Header);
129545b53394SDimitry Andric
1296b1c73532SDimitry Andric bool isCompilingModuleHeader = Mod->isForBuilding(LangOpts);
129745b53394SDimitry Andric if (!Imported || isCompilingModuleHeader) {
129845b53394SDimitry Andric // When we import HeaderFileInfo, the external source is expected to
129945b53394SDimitry Andric // set the isModuleHeader flag itself.
130006d4ba38SDimitry Andric HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
130106d4ba38SDimitry Andric isCompilingModuleHeader);
130206d4ba38SDimitry Andric }
13032b6b257fSDimitry Andric
13042b6b257fSDimitry Andric // Notify callbacks that we just added a new header.
13052b6b257fSDimitry Andric for (const auto &Cb : Callbacks)
13067fa27ce4SDimitry Andric Cb->moduleMapAddHeader(Header.Entry.getName());
130706d4ba38SDimitry Andric }
130806d4ba38SDimitry Andric
getContainingModuleMapFileID(const Module * Module) const1309ac9a064cSDimitry Andric FileID ModuleMap::getContainingModuleMapFileID(const Module *Module) const {
1310bfef3995SDimitry Andric if (Module->DefinitionLoc.isInvalid())
1311ac9a064cSDimitry Andric return {};
1312dbe13110SDimitry Andric
1313ac9a064cSDimitry Andric return SourceMgr.getFileID(Module->DefinitionLoc);
1314dbe13110SDimitry Andric }
1315dbe13110SDimitry Andric
1316e3b55780SDimitry Andric OptionalFileEntryRef
getContainingModuleMapFile(const Module * Module) const1317ac9a064cSDimitry Andric ModuleMap::getContainingModuleMapFile(const Module *Module) const {
1318ac9a064cSDimitry Andric return SourceMgr.getFileEntryRefForID(getContainingModuleMapFileID(Module));
1319ac9a064cSDimitry Andric }
1320ac9a064cSDimitry Andric
getModuleMapFileIDForUniquing(const Module * M) const1321ac9a064cSDimitry Andric FileID ModuleMap::getModuleMapFileIDForUniquing(const Module *M) const {
132206d4ba38SDimitry Andric if (M->IsInferred) {
132306d4ba38SDimitry Andric assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
1324b1c73532SDimitry Andric return InferredModuleAllowedBy.find(M)->second;
132506d4ba38SDimitry Andric }
1326ac9a064cSDimitry Andric return getContainingModuleMapFileID(M);
132706d4ba38SDimitry Andric }
132806d4ba38SDimitry Andric
1329ac9a064cSDimitry Andric OptionalFileEntryRef
getModuleMapFileForUniquing(const Module * M) const1330ac9a064cSDimitry Andric ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
1331ac9a064cSDimitry Andric return SourceMgr.getFileEntryRefForID(getModuleMapFileIDForUniquing(M));
1332ac9a064cSDimitry Andric }
1333ac9a064cSDimitry Andric
setInferredModuleAllowedBy(Module * M,FileID ModMapFID)1334ac9a064cSDimitry Andric void ModuleMap::setInferredModuleAllowedBy(Module *M, FileID ModMapFID) {
133506d4ba38SDimitry Andric assert(M->IsInferred && "module not inferred");
1336ac9a064cSDimitry Andric InferredModuleAllowedBy[M] = ModMapFID;
133706d4ba38SDimitry Andric }
133806d4ba38SDimitry Andric
1339e3b55780SDimitry Andric std::error_code
canonicalizeModuleMapPath(SmallVectorImpl<char> & Path)1340e3b55780SDimitry Andric ModuleMap::canonicalizeModuleMapPath(SmallVectorImpl<char> &Path) {
1341e3b55780SDimitry Andric StringRef Dir = llvm::sys::path::parent_path({Path.data(), Path.size()});
1342e3b55780SDimitry Andric
1343e3b55780SDimitry Andric // Do not canonicalize within the framework; the module map parser expects
1344e3b55780SDimitry Andric // Modules/ not Versions/A/Modules.
1345e3b55780SDimitry Andric if (llvm::sys::path::filename(Dir) == "Modules") {
1346e3b55780SDimitry Andric StringRef Parent = llvm::sys::path::parent_path(Dir);
1347312c0ed1SDimitry Andric if (Parent.ends_with(".framework"))
1348e3b55780SDimitry Andric Dir = Parent;
1349e3b55780SDimitry Andric }
1350e3b55780SDimitry Andric
1351e3b55780SDimitry Andric FileManager &FM = SourceMgr.getFileManager();
13527fa27ce4SDimitry Andric auto DirEntry = FM.getDirectoryRef(Dir.empty() ? "." : Dir);
1353e3b55780SDimitry Andric if (!DirEntry)
13547fa27ce4SDimitry Andric return llvm::errorToErrorCode(DirEntry.takeError());
1355e3b55780SDimitry Andric
1356e3b55780SDimitry Andric // Canonicalize the directory.
1357e3b55780SDimitry Andric StringRef CanonicalDir = FM.getCanonicalName(*DirEntry);
13587fa27ce4SDimitry Andric if (CanonicalDir != Dir)
13597fa27ce4SDimitry Andric llvm::sys::path::replace_path_prefix(Path, Dir, CanonicalDir);
1360e3b55780SDimitry Andric
1361e3b55780SDimitry Andric // In theory, the filename component should also be canonicalized if it
1362e3b55780SDimitry Andric // on a case-insensitive filesystem. However, the extra canonicalization is
1363e3b55780SDimitry Andric // expensive and if clang looked up the filename it will always be lowercase.
1364e3b55780SDimitry Andric
1365e3b55780SDimitry Andric // Remove ., remove redundant separators, and switch to native separators.
1366e3b55780SDimitry Andric // This is needed for separators between CanonicalDir and the filename.
1367e3b55780SDimitry Andric llvm::sys::path::remove_dots(Path);
1368e3b55780SDimitry Andric
1369e3b55780SDimitry Andric return std::error_code();
1370e3b55780SDimitry Andric }
1371e3b55780SDimitry Andric
addAdditionalModuleMapFile(const Module * M,FileEntryRef ModuleMap)1372cfca06d7SDimitry Andric void ModuleMap::addAdditionalModuleMapFile(const Module *M,
1373b1c73532SDimitry Andric FileEntryRef ModuleMap) {
1374cfca06d7SDimitry Andric AdditionalModMaps[M].insert(ModuleMap);
1375cfca06d7SDimitry Andric }
1376cfca06d7SDimitry Andric
dump()13772b6b257fSDimitry Andric LLVM_DUMP_METHOD void ModuleMap::dump() {
1378dbe13110SDimitry Andric llvm::errs() << "Modules:";
1379dbe13110SDimitry Andric for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
1380dbe13110SDimitry Andric MEnd = Modules.end();
1381dbe13110SDimitry Andric M != MEnd; ++M)
1382dbe13110SDimitry Andric M->getValue()->print(llvm::errs(), 2);
1383dbe13110SDimitry Andric
1384dbe13110SDimitry Andric llvm::errs() << "Headers:";
138513cc256eSDimitry Andric for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
1386dbe13110SDimitry Andric H != HEnd; ++H) {
1387b1c73532SDimitry Andric llvm::errs() << " \"" << H->first.getName() << "\" -> ";
1388bfef3995SDimitry Andric for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
1389bfef3995SDimitry Andric E = H->second.end();
1390bfef3995SDimitry Andric I != E; ++I) {
1391bfef3995SDimitry Andric if (I != H->second.begin())
1392bfef3995SDimitry Andric llvm::errs() << ",";
1393bfef3995SDimitry Andric llvm::errs() << I->getModule()->getFullModuleName();
1394bfef3995SDimitry Andric }
1395bfef3995SDimitry Andric llvm::errs() << "\n";
1396dbe13110SDimitry Andric }
1397dbe13110SDimitry Andric }
1398dbe13110SDimitry Andric
resolveExports(Module * Mod,bool Complain)1399dbe13110SDimitry Andric bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
14005e20cdd8SDimitry Andric auto Unresolved = std::move(Mod->UnresolvedExports);
14015e20cdd8SDimitry Andric Mod->UnresolvedExports.clear();
14025e20cdd8SDimitry Andric for (auto &UE : Unresolved) {
14035e20cdd8SDimitry Andric Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
1404dbe13110SDimitry Andric if (Export.getPointer() || Export.getInt())
1405dbe13110SDimitry Andric Mod->Exports.push_back(Export);
1406dbe13110SDimitry Andric else
14075e20cdd8SDimitry Andric Mod->UnresolvedExports.push_back(UE);
1408dbe13110SDimitry Andric }
14095e20cdd8SDimitry Andric return !Mod->UnresolvedExports.empty();
1410dbe13110SDimitry Andric }
1411dbe13110SDimitry Andric
resolveUses(Module * Mod,bool Complain)1412bfef3995SDimitry Andric bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
1413b1c73532SDimitry Andric auto *Top = Mod->getTopLevelModule();
1414b1c73532SDimitry Andric auto Unresolved = std::move(Top->UnresolvedDirectUses);
1415b1c73532SDimitry Andric Top->UnresolvedDirectUses.clear();
14165e20cdd8SDimitry Andric for (auto &UDU : Unresolved) {
1417b1c73532SDimitry Andric Module *DirectUse = resolveModuleId(UDU, Top, Complain);
1418bfef3995SDimitry Andric if (DirectUse)
1419b1c73532SDimitry Andric Top->DirectUses.push_back(DirectUse);
1420bfef3995SDimitry Andric else
1421b1c73532SDimitry Andric Top->UnresolvedDirectUses.push_back(UDU);
1422bfef3995SDimitry Andric }
1423b1c73532SDimitry Andric return !Top->UnresolvedDirectUses.empty();
1424bfef3995SDimitry Andric }
1425bfef3995SDimitry Andric
resolveConflicts(Module * Mod,bool Complain)1426809500fcSDimitry Andric bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
14275e20cdd8SDimitry Andric auto Unresolved = std::move(Mod->UnresolvedConflicts);
14285e20cdd8SDimitry Andric Mod->UnresolvedConflicts.clear();
14295e20cdd8SDimitry Andric for (auto &UC : Unresolved) {
14305e20cdd8SDimitry Andric if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
1431809500fcSDimitry Andric Module::Conflict Conflict;
1432809500fcSDimitry Andric Conflict.Other = OtherMod;
14335e20cdd8SDimitry Andric Conflict.Message = UC.Message;
1434809500fcSDimitry Andric Mod->Conflicts.push_back(Conflict);
14355e20cdd8SDimitry Andric } else
14365e20cdd8SDimitry Andric Mod->UnresolvedConflicts.push_back(UC);
1437809500fcSDimitry Andric }
14385e20cdd8SDimitry Andric return !Mod->UnresolvedConflicts.empty();
1439809500fcSDimitry Andric }
1440809500fcSDimitry Andric
1441dbe13110SDimitry Andric //----------------------------------------------------------------------------//
1442dbe13110SDimitry Andric // Module map file parser
1443dbe13110SDimitry Andric //----------------------------------------------------------------------------//
1444dbe13110SDimitry Andric
1445dbe13110SDimitry Andric namespace clang {
1446461a67faSDimitry Andric
144748675466SDimitry Andric /// A token in a module map file.
1448dbe13110SDimitry Andric struct MMToken {
1449dbe13110SDimitry Andric enum TokenKind {
1450dbe13110SDimitry Andric Comma,
1451809500fcSDimitry Andric ConfigMacros,
1452809500fcSDimitry Andric Conflict,
1453dbe13110SDimitry Andric EndOfFile,
1454dbe13110SDimitry Andric HeaderKeyword,
1455dbe13110SDimitry Andric Identifier,
1456bfef3995SDimitry Andric Exclaim,
145713cc256eSDimitry Andric ExcludeKeyword,
1458dbe13110SDimitry Andric ExplicitKeyword,
1459dbe13110SDimitry Andric ExportKeyword,
1460461a67faSDimitry Andric ExportAsKeyword,
1461bfef3995SDimitry Andric ExternKeyword,
1462dbe13110SDimitry Andric FrameworkKeyword,
1463809500fcSDimitry Andric LinkKeyword,
1464dbe13110SDimitry Andric ModuleKeyword,
1465dbe13110SDimitry Andric Period,
1466bfef3995SDimitry Andric PrivateKeyword,
1467dbe13110SDimitry Andric UmbrellaKeyword,
1468bfef3995SDimitry Andric UseKeyword,
1469dbe13110SDimitry Andric RequiresKeyword,
1470dbe13110SDimitry Andric Star,
1471dbe13110SDimitry Andric StringLiteral,
1472551c6985SDimitry Andric IntegerLiteral,
147306d4ba38SDimitry Andric TextualKeyword,
1474dbe13110SDimitry Andric LBrace,
1475dbe13110SDimitry Andric RBrace,
1476dbe13110SDimitry Andric LSquare,
1477dbe13110SDimitry Andric RSquare
1478dbe13110SDimitry Andric } Kind;
1479dbe13110SDimitry Andric
1480344a3780SDimitry Andric SourceLocation::UIntTy Location;
1481dbe13110SDimitry Andric unsigned StringLength;
1482551c6985SDimitry Andric union {
1483551c6985SDimitry Andric // If Kind != IntegerLiteral.
1484dbe13110SDimitry Andric const char *StringData;
1485461a67faSDimitry Andric
1486551c6985SDimitry Andric // If Kind == IntegerLiteral.
1487551c6985SDimitry Andric uint64_t IntegerValue;
1488551c6985SDimitry Andric };
1489dbe13110SDimitry Andric
clearclang::MMToken1490dbe13110SDimitry Andric void clear() {
1491dbe13110SDimitry Andric Kind = EndOfFile;
1492dbe13110SDimitry Andric Location = 0;
1493dbe13110SDimitry Andric StringLength = 0;
14949f4dbff6SDimitry Andric StringData = nullptr;
1495dbe13110SDimitry Andric }
1496dbe13110SDimitry Andric
isclang::MMToken1497dbe13110SDimitry Andric bool is(TokenKind K) const { return Kind == K; }
1498dbe13110SDimitry Andric
getLocationclang::MMToken1499dbe13110SDimitry Andric SourceLocation getLocation() const {
1500dbe13110SDimitry Andric return SourceLocation::getFromRawEncoding(Location);
1501dbe13110SDimitry Andric }
1502dbe13110SDimitry Andric
getIntegerclang::MMToken1503551c6985SDimitry Andric uint64_t getInteger() const {
1504551c6985SDimitry Andric return Kind == IntegerLiteral ? IntegerValue : 0;
1505551c6985SDimitry Andric }
1506551c6985SDimitry Andric
getStringclang::MMToken1507dbe13110SDimitry Andric StringRef getString() const {
1508551c6985SDimitry Andric return Kind == IntegerLiteral ? StringRef()
1509551c6985SDimitry Andric : StringRef(StringData, StringLength);
1510dbe13110SDimitry Andric }
1511dbe13110SDimitry Andric };
1512dbe13110SDimitry Andric
1513dbe13110SDimitry Andric class ModuleMapParser {
1514dbe13110SDimitry Andric Lexer &L;
1515dbe13110SDimitry Andric SourceManager &SourceMgr;
151613cc256eSDimitry Andric
151748675466SDimitry Andric /// Default target information, used only for string literal
151813cc256eSDimitry Andric /// parsing.
151913cc256eSDimitry Andric const TargetInfo *Target;
152013cc256eSDimitry Andric
1521dbe13110SDimitry Andric DiagnosticsEngine &Diags;
1522dbe13110SDimitry Andric ModuleMap ⤅
1523dbe13110SDimitry Andric
152448675466SDimitry Andric /// The current module map file.
1525ac9a064cSDimitry Andric FileID ModuleMapFID;
15269f4dbff6SDimitry Andric
152748675466SDimitry Andric /// Source location of most recent parsed module declaration
152848675466SDimitry Andric SourceLocation CurrModuleDeclLoc;
152948675466SDimitry Andric
153048675466SDimitry Andric /// The directory that file names in this module map file should
153106d4ba38SDimitry Andric /// be resolved relative to.
15327fa27ce4SDimitry Andric DirectoryEntryRef Directory;
1533dbe13110SDimitry Andric
153448675466SDimitry Andric /// Whether this module map is in a system header directory.
1535bfef3995SDimitry Andric bool IsSystem;
1536bfef3995SDimitry Andric
153748675466SDimitry Andric /// Whether an error occurred.
1538461a67faSDimitry Andric bool HadError = false;
1539dbe13110SDimitry Andric
154048675466SDimitry Andric /// Stores string data for the various string literals referenced
1541dbe13110SDimitry Andric /// during parsing.
1542dbe13110SDimitry Andric llvm::BumpPtrAllocator StringData;
1543dbe13110SDimitry Andric
154448675466SDimitry Andric /// The current token.
1545dbe13110SDimitry Andric MMToken Tok;
1546dbe13110SDimitry Andric
154748675466SDimitry Andric /// The active module.
1548461a67faSDimitry Andric Module *ActiveModule = nullptr;
1549dbe13110SDimitry Andric
155048675466SDimitry Andric /// Whether a module uses the 'requires excluded' hack to mark its
155145b53394SDimitry Andric /// contents as 'textual'.
155245b53394SDimitry Andric ///
155345b53394SDimitry Andric /// On older Darwin SDK versions, 'requires excluded' is used to mark the
155445b53394SDimitry Andric /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
155545b53394SDimitry Andric /// non-modular headers. For backwards compatibility, we continue to
155645b53394SDimitry Andric /// support this idiom for just these modules, and map the headers to
155745b53394SDimitry Andric /// 'textual' to match the original intent.
155845b53394SDimitry Andric llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
155945b53394SDimitry Andric
156048675466SDimitry Andric /// Consume the current token and return its location.
1561dbe13110SDimitry Andric SourceLocation consumeToken();
1562dbe13110SDimitry Andric
156348675466SDimitry Andric /// Skip tokens until we reach the a token with the given kind
1564dbe13110SDimitry Andric /// (or the end of the file).
1565dbe13110SDimitry Andric void skipUntil(MMToken::TokenKind K);
1566dbe13110SDimitry Andric
1567dbe13110SDimitry Andric bool parseModuleId(ModuleId &Id);
1568dbe13110SDimitry Andric void parseModuleDecl();
1569bfef3995SDimitry Andric void parseExternModuleDecl();
1570dbe13110SDimitry Andric void parseRequiresDecl();
1571461a67faSDimitry Andric void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
1572dbe13110SDimitry Andric void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
1573dbe13110SDimitry Andric void parseExportDecl();
1574461a67faSDimitry Andric void parseExportAsDecl();
1575bfef3995SDimitry Andric void parseUseDecl();
1576809500fcSDimitry Andric void parseLinkDecl();
1577809500fcSDimitry Andric void parseConfigMacros();
1578809500fcSDimitry Andric void parseConflict();
157913cc256eSDimitry Andric void parseInferredModuleDecl(bool Framework, bool Explicit);
158006d4ba38SDimitry Andric
158148675466SDimitry Andric /// Private modules are canonicalized as Foo_Private. Clang provides extra
158248675466SDimitry Andric /// module map search logic to find the appropriate private module when PCH
158348675466SDimitry Andric /// is used with implicit module maps. Warn when private modules are written
158448675466SDimitry Andric /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
158548675466SDimitry Andric void diagnosePrivateModules(SourceLocation ExplicitLoc,
158648675466SDimitry Andric SourceLocation FrameworkLoc);
158748675466SDimitry Andric
1588461a67faSDimitry Andric using Attributes = ModuleMap::Attributes;
1589461a67faSDimitry Andric
159013cc256eSDimitry Andric bool parseOptionalAttributes(Attributes &Attrs);
1591dbe13110SDimitry Andric
1592dbe13110SDimitry Andric public:
ModuleMapParser(Lexer & L,SourceManager & SourceMgr,const TargetInfo * Target,DiagnosticsEngine & Diags,ModuleMap & Map,FileID ModuleMapFID,DirectoryEntryRef Directory,bool IsSystem)1593ac9a064cSDimitry Andric ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
159448675466SDimitry Andric const TargetInfo *Target, DiagnosticsEngine &Diags,
1595ac9a064cSDimitry Andric ModuleMap &Map, FileID ModuleMapFID,
15967fa27ce4SDimitry Andric DirectoryEntryRef Directory, bool IsSystem)
159713cc256eSDimitry Andric : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
1598ac9a064cSDimitry Andric ModuleMapFID(ModuleMapFID), Directory(Directory), IsSystem(IsSystem) {
1599dbe13110SDimitry Andric Tok.clear();
1600dbe13110SDimitry Andric consumeToken();
1601dbe13110SDimitry Andric }
1602dbe13110SDimitry Andric
1603dbe13110SDimitry Andric bool parseModuleMapFile();
16040a5fb09bSDimitry Andric
terminatedByDirective()16050a5fb09bSDimitry Andric bool terminatedByDirective() { return false; }
getLocation()16060a5fb09bSDimitry Andric SourceLocation getLocation() { return Tok.getLocation(); }
1607dbe13110SDimitry Andric };
1608461a67faSDimitry Andric
1609461a67faSDimitry Andric } // namespace clang
1610dbe13110SDimitry Andric
consumeToken()1611dbe13110SDimitry Andric SourceLocation ModuleMapParser::consumeToken() {
1612dbe13110SDimitry Andric SourceLocation Result = Tok.getLocation();
1613dbe13110SDimitry Andric
16140a5fb09bSDimitry Andric retry:
16150a5fb09bSDimitry Andric Tok.clear();
1616dbe13110SDimitry Andric Token LToken;
1617dbe13110SDimitry Andric L.LexFromRawLexer(LToken);
1618dbe13110SDimitry Andric Tok.Location = LToken.getLocation().getRawEncoding();
1619dbe13110SDimitry Andric switch (LToken.getKind()) {
16209f4dbff6SDimitry Andric case tok::raw_identifier: {
16219f4dbff6SDimitry Andric StringRef RI = LToken.getRawIdentifier();
16229f4dbff6SDimitry Andric Tok.StringData = RI.data();
16239f4dbff6SDimitry Andric Tok.StringLength = RI.size();
16249f4dbff6SDimitry Andric Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
1625809500fcSDimitry Andric .Case("config_macros", MMToken::ConfigMacros)
1626809500fcSDimitry Andric .Case("conflict", MMToken::Conflict)
162713cc256eSDimitry Andric .Case("exclude", MMToken::ExcludeKeyword)
1628dbe13110SDimitry Andric .Case("explicit", MMToken::ExplicitKeyword)
1629dbe13110SDimitry Andric .Case("export", MMToken::ExportKeyword)
1630461a67faSDimitry Andric .Case("export_as", MMToken::ExportAsKeyword)
1631bfef3995SDimitry Andric .Case("extern", MMToken::ExternKeyword)
1632dbe13110SDimitry Andric .Case("framework", MMToken::FrameworkKeyword)
1633809500fcSDimitry Andric .Case("header", MMToken::HeaderKeyword)
1634809500fcSDimitry Andric .Case("link", MMToken::LinkKeyword)
1635dbe13110SDimitry Andric .Case("module", MMToken::ModuleKeyword)
1636bfef3995SDimitry Andric .Case("private", MMToken::PrivateKeyword)
1637dbe13110SDimitry Andric .Case("requires", MMToken::RequiresKeyword)
163806d4ba38SDimitry Andric .Case("textual", MMToken::TextualKeyword)
1639dbe13110SDimitry Andric .Case("umbrella", MMToken::UmbrellaKeyword)
1640bfef3995SDimitry Andric .Case("use", MMToken::UseKeyword)
1641dbe13110SDimitry Andric .Default(MMToken::Identifier);
1642dbe13110SDimitry Andric break;
16439f4dbff6SDimitry Andric }
1644dbe13110SDimitry Andric
1645dbe13110SDimitry Andric case tok::comma:
1646dbe13110SDimitry Andric Tok.Kind = MMToken::Comma;
1647dbe13110SDimitry Andric break;
1648dbe13110SDimitry Andric
1649dbe13110SDimitry Andric case tok::eof:
1650dbe13110SDimitry Andric Tok.Kind = MMToken::EndOfFile;
1651dbe13110SDimitry Andric break;
1652dbe13110SDimitry Andric
1653dbe13110SDimitry Andric case tok::l_brace:
1654dbe13110SDimitry Andric Tok.Kind = MMToken::LBrace;
1655dbe13110SDimitry Andric break;
1656dbe13110SDimitry Andric
1657dbe13110SDimitry Andric case tok::l_square:
1658dbe13110SDimitry Andric Tok.Kind = MMToken::LSquare;
1659dbe13110SDimitry Andric break;
1660dbe13110SDimitry Andric
1661dbe13110SDimitry Andric case tok::period:
1662dbe13110SDimitry Andric Tok.Kind = MMToken::Period;
1663dbe13110SDimitry Andric break;
1664dbe13110SDimitry Andric
1665dbe13110SDimitry Andric case tok::r_brace:
1666dbe13110SDimitry Andric Tok.Kind = MMToken::RBrace;
1667dbe13110SDimitry Andric break;
1668dbe13110SDimitry Andric
1669dbe13110SDimitry Andric case tok::r_square:
1670dbe13110SDimitry Andric Tok.Kind = MMToken::RSquare;
1671dbe13110SDimitry Andric break;
1672dbe13110SDimitry Andric
1673dbe13110SDimitry Andric case tok::star:
1674dbe13110SDimitry Andric Tok.Kind = MMToken::Star;
1675dbe13110SDimitry Andric break;
1676dbe13110SDimitry Andric
1677bfef3995SDimitry Andric case tok::exclaim:
1678bfef3995SDimitry Andric Tok.Kind = MMToken::Exclaim;
1679bfef3995SDimitry Andric break;
1680bfef3995SDimitry Andric
1681dbe13110SDimitry Andric case tok::string_literal: {
1682dbe13110SDimitry Andric if (LToken.hasUDSuffix()) {
1683dbe13110SDimitry Andric Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
1684dbe13110SDimitry Andric HadError = true;
1685dbe13110SDimitry Andric goto retry;
1686dbe13110SDimitry Andric }
1687dbe13110SDimitry Andric
1688dbe13110SDimitry Andric // Parse the string literal.
1689dbe13110SDimitry Andric LangOptions LangOpts;
16909f4dbff6SDimitry Andric StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
1691dbe13110SDimitry Andric if (StringLiteral.hadError)
1692dbe13110SDimitry Andric goto retry;
1693dbe13110SDimitry Andric
1694dbe13110SDimitry Andric // Copy the string literal into our string data allocator.
1695dbe13110SDimitry Andric unsigned Length = StringLiteral.GetStringLength();
1696dbe13110SDimitry Andric char *Saved = StringData.Allocate<char>(Length + 1);
1697dbe13110SDimitry Andric memcpy(Saved, StringLiteral.GetString().data(), Length);
1698dbe13110SDimitry Andric Saved[Length] = 0;
1699dbe13110SDimitry Andric
1700dbe13110SDimitry Andric // Form the token.
1701dbe13110SDimitry Andric Tok.Kind = MMToken::StringLiteral;
1702dbe13110SDimitry Andric Tok.StringData = Saved;
1703dbe13110SDimitry Andric Tok.StringLength = Length;
1704dbe13110SDimitry Andric break;
1705dbe13110SDimitry Andric }
1706dbe13110SDimitry Andric
1707551c6985SDimitry Andric case tok::numeric_constant: {
1708551c6985SDimitry Andric // We don't support any suffixes or other complications.
1709551c6985SDimitry Andric SmallString<32> SpellingBuffer;
1710551c6985SDimitry Andric SpellingBuffer.resize(LToken.getLength() + 1);
1711551c6985SDimitry Andric const char *Start = SpellingBuffer.data();
1712551c6985SDimitry Andric unsigned Length =
1713145449b1SDimitry Andric Lexer::getSpelling(LToken, Start, SourceMgr, Map.LangOpts);
1714551c6985SDimitry Andric uint64_t Value;
1715551c6985SDimitry Andric if (StringRef(Start, Length).getAsInteger(0, Value)) {
1716551c6985SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1717551c6985SDimitry Andric HadError = true;
1718551c6985SDimitry Andric goto retry;
1719551c6985SDimitry Andric }
1720551c6985SDimitry Andric
1721551c6985SDimitry Andric Tok.Kind = MMToken::IntegerLiteral;
1722551c6985SDimitry Andric Tok.IntegerValue = Value;
1723551c6985SDimitry Andric break;
1724551c6985SDimitry Andric }
1725551c6985SDimitry Andric
1726dbe13110SDimitry Andric case tok::comment:
1727dbe13110SDimitry Andric goto retry;
1728dbe13110SDimitry Andric
17290a5fb09bSDimitry Andric case tok::hash:
17300a5fb09bSDimitry Andric // A module map can be terminated prematurely by
17310a5fb09bSDimitry Andric // #pragma clang module contents
17320a5fb09bSDimitry Andric // When building the module, we'll treat the rest of the file as the
17330a5fb09bSDimitry Andric // contents of the module.
17340a5fb09bSDimitry Andric {
17350a5fb09bSDimitry Andric auto NextIsIdent = [&](StringRef Str) -> bool {
17360a5fb09bSDimitry Andric L.LexFromRawLexer(LToken);
17370a5fb09bSDimitry Andric return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
17380a5fb09bSDimitry Andric LToken.getRawIdentifier() == Str;
17390a5fb09bSDimitry Andric };
17400a5fb09bSDimitry Andric if (NextIsIdent("pragma") && NextIsIdent("clang") &&
17410a5fb09bSDimitry Andric NextIsIdent("module") && NextIsIdent("contents")) {
17420a5fb09bSDimitry Andric Tok.Kind = MMToken::EndOfFile;
17430a5fb09bSDimitry Andric break;
17440a5fb09bSDimitry Andric }
17450a5fb09bSDimitry Andric }
1746e3b55780SDimitry Andric [[fallthrough]];
17470a5fb09bSDimitry Andric
1748dbe13110SDimitry Andric default:
17490a5fb09bSDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
1750dbe13110SDimitry Andric HadError = true;
1751dbe13110SDimitry Andric goto retry;
1752dbe13110SDimitry Andric }
1753dbe13110SDimitry Andric
1754dbe13110SDimitry Andric return Result;
1755dbe13110SDimitry Andric }
1756dbe13110SDimitry Andric
skipUntil(MMToken::TokenKind K)1757dbe13110SDimitry Andric void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
1758dbe13110SDimitry Andric unsigned braceDepth = 0;
1759dbe13110SDimitry Andric unsigned squareDepth = 0;
1760dbe13110SDimitry Andric do {
1761dbe13110SDimitry Andric switch (Tok.Kind) {
1762dbe13110SDimitry Andric case MMToken::EndOfFile:
1763dbe13110SDimitry Andric return;
1764dbe13110SDimitry Andric
1765dbe13110SDimitry Andric case MMToken::LBrace:
1766dbe13110SDimitry Andric if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1767dbe13110SDimitry Andric return;
1768dbe13110SDimitry Andric
1769dbe13110SDimitry Andric ++braceDepth;
1770dbe13110SDimitry Andric break;
1771dbe13110SDimitry Andric
1772dbe13110SDimitry Andric case MMToken::LSquare:
1773dbe13110SDimitry Andric if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1774dbe13110SDimitry Andric return;
1775dbe13110SDimitry Andric
1776dbe13110SDimitry Andric ++squareDepth;
1777dbe13110SDimitry Andric break;
1778dbe13110SDimitry Andric
1779dbe13110SDimitry Andric case MMToken::RBrace:
1780dbe13110SDimitry Andric if (braceDepth > 0)
1781dbe13110SDimitry Andric --braceDepth;
1782dbe13110SDimitry Andric else if (Tok.is(K))
1783dbe13110SDimitry Andric return;
1784dbe13110SDimitry Andric break;
1785dbe13110SDimitry Andric
1786dbe13110SDimitry Andric case MMToken::RSquare:
1787dbe13110SDimitry Andric if (squareDepth > 0)
1788dbe13110SDimitry Andric --squareDepth;
1789dbe13110SDimitry Andric else if (Tok.is(K))
1790dbe13110SDimitry Andric return;
1791dbe13110SDimitry Andric break;
1792dbe13110SDimitry Andric
1793dbe13110SDimitry Andric default:
1794dbe13110SDimitry Andric if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
1795dbe13110SDimitry Andric return;
1796dbe13110SDimitry Andric break;
1797dbe13110SDimitry Andric }
1798dbe13110SDimitry Andric
1799dbe13110SDimitry Andric consumeToken();
1800dbe13110SDimitry Andric } while (true);
1801dbe13110SDimitry Andric }
1802dbe13110SDimitry Andric
180348675466SDimitry Andric /// Parse a module-id.
1804dbe13110SDimitry Andric ///
1805dbe13110SDimitry Andric /// module-id:
1806dbe13110SDimitry Andric /// identifier
1807dbe13110SDimitry Andric /// identifier '.' module-id
1808dbe13110SDimitry Andric ///
1809dbe13110SDimitry Andric /// \returns true if an error occurred, false otherwise.
parseModuleId(ModuleId & Id)1810dbe13110SDimitry Andric bool ModuleMapParser::parseModuleId(ModuleId &Id) {
1811dbe13110SDimitry Andric Id.clear();
1812dbe13110SDimitry Andric do {
18139f4dbff6SDimitry Andric if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1814cfca06d7SDimitry Andric Id.push_back(
1815cfca06d7SDimitry Andric std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
1816dbe13110SDimitry Andric consumeToken();
1817dbe13110SDimitry Andric } else {
1818dbe13110SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1819dbe13110SDimitry Andric return true;
1820dbe13110SDimitry Andric }
1821dbe13110SDimitry Andric
1822dbe13110SDimitry Andric if (!Tok.is(MMToken::Period))
1823dbe13110SDimitry Andric break;
1824dbe13110SDimitry Andric
1825dbe13110SDimitry Andric consumeToken();
1826dbe13110SDimitry Andric } while (true);
1827dbe13110SDimitry Andric
1828dbe13110SDimitry Andric return false;
1829dbe13110SDimitry Andric }
1830dbe13110SDimitry Andric
1831dbe13110SDimitry Andric namespace {
1832461a67faSDimitry Andric
183348675466SDimitry Andric /// Enumerates the known attributes.
1834dbe13110SDimitry Andric enum AttributeKind {
183548675466SDimitry Andric /// An unknown attribute.
1836dbe13110SDimitry Andric AT_unknown,
1837461a67faSDimitry Andric
183848675466SDimitry Andric /// The 'system' attribute.
1839809500fcSDimitry Andric AT_system,
1840461a67faSDimitry Andric
184148675466SDimitry Andric /// The 'extern_c' attribute.
18429f4dbff6SDimitry Andric AT_extern_c,
1843461a67faSDimitry Andric
184448675466SDimitry Andric /// The 'exhaustive' attribute.
1845bab175ecSDimitry Andric AT_exhaustive,
1846461a67faSDimitry Andric
184748675466SDimitry Andric /// The 'no_undeclared_includes' attribute.
1848bab175ecSDimitry Andric AT_no_undeclared_includes
1849dbe13110SDimitry Andric };
1850461a67faSDimitry Andric
1851461a67faSDimitry Andric } // namespace
1852dbe13110SDimitry Andric
18536252156dSDimitry Andric /// Private modules are canonicalized as Foo_Private. Clang provides extra
18546252156dSDimitry Andric /// module map search logic to find the appropriate private module when PCH
18556252156dSDimitry Andric /// is used with implicit module maps. Warn when private modules are written
18566252156dSDimitry Andric /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
diagnosePrivateModules(SourceLocation ExplicitLoc,SourceLocation FrameworkLoc)185748675466SDimitry Andric void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
185848675466SDimitry Andric SourceLocation FrameworkLoc) {
18596252156dSDimitry Andric auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
186048675466SDimitry Andric const Module *M, SourceRange ReplLoc) {
18616252156dSDimitry Andric auto D = Diags.Report(ActiveModule->DefinitionLoc,
18626252156dSDimitry Andric diag::note_mmap_rename_top_level_private_module);
18636252156dSDimitry Andric D << BadName << M->Name;
186448675466SDimitry Andric D << FixItHint::CreateReplacement(ReplLoc, Canonical);
18656252156dSDimitry Andric };
18666252156dSDimitry Andric
18676252156dSDimitry Andric for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
18686252156dSDimitry Andric auto const *M = E->getValue();
18696252156dSDimitry Andric if (M->Directory != ActiveModule->Directory)
18706252156dSDimitry Andric continue;
18716252156dSDimitry Andric
18726252156dSDimitry Andric SmallString<128> FullName(ActiveModule->getFullModuleName());
1873312c0ed1SDimitry Andric if (!FullName.starts_with(M->Name) && !FullName.ends_with("Private"))
18746252156dSDimitry Andric continue;
187548675466SDimitry Andric SmallString<128> FixedPrivModDecl;
18766252156dSDimitry Andric SmallString<128> Canonical(M->Name);
18776252156dSDimitry Andric Canonical.append("_Private");
18786252156dSDimitry Andric
18796252156dSDimitry Andric // Foo.Private -> Foo_Private
18806252156dSDimitry Andric if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
18816252156dSDimitry Andric M->Name == ActiveModule->Parent->Name) {
18826252156dSDimitry Andric Diags.Report(ActiveModule->DefinitionLoc,
18836252156dSDimitry Andric diag::warn_mmap_mismatched_private_submodule)
18846252156dSDimitry Andric << FullName;
188548675466SDimitry Andric
188648675466SDimitry Andric SourceLocation FixItInitBegin = CurrModuleDeclLoc;
188748675466SDimitry Andric if (FrameworkLoc.isValid())
188848675466SDimitry Andric FixItInitBegin = FrameworkLoc;
188948675466SDimitry Andric if (ExplicitLoc.isValid())
189048675466SDimitry Andric FixItInitBegin = ExplicitLoc;
189148675466SDimitry Andric
189248675466SDimitry Andric if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
189348675466SDimitry Andric FixedPrivModDecl.append("framework ");
189448675466SDimitry Andric FixedPrivModDecl.append("module ");
189548675466SDimitry Andric FixedPrivModDecl.append(Canonical);
189648675466SDimitry Andric
189748675466SDimitry Andric GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
189848675466SDimitry Andric SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
18996252156dSDimitry Andric continue;
19006252156dSDimitry Andric }
19016252156dSDimitry Andric
19026252156dSDimitry Andric // FooPrivate and whatnots -> Foo_Private
19036252156dSDimitry Andric if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
19046252156dSDimitry Andric ActiveModule->Name != Canonical) {
19056252156dSDimitry Andric Diags.Report(ActiveModule->DefinitionLoc,
19066252156dSDimitry Andric diag::warn_mmap_mismatched_private_module_name)
19076252156dSDimitry Andric << ActiveModule->Name;
190848675466SDimitry Andric GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
190948675466SDimitry Andric SourceRange(ActiveModule->DefinitionLoc));
19106252156dSDimitry Andric }
19116252156dSDimitry Andric }
19126252156dSDimitry Andric }
19136252156dSDimitry Andric
191448675466SDimitry Andric /// Parse a module declaration.
1915dbe13110SDimitry Andric ///
1916dbe13110SDimitry Andric /// module-declaration:
1917bfef3995SDimitry Andric /// 'extern' 'module' module-id string-literal
1918dbe13110SDimitry Andric /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1919dbe13110SDimitry Andric /// { module-member* }
1920dbe13110SDimitry Andric ///
1921dbe13110SDimitry Andric /// module-member:
1922dbe13110SDimitry Andric /// requires-declaration
1923dbe13110SDimitry Andric /// header-declaration
1924dbe13110SDimitry Andric /// submodule-declaration
1925dbe13110SDimitry Andric /// export-declaration
1926461a67faSDimitry Andric /// export-as-declaration
1927809500fcSDimitry Andric /// link-declaration
1928dbe13110SDimitry Andric ///
1929dbe13110SDimitry Andric /// submodule-declaration:
1930dbe13110SDimitry Andric /// module-declaration
1931dbe13110SDimitry Andric /// inferred-submodule-declaration
parseModuleDecl()1932dbe13110SDimitry Andric void ModuleMapParser::parseModuleDecl() {
1933dbe13110SDimitry Andric assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
1934bfef3995SDimitry Andric Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
1935bfef3995SDimitry Andric if (Tok.is(MMToken::ExternKeyword)) {
1936bfef3995SDimitry Andric parseExternModuleDecl();
1937bfef3995SDimitry Andric return;
1938bfef3995SDimitry Andric }
1939bfef3995SDimitry Andric
1940dbe13110SDimitry Andric // Parse 'explicit' or 'framework' keyword, if present.
1941dbe13110SDimitry Andric SourceLocation ExplicitLoc;
194248675466SDimitry Andric SourceLocation FrameworkLoc;
1943dbe13110SDimitry Andric bool Explicit = false;
1944dbe13110SDimitry Andric bool Framework = false;
1945dbe13110SDimitry Andric
1946dbe13110SDimitry Andric // Parse 'explicit' keyword, if present.
1947dbe13110SDimitry Andric if (Tok.is(MMToken::ExplicitKeyword)) {
1948dbe13110SDimitry Andric ExplicitLoc = consumeToken();
1949dbe13110SDimitry Andric Explicit = true;
1950dbe13110SDimitry Andric }
1951dbe13110SDimitry Andric
1952dbe13110SDimitry Andric // Parse 'framework' keyword, if present.
1953dbe13110SDimitry Andric if (Tok.is(MMToken::FrameworkKeyword)) {
195448675466SDimitry Andric FrameworkLoc = consumeToken();
1955dbe13110SDimitry Andric Framework = true;
1956dbe13110SDimitry Andric }
1957dbe13110SDimitry Andric
1958dbe13110SDimitry Andric // Parse 'module' keyword.
1959dbe13110SDimitry Andric if (!Tok.is(MMToken::ModuleKeyword)) {
1960dbe13110SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1961dbe13110SDimitry Andric consumeToken();
1962dbe13110SDimitry Andric HadError = true;
1963dbe13110SDimitry Andric return;
1964dbe13110SDimitry Andric }
196548675466SDimitry Andric CurrModuleDeclLoc = consumeToken(); // 'module' keyword
1966dbe13110SDimitry Andric
1967dbe13110SDimitry Andric // If we have a wildcard for the module name, this is an inferred submodule.
1968dbe13110SDimitry Andric // Parse it.
1969dbe13110SDimitry Andric if (Tok.is(MMToken::Star))
197013cc256eSDimitry Andric return parseInferredModuleDecl(Framework, Explicit);
1971dbe13110SDimitry Andric
1972dbe13110SDimitry Andric // Parse the module name.
1973dbe13110SDimitry Andric ModuleId Id;
1974dbe13110SDimitry Andric if (parseModuleId(Id)) {
1975dbe13110SDimitry Andric HadError = true;
1976dbe13110SDimitry Andric return;
1977dbe13110SDimitry Andric }
1978dbe13110SDimitry Andric
1979dbe13110SDimitry Andric if (ActiveModule) {
1980dbe13110SDimitry Andric if (Id.size() > 1) {
1981dbe13110SDimitry Andric Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1982dbe13110SDimitry Andric << SourceRange(Id.front().second, Id.back().second);
1983dbe13110SDimitry Andric
1984dbe13110SDimitry Andric HadError = true;
1985dbe13110SDimitry Andric return;
1986dbe13110SDimitry Andric }
1987dbe13110SDimitry Andric } else if (Id.size() == 1 && Explicit) {
1988dbe13110SDimitry Andric // Top-level modules can't be explicit.
1989dbe13110SDimitry Andric Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1990dbe13110SDimitry Andric Explicit = false;
1991dbe13110SDimitry Andric ExplicitLoc = SourceLocation();
1992dbe13110SDimitry Andric HadError = true;
1993dbe13110SDimitry Andric }
1994dbe13110SDimitry Andric
1995dbe13110SDimitry Andric Module *PreviousActiveModule = ActiveModule;
1996dbe13110SDimitry Andric if (Id.size() > 1) {
1997dbe13110SDimitry Andric // This module map defines a submodule. Go find the module of which it
1998dbe13110SDimitry Andric // is a submodule.
19999f4dbff6SDimitry Andric ActiveModule = nullptr;
200006d4ba38SDimitry Andric const Module *TopLevelModule = nullptr;
2001dbe13110SDimitry Andric for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
2002dbe13110SDimitry Andric if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
200306d4ba38SDimitry Andric if (I == 0)
200406d4ba38SDimitry Andric TopLevelModule = Next;
2005dbe13110SDimitry Andric ActiveModule = Next;
2006dbe13110SDimitry Andric continue;
2007dbe13110SDimitry Andric }
2008dbe13110SDimitry Andric
2009b60736ecSDimitry Andric Diags.Report(Id[I].second, diag::err_mmap_missing_parent_module)
2010b60736ecSDimitry Andric << Id[I].first << (ActiveModule != nullptr)
2011b60736ecSDimitry Andric << (ActiveModule
2012b60736ecSDimitry Andric ? ActiveModule->getTopLevelModule()->getFullModuleName()
2013b60736ecSDimitry Andric : "");
2014dbe13110SDimitry Andric HadError = true;
2015dbe13110SDimitry Andric }
201606d4ba38SDimitry Andric
2017b60736ecSDimitry Andric if (TopLevelModule &&
2018ac9a064cSDimitry Andric ModuleMapFID != Map.getContainingModuleMapFileID(TopLevelModule)) {
2019ac9a064cSDimitry Andric assert(ModuleMapFID !=
2020ac9a064cSDimitry Andric Map.getModuleMapFileIDForUniquing(TopLevelModule) &&
202106d4ba38SDimitry Andric "submodule defined in same file as 'module *' that allowed its "
202206d4ba38SDimitry Andric "top-level module");
2023ac9a064cSDimitry Andric Map.addAdditionalModuleMapFile(
2024ac9a064cSDimitry Andric TopLevelModule, *SourceMgr.getFileEntryRefForID(ModuleMapFID));
202506d4ba38SDimitry Andric }
2026dbe13110SDimitry Andric }
2027dbe13110SDimitry Andric
2028dbe13110SDimitry Andric StringRef ModuleName = Id.back().first;
2029dbe13110SDimitry Andric SourceLocation ModuleNameLoc = Id.back().second;
2030dbe13110SDimitry Andric
2031dbe13110SDimitry Andric // Parse the optional attribute list.
203213cc256eSDimitry Andric Attributes Attrs;
20332b6b257fSDimitry Andric if (parseOptionalAttributes(Attrs))
20342b6b257fSDimitry Andric return;
20352b6b257fSDimitry Andric
2036dbe13110SDimitry Andric // Parse the opening brace.
2037dbe13110SDimitry Andric if (!Tok.is(MMToken::LBrace)) {
2038dbe13110SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
2039dbe13110SDimitry Andric << ModuleName;
2040dbe13110SDimitry Andric HadError = true;
2041dbe13110SDimitry Andric return;
2042dbe13110SDimitry Andric }
2043dbe13110SDimitry Andric SourceLocation LBraceLoc = consumeToken();
2044dbe13110SDimitry Andric
2045dbe13110SDimitry Andric // Determine whether this (sub)module has already been defined.
204648675466SDimitry Andric Module *ShadowingModule = nullptr;
2047dbe13110SDimitry Andric if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
20482410013dSDimitry Andric // We might see a (re)definition of a module that we already have a
20497fa27ce4SDimitry Andric // definition for in four cases:
20502410013dSDimitry Andric // - If we loaded one definition from an AST file and we've just found a
20512410013dSDimitry Andric // corresponding definition in a module map file, or
20527fa27ce4SDimitry Andric bool LoadedFromASTFile = Existing->IsFromModuleFile;
20537fa27ce4SDimitry Andric // - If we previously inferred this module from different module map file.
20547fa27ce4SDimitry Andric bool Inferred = Existing->IsInferred;
20557fa27ce4SDimitry Andric // - If we're building a framework that vends a module map, we might've
20567fa27ce4SDimitry Andric // previously seen the one in intermediate products and now the system
20577fa27ce4SDimitry Andric // one.
20587fa27ce4SDimitry Andric // FIXME: If we're parsing module map file that looks like this:
20597fa27ce4SDimitry Andric // framework module FW { ... }
20607fa27ce4SDimitry Andric // module FW.Sub { ... }
20617fa27ce4SDimitry Andric // We can't check the framework qualifier, since it's not attached to
20627fa27ce4SDimitry Andric // the definition of Sub. Checking that qualifier on \c Existing is
20637fa27ce4SDimitry Andric // not correct either, since we might've previously seen:
20647fa27ce4SDimitry Andric // module FW { ... }
20657fa27ce4SDimitry Andric // module FW.Sub { ... }
20667fa27ce4SDimitry Andric // We should enforce consistency of redefinitions so that we can rely
20677fa27ce4SDimitry Andric // that \c Existing is part of a framework iff the redefinition of FW
20687fa27ce4SDimitry Andric // we have just skipped had it too. Once we do that, stop checking
20697fa27ce4SDimitry Andric // the local framework qualifier and only rely on \c Existing.
20707fa27ce4SDimitry Andric bool PartOfFramework = Framework || Existing->isPartOfFramework();
20712410013dSDimitry Andric // - If we're building a (preprocessed) module and we've just loaded the
20722410013dSDimitry Andric // module map file from which it was created.
20732410013dSDimitry Andric bool ParsedAsMainInput =
20742410013dSDimitry Andric Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
20752410013dSDimitry Andric Map.LangOpts.CurrentModule == ModuleName &&
20762410013dSDimitry Andric SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
20772410013dSDimitry Andric SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
20787fa27ce4SDimitry Andric if (LoadedFromASTFile || Inferred || PartOfFramework || ParsedAsMainInput) {
20797fa27ce4SDimitry Andric ActiveModule = PreviousActiveModule;
2080dbe13110SDimitry Andric // Skip the module definition.
2081dbe13110SDimitry Andric skipUntil(MMToken::RBrace);
2082dbe13110SDimitry Andric if (Tok.is(MMToken::RBrace))
2083dbe13110SDimitry Andric consumeToken();
2084dbe13110SDimitry Andric else {
2085dbe13110SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2086dbe13110SDimitry Andric Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2087dbe13110SDimitry Andric HadError = true;
2088dbe13110SDimitry Andric }
2089dbe13110SDimitry Andric return;
2090dbe13110SDimitry Andric }
2091dbe13110SDimitry Andric
209248675466SDimitry Andric if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
209348675466SDimitry Andric ShadowingModule = Existing;
209448675466SDimitry Andric } else {
209548675466SDimitry Andric // This is not a shawdowed module decl, it is an illegal redefinition.
2096dbe13110SDimitry Andric Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
2097dbe13110SDimitry Andric << ModuleName;
2098dbe13110SDimitry Andric Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
2099dbe13110SDimitry Andric
2100dbe13110SDimitry Andric // Skip the module definition.
2101dbe13110SDimitry Andric skipUntil(MMToken::RBrace);
2102dbe13110SDimitry Andric if (Tok.is(MMToken::RBrace))
2103dbe13110SDimitry Andric consumeToken();
2104dbe13110SDimitry Andric
2105dbe13110SDimitry Andric HadError = true;
2106dbe13110SDimitry Andric return;
2107dbe13110SDimitry Andric }
210848675466SDimitry Andric }
2109dbe13110SDimitry Andric
2110dbe13110SDimitry Andric // Start defining this module.
211148675466SDimitry Andric if (ShadowingModule) {
211248675466SDimitry Andric ActiveModule =
211348675466SDimitry Andric Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
211448675466SDimitry Andric } else {
211548675466SDimitry Andric ActiveModule =
211648675466SDimitry Andric Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
211748675466SDimitry Andric .first;
211848675466SDimitry Andric }
211948675466SDimitry Andric
2120dbe13110SDimitry Andric ActiveModule->DefinitionLoc = ModuleNameLoc;
2121bfef3995SDimitry Andric if (Attrs.IsSystem || IsSystem)
2122dbe13110SDimitry Andric ActiveModule->IsSystem = true;
21239f4dbff6SDimitry Andric if (Attrs.IsExternC)
21249f4dbff6SDimitry Andric ActiveModule->IsExternC = true;
2125e3b55780SDimitry Andric if (Attrs.NoUndeclaredIncludes)
2126bab175ecSDimitry Andric ActiveModule->NoUndeclaredIncludes = true;
212706d4ba38SDimitry Andric ActiveModule->Directory = Directory;
2128dbe13110SDimitry Andric
2129ac9a064cSDimitry Andric StringRef MapFileName(
2130ac9a064cSDimitry Andric SourceMgr.getFileEntryRefForID(ModuleMapFID)->getName());
2131312c0ed1SDimitry Andric if (MapFileName.ends_with("module.private.modulemap") ||
2132312c0ed1SDimitry Andric MapFileName.ends_with("module_private.map")) {
213348675466SDimitry Andric ActiveModule->ModuleMapIsPrivate = true;
213448675466SDimitry Andric }
21356252156dSDimitry Andric
21366252156dSDimitry Andric // Private modules named as FooPrivate, Foo.Private or similar are likely a
21376252156dSDimitry Andric // user error; provide warnings, notes and fixits to direct users to use
21386252156dSDimitry Andric // Foo_Private instead.
21396252156dSDimitry Andric SourceLocation StartLoc =
21406252156dSDimitry Andric SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
21416252156dSDimitry Andric if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
21426252156dSDimitry Andric !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
21436252156dSDimitry Andric StartLoc) &&
21446252156dSDimitry Andric !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
21456252156dSDimitry Andric StartLoc) &&
214648675466SDimitry Andric ActiveModule->ModuleMapIsPrivate)
214748675466SDimitry Andric diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
2148bab175ecSDimitry Andric
2149dbe13110SDimitry Andric bool Done = false;
2150dbe13110SDimitry Andric do {
2151dbe13110SDimitry Andric switch (Tok.Kind) {
2152dbe13110SDimitry Andric case MMToken::EndOfFile:
2153dbe13110SDimitry Andric case MMToken::RBrace:
2154dbe13110SDimitry Andric Done = true;
2155dbe13110SDimitry Andric break;
2156dbe13110SDimitry Andric
2157809500fcSDimitry Andric case MMToken::ConfigMacros:
2158809500fcSDimitry Andric parseConfigMacros();
2159809500fcSDimitry Andric break;
2160809500fcSDimitry Andric
2161809500fcSDimitry Andric case MMToken::Conflict:
2162809500fcSDimitry Andric parseConflict();
2163809500fcSDimitry Andric break;
2164809500fcSDimitry Andric
2165dbe13110SDimitry Andric case MMToken::ExplicitKeyword:
2166bfef3995SDimitry Andric case MMToken::ExternKeyword:
2167dbe13110SDimitry Andric case MMToken::FrameworkKeyword:
2168dbe13110SDimitry Andric case MMToken::ModuleKeyword:
2169dbe13110SDimitry Andric parseModuleDecl();
2170dbe13110SDimitry Andric break;
2171dbe13110SDimitry Andric
2172dbe13110SDimitry Andric case MMToken::ExportKeyword:
2173dbe13110SDimitry Andric parseExportDecl();
2174dbe13110SDimitry Andric break;
2175dbe13110SDimitry Andric
2176461a67faSDimitry Andric case MMToken::ExportAsKeyword:
2177461a67faSDimitry Andric parseExportAsDecl();
2178461a67faSDimitry Andric break;
2179461a67faSDimitry Andric
2180bfef3995SDimitry Andric case MMToken::UseKeyword:
2181bfef3995SDimitry Andric parseUseDecl();
2182bfef3995SDimitry Andric break;
2183bfef3995SDimitry Andric
2184dbe13110SDimitry Andric case MMToken::RequiresKeyword:
2185dbe13110SDimitry Andric parseRequiresDecl();
2186dbe13110SDimitry Andric break;
2187dbe13110SDimitry Andric
218806d4ba38SDimitry Andric case MMToken::TextualKeyword:
218906d4ba38SDimitry Andric parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
219006d4ba38SDimitry Andric break;
219106d4ba38SDimitry Andric
2192dbe13110SDimitry Andric case MMToken::UmbrellaKeyword: {
2193dbe13110SDimitry Andric SourceLocation UmbrellaLoc = consumeToken();
2194dbe13110SDimitry Andric if (Tok.is(MMToken::HeaderKeyword))
2195bfef3995SDimitry Andric parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
2196dbe13110SDimitry Andric else
2197dbe13110SDimitry Andric parseUmbrellaDirDecl(UmbrellaLoc);
2198dbe13110SDimitry Andric break;
2199dbe13110SDimitry Andric }
2200dbe13110SDimitry Andric
220106d4ba38SDimitry Andric case MMToken::ExcludeKeyword:
220206d4ba38SDimitry Andric parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
220313cc256eSDimitry Andric break;
220413cc256eSDimitry Andric
220506d4ba38SDimitry Andric case MMToken::PrivateKeyword:
220606d4ba38SDimitry Andric parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
2207bfef3995SDimitry Andric break;
2208bfef3995SDimitry Andric
2209dbe13110SDimitry Andric case MMToken::HeaderKeyword:
221006d4ba38SDimitry Andric parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
2211dbe13110SDimitry Andric break;
2212dbe13110SDimitry Andric
2213809500fcSDimitry Andric case MMToken::LinkKeyword:
2214809500fcSDimitry Andric parseLinkDecl();
2215809500fcSDimitry Andric break;
2216809500fcSDimitry Andric
2217dbe13110SDimitry Andric default:
2218dbe13110SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
2219dbe13110SDimitry Andric consumeToken();
2220dbe13110SDimitry Andric break;
2221dbe13110SDimitry Andric }
2222dbe13110SDimitry Andric } while (!Done);
2223dbe13110SDimitry Andric
2224dbe13110SDimitry Andric if (Tok.is(MMToken::RBrace))
2225dbe13110SDimitry Andric consumeToken();
2226dbe13110SDimitry Andric else {
2227dbe13110SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2228dbe13110SDimitry Andric Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2229dbe13110SDimitry Andric HadError = true;
2230dbe13110SDimitry Andric }
2231dbe13110SDimitry Andric
2232809500fcSDimitry Andric // If the active module is a top-level framework, and there are no link
2233809500fcSDimitry Andric // libraries, automatically link against the framework.
2234809500fcSDimitry Andric if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
22357fa27ce4SDimitry Andric ActiveModule->LinkLibraries.empty())
22367fa27ce4SDimitry Andric inferFrameworkLink(ActiveModule);
2237809500fcSDimitry Andric
22389f4dbff6SDimitry Andric // If the module meets all requirements but is still unavailable, mark the
22399f4dbff6SDimitry Andric // whole tree as unavailable to prevent it from building.
2240cfca06d7SDimitry Andric if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
22419f4dbff6SDimitry Andric ActiveModule->Parent) {
2242cfca06d7SDimitry Andric ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false);
22439f4dbff6SDimitry Andric ActiveModule->getTopLevelModule()->MissingHeaders.append(
22449f4dbff6SDimitry Andric ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
22459f4dbff6SDimitry Andric }
22469f4dbff6SDimitry Andric
2247dbe13110SDimitry Andric // We're done parsing this module. Pop back to the previous module.
2248dbe13110SDimitry Andric ActiveModule = PreviousActiveModule;
2249dbe13110SDimitry Andric }
2250dbe13110SDimitry Andric
225148675466SDimitry Andric /// Parse an extern module declaration.
2252bfef3995SDimitry Andric ///
2253bfef3995SDimitry Andric /// extern module-declaration:
2254bfef3995SDimitry Andric /// 'extern' 'module' module-id string-literal
parseExternModuleDecl()2255bfef3995SDimitry Andric void ModuleMapParser::parseExternModuleDecl() {
2256bfef3995SDimitry Andric assert(Tok.is(MMToken::ExternKeyword));
225751ece4aaSDimitry Andric SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
2258bfef3995SDimitry Andric
2259bfef3995SDimitry Andric // Parse 'module' keyword.
2260bfef3995SDimitry Andric if (!Tok.is(MMToken::ModuleKeyword)) {
2261bfef3995SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
2262bfef3995SDimitry Andric consumeToken();
2263bfef3995SDimitry Andric HadError = true;
2264bfef3995SDimitry Andric return;
2265bfef3995SDimitry Andric }
2266bfef3995SDimitry Andric consumeToken(); // 'module' keyword
2267bfef3995SDimitry Andric
2268bfef3995SDimitry Andric // Parse the module name.
2269bfef3995SDimitry Andric ModuleId Id;
2270bfef3995SDimitry Andric if (parseModuleId(Id)) {
2271bfef3995SDimitry Andric HadError = true;
2272bfef3995SDimitry Andric return;
2273bfef3995SDimitry Andric }
2274bfef3995SDimitry Andric
2275bfef3995SDimitry Andric // Parse the referenced module map file name.
2276bfef3995SDimitry Andric if (!Tok.is(MMToken::StringLiteral)) {
2277bfef3995SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
2278bfef3995SDimitry Andric HadError = true;
2279bfef3995SDimitry Andric return;
2280bfef3995SDimitry Andric }
2281cfca06d7SDimitry Andric std::string FileName = std::string(Tok.getString());
2282bfef3995SDimitry Andric consumeToken(); // filename
2283bfef3995SDimitry Andric
2284bfef3995SDimitry Andric StringRef FileNameRef = FileName;
2285bfef3995SDimitry Andric SmallString<128> ModuleMapFileName;
2286bfef3995SDimitry Andric if (llvm::sys::path::is_relative(FileNameRef)) {
22877fa27ce4SDimitry Andric ModuleMapFileName += Directory.getName();
2288bfef3995SDimitry Andric llvm::sys::path::append(ModuleMapFileName, FileName);
22895e20cdd8SDimitry Andric FileNameRef = ModuleMapFileName;
2290bfef3995SDimitry Andric }
22917fa27ce4SDimitry Andric if (auto File = SourceMgr.getFileManager().getOptionalFileRef(FileNameRef))
229206d4ba38SDimitry Andric Map.parseModuleMapFile(
2293c0981da4SDimitry Andric *File, IsSystem,
229406d4ba38SDimitry Andric Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
229506d4ba38SDimitry Andric ? Directory
22967fa27ce4SDimitry Andric : File->getDir(),
22970a5fb09bSDimitry Andric FileID(), nullptr, ExternLoc);
2298bfef3995SDimitry Andric }
2299bfef3995SDimitry Andric
230045b53394SDimitry Andric /// Whether to add the requirement \p Feature to the module \p M.
230145b53394SDimitry Andric ///
230245b53394SDimitry Andric /// This preserves backwards compatibility for two hacks in the Darwin system
230345b53394SDimitry Andric /// module map files:
230445b53394SDimitry Andric ///
230545b53394SDimitry Andric /// 1. The use of 'requires excluded' to make headers non-modular, which
230645b53394SDimitry Andric /// should really be mapped to 'textual' now that we have this feature. We
230745b53394SDimitry Andric /// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
230845b53394SDimitry Andric /// true. Later, this bit will be used to map all the headers inside this
230945b53394SDimitry Andric /// module to 'textual'.
231045b53394SDimitry Andric ///
231145b53394SDimitry Andric /// This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
231245b53394SDimitry Andric ///
231345b53394SDimitry Andric /// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement
231445b53394SDimitry Andric /// was never correct and causes issues now that we check it, so drop it.
shouldAddRequirement(Module * M,StringRef Feature,bool & IsRequiresExcludedHack)231545b53394SDimitry Andric static bool shouldAddRequirement(Module *M, StringRef Feature,
231645b53394SDimitry Andric bool &IsRequiresExcludedHack) {
2317bab175ecSDimitry Andric if (Feature == "excluded" &&
2318bab175ecSDimitry Andric (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
2319bab175ecSDimitry Andric M->fullModuleNameIs({"Tcl", "Private"}))) {
232045b53394SDimitry Andric IsRequiresExcludedHack = true;
232145b53394SDimitry Andric return false;
2322bab175ecSDimitry Andric } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
232345b53394SDimitry Andric return false;
232445b53394SDimitry Andric }
232545b53394SDimitry Andric
232645b53394SDimitry Andric return true;
232745b53394SDimitry Andric }
232845b53394SDimitry Andric
232948675466SDimitry Andric /// Parse a requires declaration.
2330dbe13110SDimitry Andric ///
2331dbe13110SDimitry Andric /// requires-declaration:
2332dbe13110SDimitry Andric /// 'requires' feature-list
2333dbe13110SDimitry Andric ///
2334dbe13110SDimitry Andric /// feature-list:
2335bfef3995SDimitry Andric /// feature ',' feature-list
2336bfef3995SDimitry Andric /// feature
2337bfef3995SDimitry Andric ///
2338bfef3995SDimitry Andric /// feature:
2339bfef3995SDimitry Andric /// '!'[opt] identifier
parseRequiresDecl()2340dbe13110SDimitry Andric void ModuleMapParser::parseRequiresDecl() {
2341dbe13110SDimitry Andric assert(Tok.is(MMToken::RequiresKeyword));
2342dbe13110SDimitry Andric
2343dbe13110SDimitry Andric // Parse 'requires' keyword.
2344dbe13110SDimitry Andric consumeToken();
2345dbe13110SDimitry Andric
2346dbe13110SDimitry Andric // Parse the feature-list.
2347dbe13110SDimitry Andric do {
2348bfef3995SDimitry Andric bool RequiredState = true;
2349bfef3995SDimitry Andric if (Tok.is(MMToken::Exclaim)) {
2350bfef3995SDimitry Andric RequiredState = false;
2351bfef3995SDimitry Andric consumeToken();
2352bfef3995SDimitry Andric }
2353bfef3995SDimitry Andric
2354dbe13110SDimitry Andric if (!Tok.is(MMToken::Identifier)) {
2355dbe13110SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
2356dbe13110SDimitry Andric HadError = true;
2357dbe13110SDimitry Andric return;
2358dbe13110SDimitry Andric }
2359dbe13110SDimitry Andric
2360dbe13110SDimitry Andric // Consume the feature name.
2361cfca06d7SDimitry Andric std::string Feature = std::string(Tok.getString());
2362dbe13110SDimitry Andric consumeToken();
2363dbe13110SDimitry Andric
236445b53394SDimitry Andric bool IsRequiresExcludedHack = false;
236545b53394SDimitry Andric bool ShouldAddRequirement =
236645b53394SDimitry Andric shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
236745b53394SDimitry Andric
236845b53394SDimitry Andric if (IsRequiresExcludedHack)
236945b53394SDimitry Andric UsesRequiresExcludedHack.insert(ActiveModule);
237045b53394SDimitry Andric
237145b53394SDimitry Andric if (ShouldAddRequirement) {
2372dbe13110SDimitry Andric // Add this feature.
237345b53394SDimitry Andric ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
237445b53394SDimitry Andric *Map.Target);
237545b53394SDimitry Andric }
2376dbe13110SDimitry Andric
2377dbe13110SDimitry Andric if (!Tok.is(MMToken::Comma))
2378dbe13110SDimitry Andric break;
2379dbe13110SDimitry Andric
2380dbe13110SDimitry Andric // Consume the comma.
2381dbe13110SDimitry Andric consumeToken();
2382dbe13110SDimitry Andric } while (true);
2383dbe13110SDimitry Andric }
2384dbe13110SDimitry Andric
238548675466SDimitry Andric /// Parse a header declaration.
2386dbe13110SDimitry Andric ///
2387dbe13110SDimitry Andric /// header-declaration:
238806d4ba38SDimitry Andric /// 'textual'[opt] 'header' string-literal
238906d4ba38SDimitry Andric /// 'private' 'textual'[opt] 'header' string-literal
239006d4ba38SDimitry Andric /// 'exclude' 'header' string-literal
239106d4ba38SDimitry Andric /// 'umbrella' 'header' string-literal
239206d4ba38SDimitry Andric ///
239306d4ba38SDimitry Andric /// FIXME: Support 'private textual header'.
parseHeaderDecl(MMToken::TokenKind LeadingToken,SourceLocation LeadingLoc)2394bfef3995SDimitry Andric void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
2395bfef3995SDimitry Andric SourceLocation LeadingLoc) {
239606d4ba38SDimitry Andric // We've already consumed the first token.
239706d4ba38SDimitry Andric ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
2398e3b55780SDimitry Andric
239906d4ba38SDimitry Andric if (LeadingToken == MMToken::PrivateKeyword) {
240006d4ba38SDimitry Andric Role = ModuleMap::PrivateHeader;
240106d4ba38SDimitry Andric // 'private' may optionally be followed by 'textual'.
240206d4ba38SDimitry Andric if (Tok.is(MMToken::TextualKeyword)) {
240306d4ba38SDimitry Andric LeadingToken = Tok.Kind;
2404dbe13110SDimitry Andric consumeToken();
240506d4ba38SDimitry Andric }
2406e3b55780SDimitry Andric } else if (LeadingToken == MMToken::ExcludeKeyword) {
2407e3b55780SDimitry Andric Role = ModuleMap::ExcludedHeader;
240806d4ba38SDimitry Andric }
240945b53394SDimitry Andric
241006d4ba38SDimitry Andric if (LeadingToken == MMToken::TextualKeyword)
241106d4ba38SDimitry Andric Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
241206d4ba38SDimitry Andric
241345b53394SDimitry Andric if (UsesRequiresExcludedHack.count(ActiveModule)) {
241445b53394SDimitry Andric // Mark this header 'textual' (see doc comment for
241545b53394SDimitry Andric // Module::UsesRequiresExcludedHack).
241645b53394SDimitry Andric Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
241745b53394SDimitry Andric }
241845b53394SDimitry Andric
241906d4ba38SDimitry Andric if (LeadingToken != MMToken::HeaderKeyword) {
242006d4ba38SDimitry Andric if (!Tok.is(MMToken::HeaderKeyword)) {
242106d4ba38SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
242206d4ba38SDimitry Andric << (LeadingToken == MMToken::PrivateKeyword ? "private" :
242306d4ba38SDimitry Andric LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
242406d4ba38SDimitry Andric LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
242506d4ba38SDimitry Andric return;
242606d4ba38SDimitry Andric }
242706d4ba38SDimitry Andric consumeToken();
242806d4ba38SDimitry Andric }
2429dbe13110SDimitry Andric
2430dbe13110SDimitry Andric // Parse the header name.
2431dbe13110SDimitry Andric if (!Tok.is(MMToken::StringLiteral)) {
2432dbe13110SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2433dbe13110SDimitry Andric << "header";
2434dbe13110SDimitry Andric HadError = true;
2435dbe13110SDimitry Andric return;
2436dbe13110SDimitry Andric }
243706d4ba38SDimitry Andric Module::UnresolvedHeaderDirective Header;
2438cfca06d7SDimitry Andric Header.FileName = std::string(Tok.getString());
24399f4dbff6SDimitry Andric Header.FileNameLoc = consumeToken();
2440b5aee35cSDimitry Andric Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
2441e3b55780SDimitry Andric Header.Kind = Map.headerRoleToKind(Role);
2442dbe13110SDimitry Andric
2443dbe13110SDimitry Andric // Check whether we already have an umbrella.
2444b1c73532SDimitry Andric if (Header.IsUmbrella &&
2445b1c73532SDimitry Andric !std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
24469f4dbff6SDimitry Andric Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2447dbe13110SDimitry Andric << ActiveModule->getFullModuleName();
2448dbe13110SDimitry Andric HadError = true;
2449dbe13110SDimitry Andric return;
2450dbe13110SDimitry Andric }
2451dbe13110SDimitry Andric
2452551c6985SDimitry Andric // If we were given stat information, parse it so we can skip looking for
2453551c6985SDimitry Andric // the file.
2454551c6985SDimitry Andric if (Tok.is(MMToken::LBrace)) {
2455551c6985SDimitry Andric SourceLocation LBraceLoc = consumeToken();
2456dbe13110SDimitry Andric
2457551c6985SDimitry Andric while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
2458551c6985SDimitry Andric enum Attribute { Size, ModTime, Unknown };
2459551c6985SDimitry Andric StringRef Str = Tok.getString();
2460551c6985SDimitry Andric SourceLocation Loc = consumeToken();
2461551c6985SDimitry Andric switch (llvm::StringSwitch<Attribute>(Str)
2462551c6985SDimitry Andric .Case("size", Size)
2463551c6985SDimitry Andric .Case("mtime", ModTime)
2464551c6985SDimitry Andric .Default(Unknown)) {
2465551c6985SDimitry Andric case Size:
2466551c6985SDimitry Andric if (Header.Size)
2467551c6985SDimitry Andric Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2468551c6985SDimitry Andric if (!Tok.is(MMToken::IntegerLiteral)) {
2469551c6985SDimitry Andric Diags.Report(Tok.getLocation(),
2470551c6985SDimitry Andric diag::err_mmap_invalid_header_attribute_value) << Str;
2471551c6985SDimitry Andric skipUntil(MMToken::RBrace);
2472551c6985SDimitry Andric break;
2473551c6985SDimitry Andric }
2474551c6985SDimitry Andric Header.Size = Tok.getInteger();
2475551c6985SDimitry Andric consumeToken();
2476551c6985SDimitry Andric break;
2477551c6985SDimitry Andric
2478551c6985SDimitry Andric case ModTime:
2479551c6985SDimitry Andric if (Header.ModTime)
2480551c6985SDimitry Andric Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
2481551c6985SDimitry Andric if (!Tok.is(MMToken::IntegerLiteral)) {
2482551c6985SDimitry Andric Diags.Report(Tok.getLocation(),
2483551c6985SDimitry Andric diag::err_mmap_invalid_header_attribute_value) << Str;
2484551c6985SDimitry Andric skipUntil(MMToken::RBrace);
2485551c6985SDimitry Andric break;
2486551c6985SDimitry Andric }
2487551c6985SDimitry Andric Header.ModTime = Tok.getInteger();
2488551c6985SDimitry Andric consumeToken();
2489551c6985SDimitry Andric break;
2490551c6985SDimitry Andric
2491551c6985SDimitry Andric case Unknown:
2492551c6985SDimitry Andric Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
2493551c6985SDimitry Andric skipUntil(MMToken::RBrace);
2494551c6985SDimitry Andric break;
2495551c6985SDimitry Andric }
2496dbe13110SDimitry Andric }
2497dbe13110SDimitry Andric
2498551c6985SDimitry Andric if (Tok.is(MMToken::RBrace))
2499551c6985SDimitry Andric consumeToken();
2500551c6985SDimitry Andric else {
2501551c6985SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2502551c6985SDimitry Andric Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2503dbe13110SDimitry Andric HadError = true;
2504dbe13110SDimitry Andric }
250506d4ba38SDimitry Andric }
250606d4ba38SDimitry Andric
250748675466SDimitry Andric bool NeedsFramework = false;
2508ac9a064cSDimitry Andric // Don't add headers to the builtin modules if the builtin headers belong to
2509ac9a064cSDimitry Andric // the system modules, with the exception of __stddef_max_align_t.h which
2510ac9a064cSDimitry Andric // always had its own module.
2511ac9a064cSDimitry Andric if (!Map.LangOpts.BuiltinHeadersInSystemModules ||
2512ac9a064cSDimitry Andric !isBuiltInModuleName(ActiveModule->getTopLevelModuleName()) ||
2513ac9a064cSDimitry Andric ActiveModule->fullModuleNameIs({"_Builtin_stddef", "max_align_t"}))
251448675466SDimitry Andric Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
251548675466SDimitry Andric
25167fa27ce4SDimitry Andric if (NeedsFramework)
251748675466SDimitry Andric Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
251848675466SDimitry Andric << ActiveModule->getFullModuleName()
251948675466SDimitry Andric << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
2520dbe13110SDimitry Andric }
2521dbe13110SDimitry Andric
compareModuleHeaders(const Module::Header & A,const Module::Header & B)2522b1c73532SDimitry Andric static bool compareModuleHeaders(const Module::Header &A,
2523b1c73532SDimitry Andric const Module::Header &B) {
2524b1c73532SDimitry Andric return A.NameAsWritten < B.NameAsWritten;
252545b53394SDimitry Andric }
252645b53394SDimitry Andric
252748675466SDimitry Andric /// Parse an umbrella directory declaration.
2528dbe13110SDimitry Andric ///
2529dbe13110SDimitry Andric /// umbrella-dir-declaration:
2530dbe13110SDimitry Andric /// umbrella string-literal
parseUmbrellaDirDecl(SourceLocation UmbrellaLoc)2531dbe13110SDimitry Andric void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
2532dbe13110SDimitry Andric // Parse the directory name.
2533dbe13110SDimitry Andric if (!Tok.is(MMToken::StringLiteral)) {
2534dbe13110SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
2535dbe13110SDimitry Andric << "umbrella";
2536dbe13110SDimitry Andric HadError = true;
2537dbe13110SDimitry Andric return;
2538dbe13110SDimitry Andric }
2539dbe13110SDimitry Andric
2540cfca06d7SDimitry Andric std::string DirName = std::string(Tok.getString());
2541344a3780SDimitry Andric std::string DirNameAsWritten = DirName;
2542dbe13110SDimitry Andric SourceLocation DirNameLoc = consumeToken();
2543dbe13110SDimitry Andric
2544dbe13110SDimitry Andric // Check whether we already have an umbrella.
2545b1c73532SDimitry Andric if (!std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
2546dbe13110SDimitry Andric Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
2547dbe13110SDimitry Andric << ActiveModule->getFullModuleName();
2548dbe13110SDimitry Andric HadError = true;
2549dbe13110SDimitry Andric return;
2550dbe13110SDimitry Andric }
2551dbe13110SDimitry Andric
2552dbe13110SDimitry Andric // Look for this file.
25537fa27ce4SDimitry Andric OptionalDirectoryEntryRef Dir;
2554519fc96cSDimitry Andric if (llvm::sys::path::is_absolute(DirName)) {
25557fa27ce4SDimitry Andric Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
2556519fc96cSDimitry Andric } else {
2557dbe13110SDimitry Andric SmallString<128> PathName;
25587fa27ce4SDimitry Andric PathName = Directory.getName();
2559dbe13110SDimitry Andric llvm::sys::path::append(PathName, DirName);
25607fa27ce4SDimitry Andric Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(PathName);
2561dbe13110SDimitry Andric }
2562dbe13110SDimitry Andric
2563dbe13110SDimitry Andric if (!Dir) {
2564583e75ccSDimitry Andric Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
2565dbe13110SDimitry Andric << DirName;
2566dbe13110SDimitry Andric return;
2567dbe13110SDimitry Andric }
2568dbe13110SDimitry Andric
256945b53394SDimitry Andric if (UsesRequiresExcludedHack.count(ActiveModule)) {
257045b53394SDimitry Andric // Mark this header 'textual' (see doc comment for
257145b53394SDimitry Andric // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
257245b53394SDimitry Andric // directory is relatively expensive, in practice this only applies to the
257345b53394SDimitry Andric // uncommonly used Tcl module on Darwin platforms.
257445b53394SDimitry Andric std::error_code EC;
257545b53394SDimitry Andric SmallVector<Module::Header, 6> Headers;
2576676fbe81SDimitry Andric llvm::vfs::FileSystem &FS =
257722989816SDimitry Andric SourceMgr.getFileManager().getVirtualFileSystem();
2578676fbe81SDimitry Andric for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
257945b53394SDimitry Andric I != E && !EC; I.increment(EC)) {
2580e3b55780SDimitry Andric if (auto FE = SourceMgr.getFileManager().getOptionalFileRef(I->path())) {
25817fa27ce4SDimitry Andric Module::Header Header = {"", std::string(I->path()), *FE};
258245b53394SDimitry Andric Headers.push_back(std::move(Header));
258345b53394SDimitry Andric }
258445b53394SDimitry Andric }
258545b53394SDimitry Andric
258645b53394SDimitry Andric // Sort header paths so that the pcm doesn't depend on iteration order.
2587b1c73532SDimitry Andric std::stable_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
258845b53394SDimitry Andric
258945b53394SDimitry Andric for (auto &Header : Headers)
259045b53394SDimitry Andric Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
259145b53394SDimitry Andric return;
259245b53394SDimitry Andric }
259345b53394SDimitry Andric
25947fa27ce4SDimitry Andric if (Module *OwningModule = Map.UmbrellaDirs[*Dir]) {
2595dbe13110SDimitry Andric Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
2596dbe13110SDimitry Andric << OwningModule->getFullModuleName();
2597dbe13110SDimitry Andric HadError = true;
2598dbe13110SDimitry Andric return;
2599dbe13110SDimitry Andric }
2600dbe13110SDimitry Andric
2601dbe13110SDimitry Andric // Record this umbrella directory.
26027fa27ce4SDimitry Andric Map.setUmbrellaDirAsWritten(ActiveModule, *Dir, DirNameAsWritten, DirName);
2603dbe13110SDimitry Andric }
2604dbe13110SDimitry Andric
260548675466SDimitry Andric /// Parse a module export declaration.
2606dbe13110SDimitry Andric ///
2607dbe13110SDimitry Andric /// export-declaration:
2608dbe13110SDimitry Andric /// 'export' wildcard-module-id
2609dbe13110SDimitry Andric ///
2610dbe13110SDimitry Andric /// wildcard-module-id:
2611dbe13110SDimitry Andric /// identifier
2612dbe13110SDimitry Andric /// '*'
2613dbe13110SDimitry Andric /// identifier '.' wildcard-module-id
parseExportDecl()2614dbe13110SDimitry Andric void ModuleMapParser::parseExportDecl() {
2615dbe13110SDimitry Andric assert(Tok.is(MMToken::ExportKeyword));
2616dbe13110SDimitry Andric SourceLocation ExportLoc = consumeToken();
2617dbe13110SDimitry Andric
2618dbe13110SDimitry Andric // Parse the module-id with an optional wildcard at the end.
2619dbe13110SDimitry Andric ModuleId ParsedModuleId;
2620dbe13110SDimitry Andric bool Wildcard = false;
2621dbe13110SDimitry Andric do {
262206d4ba38SDimitry Andric // FIXME: Support string-literal module names here.
2623dbe13110SDimitry Andric if (Tok.is(MMToken::Identifier)) {
2624cfca06d7SDimitry Andric ParsedModuleId.push_back(
2625cfca06d7SDimitry Andric std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
2626dbe13110SDimitry Andric consumeToken();
2627dbe13110SDimitry Andric
2628dbe13110SDimitry Andric if (Tok.is(MMToken::Period)) {
2629dbe13110SDimitry Andric consumeToken();
2630dbe13110SDimitry Andric continue;
2631dbe13110SDimitry Andric }
2632dbe13110SDimitry Andric
2633dbe13110SDimitry Andric break;
2634dbe13110SDimitry Andric }
2635dbe13110SDimitry Andric
2636dbe13110SDimitry Andric if(Tok.is(MMToken::Star)) {
2637dbe13110SDimitry Andric Wildcard = true;
2638dbe13110SDimitry Andric consumeToken();
2639dbe13110SDimitry Andric break;
2640dbe13110SDimitry Andric }
2641dbe13110SDimitry Andric
2642bfef3995SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
2643dbe13110SDimitry Andric HadError = true;
2644dbe13110SDimitry Andric return;
2645dbe13110SDimitry Andric } while (true);
2646dbe13110SDimitry Andric
2647dbe13110SDimitry Andric Module::UnresolvedExportDecl Unresolved = {
2648dbe13110SDimitry Andric ExportLoc, ParsedModuleId, Wildcard
2649dbe13110SDimitry Andric };
2650dbe13110SDimitry Andric ActiveModule->UnresolvedExports.push_back(Unresolved);
2651dbe13110SDimitry Andric }
2652dbe13110SDimitry Andric
265348675466SDimitry Andric /// Parse a module export_as declaration.
2654461a67faSDimitry Andric ///
2655461a67faSDimitry Andric /// export-as-declaration:
2656461a67faSDimitry Andric /// 'export_as' identifier
parseExportAsDecl()2657461a67faSDimitry Andric void ModuleMapParser::parseExportAsDecl() {
2658461a67faSDimitry Andric assert(Tok.is(MMToken::ExportAsKeyword));
2659461a67faSDimitry Andric consumeToken();
2660461a67faSDimitry Andric
2661461a67faSDimitry Andric if (!Tok.is(MMToken::Identifier)) {
2662461a67faSDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
2663461a67faSDimitry Andric HadError = true;
2664461a67faSDimitry Andric return;
2665461a67faSDimitry Andric }
2666461a67faSDimitry Andric
2667461a67faSDimitry Andric if (ActiveModule->Parent) {
2668461a67faSDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
2669461a67faSDimitry Andric consumeToken();
2670461a67faSDimitry Andric return;
2671461a67faSDimitry Andric }
2672461a67faSDimitry Andric
2673461a67faSDimitry Andric if (!ActiveModule->ExportAsModule.empty()) {
2674461a67faSDimitry Andric if (ActiveModule->ExportAsModule == Tok.getString()) {
2675461a67faSDimitry Andric Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
2676461a67faSDimitry Andric << ActiveModule->Name << Tok.getString();
2677461a67faSDimitry Andric } else {
2678461a67faSDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
2679461a67faSDimitry Andric << ActiveModule->Name << ActiveModule->ExportAsModule
2680461a67faSDimitry Andric << Tok.getString();
2681461a67faSDimitry Andric }
2682461a67faSDimitry Andric }
2683461a67faSDimitry Andric
2684cfca06d7SDimitry Andric ActiveModule->ExportAsModule = std::string(Tok.getString());
268548675466SDimitry Andric Map.addLinkAsDependency(ActiveModule);
268648675466SDimitry Andric
2687461a67faSDimitry Andric consumeToken();
2688461a67faSDimitry Andric }
2689461a67faSDimitry Andric
269048675466SDimitry Andric /// Parse a module use declaration.
2691bfef3995SDimitry Andric ///
26925e20cdd8SDimitry Andric /// use-declaration:
26935e20cdd8SDimitry Andric /// 'use' wildcard-module-id
parseUseDecl()2694bfef3995SDimitry Andric void ModuleMapParser::parseUseDecl() {
2695bfef3995SDimitry Andric assert(Tok.is(MMToken::UseKeyword));
26965e20cdd8SDimitry Andric auto KWLoc = consumeToken();
2697bfef3995SDimitry Andric // Parse the module-id.
2698bfef3995SDimitry Andric ModuleId ParsedModuleId;
26999f4dbff6SDimitry Andric parseModuleId(ParsedModuleId);
2700bfef3995SDimitry Andric
27015e20cdd8SDimitry Andric if (ActiveModule->Parent)
27025e20cdd8SDimitry Andric Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
27035e20cdd8SDimitry Andric else
2704bfef3995SDimitry Andric ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
2705bfef3995SDimitry Andric }
2706bfef3995SDimitry Andric
270748675466SDimitry Andric /// Parse a link declaration.
2708809500fcSDimitry Andric ///
2709809500fcSDimitry Andric /// module-declaration:
2710809500fcSDimitry Andric /// 'link' 'framework'[opt] string-literal
parseLinkDecl()2711809500fcSDimitry Andric void ModuleMapParser::parseLinkDecl() {
2712809500fcSDimitry Andric assert(Tok.is(MMToken::LinkKeyword));
2713809500fcSDimitry Andric SourceLocation LinkLoc = consumeToken();
2714809500fcSDimitry Andric
2715809500fcSDimitry Andric // Parse the optional 'framework' keyword.
2716809500fcSDimitry Andric bool IsFramework = false;
2717809500fcSDimitry Andric if (Tok.is(MMToken::FrameworkKeyword)) {
2718809500fcSDimitry Andric consumeToken();
2719809500fcSDimitry Andric IsFramework = true;
2720809500fcSDimitry Andric }
2721809500fcSDimitry Andric
2722809500fcSDimitry Andric // Parse the library name
2723809500fcSDimitry Andric if (!Tok.is(MMToken::StringLiteral)) {
2724809500fcSDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
2725809500fcSDimitry Andric << IsFramework << SourceRange(LinkLoc);
2726809500fcSDimitry Andric HadError = true;
2727809500fcSDimitry Andric return;
2728809500fcSDimitry Andric }
2729809500fcSDimitry Andric
2730cfca06d7SDimitry Andric std::string LibraryName = std::string(Tok.getString());
2731809500fcSDimitry Andric consumeToken();
2732809500fcSDimitry Andric ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
2733809500fcSDimitry Andric IsFramework));
2734809500fcSDimitry Andric }
2735809500fcSDimitry Andric
273648675466SDimitry Andric /// Parse a configuration macro declaration.
2737809500fcSDimitry Andric ///
2738809500fcSDimitry Andric /// module-declaration:
2739809500fcSDimitry Andric /// 'config_macros' attributes[opt] config-macro-list?
2740809500fcSDimitry Andric ///
2741809500fcSDimitry Andric /// config-macro-list:
2742809500fcSDimitry Andric /// identifier (',' identifier)?
parseConfigMacros()2743809500fcSDimitry Andric void ModuleMapParser::parseConfigMacros() {
2744809500fcSDimitry Andric assert(Tok.is(MMToken::ConfigMacros));
2745809500fcSDimitry Andric SourceLocation ConfigMacrosLoc = consumeToken();
2746809500fcSDimitry Andric
2747809500fcSDimitry Andric // Only top-level modules can have configuration macros.
2748809500fcSDimitry Andric if (ActiveModule->Parent) {
2749809500fcSDimitry Andric Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
2750809500fcSDimitry Andric }
2751809500fcSDimitry Andric
2752809500fcSDimitry Andric // Parse the optional attributes.
2753809500fcSDimitry Andric Attributes Attrs;
27542b6b257fSDimitry Andric if (parseOptionalAttributes(Attrs))
27552b6b257fSDimitry Andric return;
27562b6b257fSDimitry Andric
2757809500fcSDimitry Andric if (Attrs.IsExhaustive && !ActiveModule->Parent) {
2758809500fcSDimitry Andric ActiveModule->ConfigMacrosExhaustive = true;
2759809500fcSDimitry Andric }
2760809500fcSDimitry Andric
2761809500fcSDimitry Andric // If we don't have an identifier, we're done.
276206d4ba38SDimitry Andric // FIXME: Support macros with the same name as a keyword here.
2763809500fcSDimitry Andric if (!Tok.is(MMToken::Identifier))
2764809500fcSDimitry Andric return;
2765809500fcSDimitry Andric
2766809500fcSDimitry Andric // Consume the first identifier.
2767809500fcSDimitry Andric if (!ActiveModule->Parent) {
2768809500fcSDimitry Andric ActiveModule->ConfigMacros.push_back(Tok.getString().str());
2769809500fcSDimitry Andric }
2770809500fcSDimitry Andric consumeToken();
2771809500fcSDimitry Andric
2772809500fcSDimitry Andric do {
2773809500fcSDimitry Andric // If there's a comma, consume it.
2774809500fcSDimitry Andric if (!Tok.is(MMToken::Comma))
2775809500fcSDimitry Andric break;
2776809500fcSDimitry Andric consumeToken();
2777809500fcSDimitry Andric
2778809500fcSDimitry Andric // We expect to see a macro name here.
277906d4ba38SDimitry Andric // FIXME: Support macros with the same name as a keyword here.
2780809500fcSDimitry Andric if (!Tok.is(MMToken::Identifier)) {
2781809500fcSDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
2782809500fcSDimitry Andric break;
2783809500fcSDimitry Andric }
2784809500fcSDimitry Andric
2785809500fcSDimitry Andric // Consume the macro name.
2786809500fcSDimitry Andric if (!ActiveModule->Parent) {
2787809500fcSDimitry Andric ActiveModule->ConfigMacros.push_back(Tok.getString().str());
2788809500fcSDimitry Andric }
2789809500fcSDimitry Andric consumeToken();
2790809500fcSDimitry Andric } while (true);
2791809500fcSDimitry Andric }
2792809500fcSDimitry Andric
279348675466SDimitry Andric /// Format a module-id into a string.
formatModuleId(const ModuleId & Id)2794809500fcSDimitry Andric static std::string formatModuleId(const ModuleId &Id) {
2795809500fcSDimitry Andric std::string result;
2796809500fcSDimitry Andric {
2797809500fcSDimitry Andric llvm::raw_string_ostream OS(result);
2798809500fcSDimitry Andric
2799809500fcSDimitry Andric for (unsigned I = 0, N = Id.size(); I != N; ++I) {
2800809500fcSDimitry Andric if (I)
2801809500fcSDimitry Andric OS << ".";
2802809500fcSDimitry Andric OS << Id[I].first;
2803809500fcSDimitry Andric }
2804809500fcSDimitry Andric }
2805809500fcSDimitry Andric
2806809500fcSDimitry Andric return result;
2807809500fcSDimitry Andric }
2808809500fcSDimitry Andric
280948675466SDimitry Andric /// Parse a conflict declaration.
2810809500fcSDimitry Andric ///
2811809500fcSDimitry Andric /// module-declaration:
2812809500fcSDimitry Andric /// 'conflict' module-id ',' string-literal
parseConflict()2813809500fcSDimitry Andric void ModuleMapParser::parseConflict() {
2814809500fcSDimitry Andric assert(Tok.is(MMToken::Conflict));
2815809500fcSDimitry Andric SourceLocation ConflictLoc = consumeToken();
2816809500fcSDimitry Andric Module::UnresolvedConflict Conflict;
2817809500fcSDimitry Andric
2818809500fcSDimitry Andric // Parse the module-id.
2819809500fcSDimitry Andric if (parseModuleId(Conflict.Id))
2820809500fcSDimitry Andric return;
2821809500fcSDimitry Andric
2822809500fcSDimitry Andric // Parse the ','.
2823809500fcSDimitry Andric if (!Tok.is(MMToken::Comma)) {
2824809500fcSDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
2825809500fcSDimitry Andric << SourceRange(ConflictLoc);
2826809500fcSDimitry Andric return;
2827809500fcSDimitry Andric }
2828809500fcSDimitry Andric consumeToken();
2829809500fcSDimitry Andric
2830809500fcSDimitry Andric // Parse the message.
2831809500fcSDimitry Andric if (!Tok.is(MMToken::StringLiteral)) {
2832809500fcSDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
2833809500fcSDimitry Andric << formatModuleId(Conflict.Id);
2834809500fcSDimitry Andric return;
2835809500fcSDimitry Andric }
2836809500fcSDimitry Andric Conflict.Message = Tok.getString().str();
2837809500fcSDimitry Andric consumeToken();
2838809500fcSDimitry Andric
2839809500fcSDimitry Andric // Add this unresolved conflict.
2840809500fcSDimitry Andric ActiveModule->UnresolvedConflicts.push_back(Conflict);
2841809500fcSDimitry Andric }
2842809500fcSDimitry Andric
284348675466SDimitry Andric /// Parse an inferred module declaration (wildcard modules).
284413cc256eSDimitry Andric ///
284513cc256eSDimitry Andric /// module-declaration:
284613cc256eSDimitry Andric /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
284713cc256eSDimitry Andric /// { inferred-module-member* }
284813cc256eSDimitry Andric ///
284913cc256eSDimitry Andric /// inferred-module-member:
285013cc256eSDimitry Andric /// 'export' '*'
285113cc256eSDimitry Andric /// 'exclude' identifier
parseInferredModuleDecl(bool Framework,bool Explicit)285213cc256eSDimitry Andric void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
2853dbe13110SDimitry Andric assert(Tok.is(MMToken::Star));
2854dbe13110SDimitry Andric SourceLocation StarLoc = consumeToken();
2855dbe13110SDimitry Andric bool Failed = false;
2856dbe13110SDimitry Andric
2857dbe13110SDimitry Andric // Inferred modules must be submodules.
285813cc256eSDimitry Andric if (!ActiveModule && !Framework) {
2859dbe13110SDimitry Andric Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
2860dbe13110SDimitry Andric Failed = true;
2861dbe13110SDimitry Andric }
2862dbe13110SDimitry Andric
286313cc256eSDimitry Andric if (ActiveModule) {
2864dbe13110SDimitry Andric // Inferred modules must have umbrella directories.
28659f4dbff6SDimitry Andric if (!Failed && ActiveModule->IsAvailable &&
28667fa27ce4SDimitry Andric !ActiveModule->getEffectiveUmbrellaDir()) {
2867dbe13110SDimitry Andric Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
2868dbe13110SDimitry Andric Failed = true;
2869dbe13110SDimitry Andric }
2870dbe13110SDimitry Andric
2871dbe13110SDimitry Andric // Check for redefinition of an inferred module.
2872dbe13110SDimitry Andric if (!Failed && ActiveModule->InferSubmodules) {
2873dbe13110SDimitry Andric Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2874dbe13110SDimitry Andric if (ActiveModule->InferredSubmoduleLoc.isValid())
2875dbe13110SDimitry Andric Diags.Report(ActiveModule->InferredSubmoduleLoc,
2876dbe13110SDimitry Andric diag::note_mmap_prev_definition);
2877dbe13110SDimitry Andric Failed = true;
2878dbe13110SDimitry Andric }
2879dbe13110SDimitry Andric
288013cc256eSDimitry Andric // Check for the 'framework' keyword, which is not permitted here.
288113cc256eSDimitry Andric if (Framework) {
288213cc256eSDimitry Andric Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
288313cc256eSDimitry Andric Framework = false;
288413cc256eSDimitry Andric }
288513cc256eSDimitry Andric } else if (Explicit) {
288613cc256eSDimitry Andric Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
288713cc256eSDimitry Andric Explicit = false;
288813cc256eSDimitry Andric }
288913cc256eSDimitry Andric
2890dbe13110SDimitry Andric // If there were any problems with this inferred submodule, skip its body.
2891dbe13110SDimitry Andric if (Failed) {
2892dbe13110SDimitry Andric if (Tok.is(MMToken::LBrace)) {
2893dbe13110SDimitry Andric consumeToken();
2894dbe13110SDimitry Andric skipUntil(MMToken::RBrace);
2895dbe13110SDimitry Andric if (Tok.is(MMToken::RBrace))
2896dbe13110SDimitry Andric consumeToken();
2897dbe13110SDimitry Andric }
2898dbe13110SDimitry Andric HadError = true;
2899dbe13110SDimitry Andric return;
2900dbe13110SDimitry Andric }
2901dbe13110SDimitry Andric
290213cc256eSDimitry Andric // Parse optional attributes.
290313cc256eSDimitry Andric Attributes Attrs;
29042b6b257fSDimitry Andric if (parseOptionalAttributes(Attrs))
29052b6b257fSDimitry Andric return;
290613cc256eSDimitry Andric
290713cc256eSDimitry Andric if (ActiveModule) {
2908dbe13110SDimitry Andric // Note that we have an inferred submodule.
2909dbe13110SDimitry Andric ActiveModule->InferSubmodules = true;
2910dbe13110SDimitry Andric ActiveModule->InferredSubmoduleLoc = StarLoc;
2911dbe13110SDimitry Andric ActiveModule->InferExplicitSubmodules = Explicit;
291213cc256eSDimitry Andric } else {
291313cc256eSDimitry Andric // We'll be inferring framework modules for this directory.
291413cc256eSDimitry Andric Map.InferredDirectories[Directory].InferModules = true;
291506d4ba38SDimitry Andric Map.InferredDirectories[Directory].Attrs = Attrs;
2916ac9a064cSDimitry Andric Map.InferredDirectories[Directory].ModuleMapFID = ModuleMapFID;
29179f4dbff6SDimitry Andric // FIXME: Handle the 'framework' keyword.
291813cc256eSDimitry Andric }
2919dbe13110SDimitry Andric
2920dbe13110SDimitry Andric // Parse the opening brace.
2921dbe13110SDimitry Andric if (!Tok.is(MMToken::LBrace)) {
2922dbe13110SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
2923dbe13110SDimitry Andric HadError = true;
2924dbe13110SDimitry Andric return;
2925dbe13110SDimitry Andric }
2926dbe13110SDimitry Andric SourceLocation LBraceLoc = consumeToken();
2927dbe13110SDimitry Andric
2928dbe13110SDimitry Andric // Parse the body of the inferred submodule.
2929dbe13110SDimitry Andric bool Done = false;
2930dbe13110SDimitry Andric do {
2931dbe13110SDimitry Andric switch (Tok.Kind) {
2932dbe13110SDimitry Andric case MMToken::EndOfFile:
2933dbe13110SDimitry Andric case MMToken::RBrace:
2934dbe13110SDimitry Andric Done = true;
2935dbe13110SDimitry Andric break;
2936dbe13110SDimitry Andric
2937461a67faSDimitry Andric case MMToken::ExcludeKeyword:
293813cc256eSDimitry Andric if (ActiveModule) {
293913cc256eSDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
29409f4dbff6SDimitry Andric << (ActiveModule != nullptr);
294113cc256eSDimitry Andric consumeToken();
294213cc256eSDimitry Andric break;
294313cc256eSDimitry Andric }
294413cc256eSDimitry Andric
294513cc256eSDimitry Andric consumeToken();
294606d4ba38SDimitry Andric // FIXME: Support string-literal module names here.
294713cc256eSDimitry Andric if (!Tok.is(MMToken::Identifier)) {
294813cc256eSDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
294913cc256eSDimitry Andric break;
295013cc256eSDimitry Andric }
295113cc256eSDimitry Andric
2952cfca06d7SDimitry Andric Map.InferredDirectories[Directory].ExcludedModules.push_back(
2953cfca06d7SDimitry Andric std::string(Tok.getString()));
295413cc256eSDimitry Andric consumeToken();
295513cc256eSDimitry Andric break;
295613cc256eSDimitry Andric
295713cc256eSDimitry Andric case MMToken::ExportKeyword:
295813cc256eSDimitry Andric if (!ActiveModule) {
295913cc256eSDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
29609f4dbff6SDimitry Andric << (ActiveModule != nullptr);
296113cc256eSDimitry Andric consumeToken();
296213cc256eSDimitry Andric break;
296313cc256eSDimitry Andric }
296413cc256eSDimitry Andric
2965dbe13110SDimitry Andric consumeToken();
2966dbe13110SDimitry Andric if (Tok.is(MMToken::Star))
2967dbe13110SDimitry Andric ActiveModule->InferExportWildcard = true;
2968dbe13110SDimitry Andric else
2969dbe13110SDimitry Andric Diags.Report(Tok.getLocation(),
2970dbe13110SDimitry Andric diag::err_mmap_expected_export_wildcard);
2971dbe13110SDimitry Andric consumeToken();
2972dbe13110SDimitry Andric break;
2973dbe13110SDimitry Andric
2974dbe13110SDimitry Andric case MMToken::ExplicitKeyword:
2975dbe13110SDimitry Andric case MMToken::ModuleKeyword:
2976dbe13110SDimitry Andric case MMToken::HeaderKeyword:
2977bfef3995SDimitry Andric case MMToken::PrivateKeyword:
2978dbe13110SDimitry Andric case MMToken::UmbrellaKeyword:
2979dbe13110SDimitry Andric default:
298013cc256eSDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
29819f4dbff6SDimitry Andric << (ActiveModule != nullptr);
2982dbe13110SDimitry Andric consumeToken();
2983dbe13110SDimitry Andric break;
2984dbe13110SDimitry Andric }
2985dbe13110SDimitry Andric } while (!Done);
2986dbe13110SDimitry Andric
2987dbe13110SDimitry Andric if (Tok.is(MMToken::RBrace))
2988dbe13110SDimitry Andric consumeToken();
2989dbe13110SDimitry Andric else {
2990dbe13110SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2991dbe13110SDimitry Andric Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2992dbe13110SDimitry Andric HadError = true;
2993dbe13110SDimitry Andric }
2994dbe13110SDimitry Andric }
2995dbe13110SDimitry Andric
299648675466SDimitry Andric /// Parse optional attributes.
299713cc256eSDimitry Andric ///
299813cc256eSDimitry Andric /// attributes:
299913cc256eSDimitry Andric /// attribute attributes
300013cc256eSDimitry Andric /// attribute
300113cc256eSDimitry Andric ///
300213cc256eSDimitry Andric /// attribute:
300313cc256eSDimitry Andric /// [ identifier ]
300413cc256eSDimitry Andric ///
300513cc256eSDimitry Andric /// \param Attrs Will be filled in with the parsed attributes.
300613cc256eSDimitry Andric ///
300713cc256eSDimitry Andric /// \returns true if an error occurred, false otherwise.
parseOptionalAttributes(Attributes & Attrs)300813cc256eSDimitry Andric bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
300913cc256eSDimitry Andric bool HadError = false;
301013cc256eSDimitry Andric
301113cc256eSDimitry Andric while (Tok.is(MMToken::LSquare)) {
301213cc256eSDimitry Andric // Consume the '['.
301313cc256eSDimitry Andric SourceLocation LSquareLoc = consumeToken();
301413cc256eSDimitry Andric
301513cc256eSDimitry Andric // Check whether we have an attribute name here.
301613cc256eSDimitry Andric if (!Tok.is(MMToken::Identifier)) {
301713cc256eSDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
301813cc256eSDimitry Andric skipUntil(MMToken::RSquare);
301913cc256eSDimitry Andric if (Tok.is(MMToken::RSquare))
302013cc256eSDimitry Andric consumeToken();
302113cc256eSDimitry Andric HadError = true;
302213cc256eSDimitry Andric }
302313cc256eSDimitry Andric
302413cc256eSDimitry Andric // Decode the attribute name.
302513cc256eSDimitry Andric AttributeKind Attribute
302613cc256eSDimitry Andric = llvm::StringSwitch<AttributeKind>(Tok.getString())
3027809500fcSDimitry Andric .Case("exhaustive", AT_exhaustive)
30289f4dbff6SDimitry Andric .Case("extern_c", AT_extern_c)
3029bab175ecSDimitry Andric .Case("no_undeclared_includes", AT_no_undeclared_includes)
303013cc256eSDimitry Andric .Case("system", AT_system)
303113cc256eSDimitry Andric .Default(AT_unknown);
303213cc256eSDimitry Andric switch (Attribute) {
303313cc256eSDimitry Andric case AT_unknown:
303413cc256eSDimitry Andric Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
303513cc256eSDimitry Andric << Tok.getString();
303613cc256eSDimitry Andric break;
303713cc256eSDimitry Andric
303813cc256eSDimitry Andric case AT_system:
303913cc256eSDimitry Andric Attrs.IsSystem = true;
304013cc256eSDimitry Andric break;
3041809500fcSDimitry Andric
30429f4dbff6SDimitry Andric case AT_extern_c:
30439f4dbff6SDimitry Andric Attrs.IsExternC = true;
30449f4dbff6SDimitry Andric break;
30459f4dbff6SDimitry Andric
3046809500fcSDimitry Andric case AT_exhaustive:
3047809500fcSDimitry Andric Attrs.IsExhaustive = true;
3048809500fcSDimitry Andric break;
3049bab175ecSDimitry Andric
3050bab175ecSDimitry Andric case AT_no_undeclared_includes:
3051bab175ecSDimitry Andric Attrs.NoUndeclaredIncludes = true;
3052bab175ecSDimitry Andric break;
305313cc256eSDimitry Andric }
305413cc256eSDimitry Andric consumeToken();
305513cc256eSDimitry Andric
305613cc256eSDimitry Andric // Consume the ']'.
305713cc256eSDimitry Andric if (!Tok.is(MMToken::RSquare)) {
305813cc256eSDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
305913cc256eSDimitry Andric Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
306013cc256eSDimitry Andric skipUntil(MMToken::RSquare);
306113cc256eSDimitry Andric HadError = true;
306213cc256eSDimitry Andric }
306313cc256eSDimitry Andric
306413cc256eSDimitry Andric if (Tok.is(MMToken::RSquare))
306513cc256eSDimitry Andric consumeToken();
306613cc256eSDimitry Andric }
306713cc256eSDimitry Andric
306813cc256eSDimitry Andric return HadError;
306913cc256eSDimitry Andric }
307013cc256eSDimitry Andric
307148675466SDimitry Andric /// Parse a module map file.
3072dbe13110SDimitry Andric ///
3073dbe13110SDimitry Andric /// module-map-file:
3074dbe13110SDimitry Andric /// module-declaration*
parseModuleMapFile()3075dbe13110SDimitry Andric bool ModuleMapParser::parseModuleMapFile() {
3076dbe13110SDimitry Andric do {
3077dbe13110SDimitry Andric switch (Tok.Kind) {
3078dbe13110SDimitry Andric case MMToken::EndOfFile:
3079dbe13110SDimitry Andric return HadError;
3080dbe13110SDimitry Andric
3081dbe13110SDimitry Andric case MMToken::ExplicitKeyword:
3082bfef3995SDimitry Andric case MMToken::ExternKeyword:
3083dbe13110SDimitry Andric case MMToken::ModuleKeyword:
3084dbe13110SDimitry Andric case MMToken::FrameworkKeyword:
3085dbe13110SDimitry Andric parseModuleDecl();
3086dbe13110SDimitry Andric break;
3087dbe13110SDimitry Andric
3088dbe13110SDimitry Andric case MMToken::Comma:
3089809500fcSDimitry Andric case MMToken::ConfigMacros:
3090809500fcSDimitry Andric case MMToken::Conflict:
3091bfef3995SDimitry Andric case MMToken::Exclaim:
309213cc256eSDimitry Andric case MMToken::ExcludeKeyword:
3093dbe13110SDimitry Andric case MMToken::ExportKeyword:
3094461a67faSDimitry Andric case MMToken::ExportAsKeyword:
3095dbe13110SDimitry Andric case MMToken::HeaderKeyword:
3096dbe13110SDimitry Andric case MMToken::Identifier:
3097dbe13110SDimitry Andric case MMToken::LBrace:
3098809500fcSDimitry Andric case MMToken::LinkKeyword:
3099dbe13110SDimitry Andric case MMToken::LSquare:
3100dbe13110SDimitry Andric case MMToken::Period:
3101bfef3995SDimitry Andric case MMToken::PrivateKeyword:
3102dbe13110SDimitry Andric case MMToken::RBrace:
3103dbe13110SDimitry Andric case MMToken::RSquare:
3104dbe13110SDimitry Andric case MMToken::RequiresKeyword:
3105dbe13110SDimitry Andric case MMToken::Star:
3106dbe13110SDimitry Andric case MMToken::StringLiteral:
3107551c6985SDimitry Andric case MMToken::IntegerLiteral:
310806d4ba38SDimitry Andric case MMToken::TextualKeyword:
3109dbe13110SDimitry Andric case MMToken::UmbrellaKeyword:
3110bfef3995SDimitry Andric case MMToken::UseKeyword:
3111dbe13110SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
3112dbe13110SDimitry Andric HadError = true;
3113dbe13110SDimitry Andric consumeToken();
3114dbe13110SDimitry Andric break;
3115dbe13110SDimitry Andric }
3116dbe13110SDimitry Andric } while (true);
3117dbe13110SDimitry Andric }
3118dbe13110SDimitry Andric
parseModuleMapFile(FileEntryRef File,bool IsSystem,DirectoryEntryRef Dir,FileID ID,unsigned * Offset,SourceLocation ExternModuleLoc)3119b1c73532SDimitry Andric bool ModuleMap::parseModuleMapFile(FileEntryRef File, bool IsSystem,
31207fa27ce4SDimitry Andric DirectoryEntryRef Dir, FileID ID,
31210a5fb09bSDimitry Andric unsigned *Offset,
312251ece4aaSDimitry Andric SourceLocation ExternModuleLoc) {
31230a5fb09bSDimitry Andric assert(Target && "Missing target information");
3124809500fcSDimitry Andric llvm::DenseMap<const FileEntry *, bool>::iterator Known
3125809500fcSDimitry Andric = ParsedModuleMap.find(File);
3126809500fcSDimitry Andric if (Known != ParsedModuleMap.end())
3127809500fcSDimitry Andric return Known->second;
3128809500fcSDimitry Andric
31290a5fb09bSDimitry Andric // If the module map file wasn't already entered, do so now.
31300a5fb09bSDimitry Andric if (ID.isInvalid()) {
3131cf1b4019SDimitry Andric auto FileCharacter =
3132cf1b4019SDimitry Andric IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
31330a5fb09bSDimitry Andric ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
31340a5fb09bSDimitry Andric }
31350a5fb09bSDimitry Andric
31360a5fb09bSDimitry Andric assert(Target && "Missing target information");
3137e3b55780SDimitry Andric std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
3138dbe13110SDimitry Andric if (!Buffer)
3139809500fcSDimitry Andric return ParsedModuleMap[File] = true;
31400a5fb09bSDimitry Andric assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
31410a5fb09bSDimitry Andric "invalid buffer offset");
3142dbe13110SDimitry Andric
3143dbe13110SDimitry Andric // Parse this module map file.
31440a5fb09bSDimitry Andric Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
31450a5fb09bSDimitry Andric Buffer->getBufferStart(),
31460a5fb09bSDimitry Andric Buffer->getBufferStart() + (Offset ? *Offset : 0),
31470a5fb09bSDimitry Andric Buffer->getBufferEnd());
314845b53394SDimitry Andric SourceLocation Start = L.getSourceLocation();
3149ac9a064cSDimitry Andric ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, ID, Dir, IsSystem);
3150dbe13110SDimitry Andric bool Result = Parser.parseModuleMapFile();
3151809500fcSDimitry Andric ParsedModuleMap[File] = Result;
315245b53394SDimitry Andric
31530a5fb09bSDimitry Andric if (Offset) {
31540a5fb09bSDimitry Andric auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
31550a5fb09bSDimitry Andric assert(Loc.first == ID && "stopped in a different file?");
31560a5fb09bSDimitry Andric *Offset = Loc.second;
31570a5fb09bSDimitry Andric }
31580a5fb09bSDimitry Andric
315945b53394SDimitry Andric // Notify callbacks that we parsed it.
316045b53394SDimitry Andric for (const auto &Cb : Callbacks)
3161b1c73532SDimitry Andric Cb->moduleMapFileRead(Start, File, IsSystem);
316248675466SDimitry Andric
3163dbe13110SDimitry Andric return Result;
3164dbe13110SDimitry Andric }
3165