1f4a2713aSLionel Sambuc //===--- ModuleMap.cpp - Describe the layout of modules ---------*- C++ -*-===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This file defines the ModuleMap implementation, which describes the layout
11f4a2713aSLionel Sambuc // of a module as it relates to headers.
12f4a2713aSLionel Sambuc //
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc #include "clang/Lex/ModuleMap.h"
15f4a2713aSLionel Sambuc #include "clang/Basic/CharInfo.h"
16f4a2713aSLionel Sambuc #include "clang/Basic/Diagnostic.h"
17f4a2713aSLionel Sambuc #include "clang/Basic/DiagnosticOptions.h"
18f4a2713aSLionel Sambuc #include "clang/Basic/FileManager.h"
19f4a2713aSLionel Sambuc #include "clang/Basic/TargetInfo.h"
20f4a2713aSLionel Sambuc #include "clang/Basic/TargetOptions.h"
21f4a2713aSLionel Sambuc #include "clang/Lex/HeaderSearch.h"
22*0a6a1f1dSLionel Sambuc #include "clang/Lex/HeaderSearchOptions.h"
23f4a2713aSLionel Sambuc #include "clang/Lex/LexDiagnostic.h"
24f4a2713aSLionel Sambuc #include "clang/Lex/Lexer.h"
25f4a2713aSLionel Sambuc #include "clang/Lex/LiteralSupport.h"
26f4a2713aSLionel Sambuc #include "llvm/ADT/StringRef.h"
27f4a2713aSLionel Sambuc #include "llvm/ADT/StringSwitch.h"
28f4a2713aSLionel Sambuc #include "llvm/Support/Allocator.h"
29f4a2713aSLionel Sambuc #include "llvm/Support/FileSystem.h"
30f4a2713aSLionel Sambuc #include "llvm/Support/Host.h"
31f4a2713aSLionel Sambuc #include "llvm/Support/Path.h"
32f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
33f4a2713aSLionel Sambuc #include <stdlib.h>
34f4a2713aSLionel Sambuc #if defined(LLVM_ON_UNIX)
35f4a2713aSLionel Sambuc #include <limits.h>
36f4a2713aSLionel Sambuc #endif
37f4a2713aSLionel Sambuc using namespace clang;
38f4a2713aSLionel Sambuc
39f4a2713aSLionel Sambuc Module::ExportDecl
resolveExport(Module * Mod,const Module::UnresolvedExportDecl & Unresolved,bool Complain) const40f4a2713aSLionel Sambuc ModuleMap::resolveExport(Module *Mod,
41f4a2713aSLionel Sambuc const Module::UnresolvedExportDecl &Unresolved,
42f4a2713aSLionel Sambuc bool Complain) const {
43f4a2713aSLionel Sambuc // We may have just a wildcard.
44f4a2713aSLionel Sambuc if (Unresolved.Id.empty()) {
45f4a2713aSLionel Sambuc assert(Unresolved.Wildcard && "Invalid unresolved export");
46*0a6a1f1dSLionel Sambuc return Module::ExportDecl(nullptr, true);
47f4a2713aSLionel Sambuc }
48f4a2713aSLionel Sambuc
49f4a2713aSLionel Sambuc // Resolve the module-id.
50f4a2713aSLionel Sambuc Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
51f4a2713aSLionel Sambuc if (!Context)
52f4a2713aSLionel Sambuc return Module::ExportDecl();
53f4a2713aSLionel Sambuc
54f4a2713aSLionel Sambuc return Module::ExportDecl(Context, Unresolved.Wildcard);
55f4a2713aSLionel Sambuc }
56f4a2713aSLionel Sambuc
resolveModuleId(const ModuleId & Id,Module * Mod,bool Complain) const57f4a2713aSLionel Sambuc Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
58f4a2713aSLionel Sambuc bool Complain) const {
59f4a2713aSLionel Sambuc // Find the starting module.
60f4a2713aSLionel Sambuc Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
61f4a2713aSLionel Sambuc if (!Context) {
62f4a2713aSLionel Sambuc if (Complain)
63*0a6a1f1dSLionel Sambuc Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
64f4a2713aSLionel Sambuc << Id[0].first << Mod->getFullModuleName();
65f4a2713aSLionel Sambuc
66*0a6a1f1dSLionel Sambuc return nullptr;
67f4a2713aSLionel Sambuc }
68f4a2713aSLionel Sambuc
69f4a2713aSLionel Sambuc // Dig into the module path.
70f4a2713aSLionel Sambuc for (unsigned I = 1, N = Id.size(); I != N; ++I) {
71f4a2713aSLionel Sambuc Module *Sub = lookupModuleQualified(Id[I].first, Context);
72f4a2713aSLionel Sambuc if (!Sub) {
73f4a2713aSLionel Sambuc if (Complain)
74*0a6a1f1dSLionel Sambuc Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
75f4a2713aSLionel Sambuc << Id[I].first << Context->getFullModuleName()
76f4a2713aSLionel Sambuc << SourceRange(Id[0].second, Id[I-1].second);
77f4a2713aSLionel Sambuc
78*0a6a1f1dSLionel Sambuc return nullptr;
79f4a2713aSLionel Sambuc }
80f4a2713aSLionel Sambuc
81f4a2713aSLionel Sambuc Context = Sub;
82f4a2713aSLionel Sambuc }
83f4a2713aSLionel Sambuc
84f4a2713aSLionel Sambuc return Context;
85f4a2713aSLionel Sambuc }
86f4a2713aSLionel Sambuc
ModuleMap(SourceManager & SourceMgr,DiagnosticsEngine & Diags,const LangOptions & LangOpts,const TargetInfo * Target,HeaderSearch & HeaderInfo)87*0a6a1f1dSLionel Sambuc ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
88f4a2713aSLionel Sambuc const LangOptions &LangOpts, const TargetInfo *Target,
89f4a2713aSLionel Sambuc HeaderSearch &HeaderInfo)
90*0a6a1f1dSLionel Sambuc : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
91*0a6a1f1dSLionel Sambuc HeaderInfo(HeaderInfo), BuiltinIncludeDir(nullptr),
92*0a6a1f1dSLionel Sambuc CompilingModule(nullptr), SourceModule(nullptr) {}
93f4a2713aSLionel Sambuc
~ModuleMap()94f4a2713aSLionel Sambuc ModuleMap::~ModuleMap() {
95f4a2713aSLionel Sambuc for (llvm::StringMap<Module *>::iterator I = Modules.begin(),
96f4a2713aSLionel Sambuc IEnd = Modules.end();
97f4a2713aSLionel Sambuc I != IEnd; ++I) {
98f4a2713aSLionel Sambuc delete I->getValue();
99f4a2713aSLionel Sambuc }
100f4a2713aSLionel Sambuc }
101f4a2713aSLionel Sambuc
setTarget(const TargetInfo & Target)102f4a2713aSLionel Sambuc void ModuleMap::setTarget(const TargetInfo &Target) {
103f4a2713aSLionel Sambuc assert((!this->Target || this->Target == &Target) &&
104f4a2713aSLionel Sambuc "Improper target override");
105f4a2713aSLionel Sambuc this->Target = &Target;
106f4a2713aSLionel Sambuc }
107f4a2713aSLionel Sambuc
108f4a2713aSLionel Sambuc /// \brief "Sanitize" a filename so that it can be used as an identifier.
sanitizeFilenameAsIdentifier(StringRef Name,SmallVectorImpl<char> & Buffer)109f4a2713aSLionel Sambuc static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
110f4a2713aSLionel Sambuc SmallVectorImpl<char> &Buffer) {
111f4a2713aSLionel Sambuc if (Name.empty())
112f4a2713aSLionel Sambuc return Name;
113f4a2713aSLionel Sambuc
114f4a2713aSLionel Sambuc if (!isValidIdentifier(Name)) {
115f4a2713aSLionel Sambuc // If we don't already have something with the form of an identifier,
116f4a2713aSLionel Sambuc // create a buffer with the sanitized name.
117f4a2713aSLionel Sambuc Buffer.clear();
118f4a2713aSLionel Sambuc if (isDigit(Name[0]))
119f4a2713aSLionel Sambuc Buffer.push_back('_');
120f4a2713aSLionel Sambuc Buffer.reserve(Buffer.size() + Name.size());
121f4a2713aSLionel Sambuc for (unsigned I = 0, N = Name.size(); I != N; ++I) {
122f4a2713aSLionel Sambuc if (isIdentifierBody(Name[I]))
123f4a2713aSLionel Sambuc Buffer.push_back(Name[I]);
124f4a2713aSLionel Sambuc else
125f4a2713aSLionel Sambuc Buffer.push_back('_');
126f4a2713aSLionel Sambuc }
127f4a2713aSLionel Sambuc
128f4a2713aSLionel Sambuc Name = StringRef(Buffer.data(), Buffer.size());
129f4a2713aSLionel Sambuc }
130f4a2713aSLionel Sambuc
131f4a2713aSLionel Sambuc while (llvm::StringSwitch<bool>(Name)
132f4a2713aSLionel Sambuc #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
133f4a2713aSLionel Sambuc #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
134f4a2713aSLionel Sambuc #include "clang/Basic/TokenKinds.def"
135f4a2713aSLionel Sambuc .Default(false)) {
136f4a2713aSLionel Sambuc if (Name.data() != Buffer.data())
137f4a2713aSLionel Sambuc Buffer.append(Name.begin(), Name.end());
138f4a2713aSLionel Sambuc Buffer.push_back('_');
139f4a2713aSLionel Sambuc Name = StringRef(Buffer.data(), Buffer.size());
140f4a2713aSLionel Sambuc }
141f4a2713aSLionel Sambuc
142f4a2713aSLionel Sambuc return Name;
143f4a2713aSLionel Sambuc }
144f4a2713aSLionel Sambuc
145f4a2713aSLionel Sambuc /// \brief Determine whether the given file name is the name of a builtin
146f4a2713aSLionel Sambuc /// header, supplied by Clang to replace, override, or augment existing system
147f4a2713aSLionel Sambuc /// headers.
isBuiltinHeader(StringRef FileName)148f4a2713aSLionel Sambuc static bool isBuiltinHeader(StringRef FileName) {
149f4a2713aSLionel Sambuc return llvm::StringSwitch<bool>(FileName)
150f4a2713aSLionel Sambuc .Case("float.h", true)
151f4a2713aSLionel Sambuc .Case("iso646.h", true)
152f4a2713aSLionel Sambuc .Case("limits.h", true)
153f4a2713aSLionel Sambuc .Case("stdalign.h", true)
154f4a2713aSLionel Sambuc .Case("stdarg.h", true)
155f4a2713aSLionel Sambuc .Case("stdbool.h", true)
156f4a2713aSLionel Sambuc .Case("stddef.h", true)
157f4a2713aSLionel Sambuc .Case("stdint.h", true)
158f4a2713aSLionel Sambuc .Case("tgmath.h", true)
159f4a2713aSLionel Sambuc .Case("unwind.h", true)
160f4a2713aSLionel Sambuc .Default(false);
161f4a2713aSLionel Sambuc }
162f4a2713aSLionel Sambuc
163*0a6a1f1dSLionel Sambuc ModuleMap::HeadersMap::iterator
findKnownHeader(const FileEntry * File)164*0a6a1f1dSLionel Sambuc ModuleMap::findKnownHeader(const FileEntry *File) {
165f4a2713aSLionel Sambuc HeadersMap::iterator Known = Headers.find(File);
166*0a6a1f1dSLionel Sambuc if (Known == Headers.end() && File->getDir() == BuiltinIncludeDir &&
167f4a2713aSLionel Sambuc isBuiltinHeader(llvm::sys::path::filename(File->getName()))) {
168f4a2713aSLionel Sambuc HeaderInfo.loadTopLevelSystemModules();
169*0a6a1f1dSLionel Sambuc return Headers.find(File);
170*0a6a1f1dSLionel Sambuc }
171*0a6a1f1dSLionel Sambuc return Known;
172f4a2713aSLionel Sambuc }
173f4a2713aSLionel Sambuc
174*0a6a1f1dSLionel Sambuc ModuleMap::KnownHeader
findHeaderInUmbrellaDirs(const FileEntry * File,SmallVectorImpl<const DirectoryEntry * > & IntermediateDirs)175*0a6a1f1dSLionel Sambuc ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
176*0a6a1f1dSLionel Sambuc SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
177f4a2713aSLionel Sambuc const DirectoryEntry *Dir = File->getDir();
178*0a6a1f1dSLionel Sambuc assert(Dir && "file in no directory");
179f4a2713aSLionel Sambuc
180f4a2713aSLionel Sambuc // Note: as an egregious but useful hack we use the real path here, because
181f4a2713aSLionel Sambuc // frameworks moving from top-level frameworks to embedded frameworks tend
182f4a2713aSLionel Sambuc // to be symlinked from the top-level location to the embedded location,
183f4a2713aSLionel Sambuc // and we need to resolve lookups as if we had found the embedded location.
184f4a2713aSLionel Sambuc StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
185f4a2713aSLionel Sambuc
186f4a2713aSLionel Sambuc // Keep walking up the directory hierarchy, looking for a directory with
187f4a2713aSLionel Sambuc // an umbrella header.
188f4a2713aSLionel Sambuc do {
189*0a6a1f1dSLionel Sambuc auto KnownDir = UmbrellaDirs.find(Dir);
190*0a6a1f1dSLionel Sambuc if (KnownDir != UmbrellaDirs.end())
191*0a6a1f1dSLionel Sambuc return KnownHeader(KnownDir->second, NormalHeader);
192*0a6a1f1dSLionel Sambuc
193*0a6a1f1dSLionel Sambuc IntermediateDirs.push_back(Dir);
194*0a6a1f1dSLionel Sambuc
195*0a6a1f1dSLionel Sambuc // Retrieve our parent path.
196*0a6a1f1dSLionel Sambuc DirName = llvm::sys::path::parent_path(DirName);
197*0a6a1f1dSLionel Sambuc if (DirName.empty())
198*0a6a1f1dSLionel Sambuc break;
199*0a6a1f1dSLionel Sambuc
200*0a6a1f1dSLionel Sambuc // Resolve the parent path to a directory entry.
201*0a6a1f1dSLionel Sambuc Dir = SourceMgr.getFileManager().getDirectory(DirName);
202*0a6a1f1dSLionel Sambuc } while (Dir);
203*0a6a1f1dSLionel Sambuc return KnownHeader();
204*0a6a1f1dSLionel Sambuc }
205*0a6a1f1dSLionel Sambuc
206*0a6a1f1dSLionel Sambuc // Returns true if RequestingModule directly uses RequestedModule.
directlyUses(const Module * RequestingModule,const Module * RequestedModule)207*0a6a1f1dSLionel Sambuc static bool directlyUses(const Module *RequestingModule,
208*0a6a1f1dSLionel Sambuc const Module *RequestedModule) {
209*0a6a1f1dSLionel Sambuc return std::find(RequestingModule->DirectUses.begin(),
210*0a6a1f1dSLionel Sambuc RequestingModule->DirectUses.end(),
211*0a6a1f1dSLionel Sambuc RequestedModule) != RequestingModule->DirectUses.end();
212*0a6a1f1dSLionel Sambuc }
213*0a6a1f1dSLionel Sambuc
violatesPrivateInclude(Module * RequestingModule,const FileEntry * IncFileEnt,ModuleMap::ModuleHeaderRole Role,Module * RequestedModule)214*0a6a1f1dSLionel Sambuc static bool violatesPrivateInclude(Module *RequestingModule,
215*0a6a1f1dSLionel Sambuc const FileEntry *IncFileEnt,
216*0a6a1f1dSLionel Sambuc ModuleMap::ModuleHeaderRole Role,
217*0a6a1f1dSLionel Sambuc Module *RequestedModule) {
218*0a6a1f1dSLionel Sambuc bool IsPrivateRole = Role & ModuleMap::PrivateHeader;
219*0a6a1f1dSLionel Sambuc #ifndef NDEBUG
220*0a6a1f1dSLionel Sambuc // Check for consistency between the module header role
221*0a6a1f1dSLionel Sambuc // as obtained from the lookup and as obtained from the module.
222*0a6a1f1dSLionel Sambuc // This check is not cheap, so enable it only for debugging.
223*0a6a1f1dSLionel Sambuc bool IsPrivate = false;
224*0a6a1f1dSLionel Sambuc SmallVectorImpl<Module::Header> *HeaderList[] =
225*0a6a1f1dSLionel Sambuc {&RequestedModule->Headers[Module::HK_Private],
226*0a6a1f1dSLionel Sambuc &RequestedModule->Headers[Module::HK_PrivateTextual]};
227*0a6a1f1dSLionel Sambuc for (auto *Hdrs : HeaderList)
228*0a6a1f1dSLionel Sambuc IsPrivate |=
229*0a6a1f1dSLionel Sambuc std::find_if(Hdrs->begin(), Hdrs->end(), [&](const Module::Header &H) {
230*0a6a1f1dSLionel Sambuc return H.Entry == IncFileEnt;
231*0a6a1f1dSLionel Sambuc }) != Hdrs->end();
232*0a6a1f1dSLionel Sambuc assert(IsPrivate == IsPrivateRole && "inconsistent headers and roles");
233*0a6a1f1dSLionel Sambuc #endif
234*0a6a1f1dSLionel Sambuc return IsPrivateRole &&
235*0a6a1f1dSLionel Sambuc RequestedModule->getTopLevelModule() != RequestingModule;
236*0a6a1f1dSLionel Sambuc }
237*0a6a1f1dSLionel Sambuc
getTopLevelOrNull(Module * M)238*0a6a1f1dSLionel Sambuc static Module *getTopLevelOrNull(Module *M) {
239*0a6a1f1dSLionel Sambuc return M ? M->getTopLevelModule() : nullptr;
240*0a6a1f1dSLionel Sambuc }
241*0a6a1f1dSLionel Sambuc
diagnoseHeaderInclusion(Module * RequestingModule,SourceLocation FilenameLoc,StringRef Filename,const FileEntry * File)242*0a6a1f1dSLionel Sambuc void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
243*0a6a1f1dSLionel Sambuc SourceLocation FilenameLoc,
244*0a6a1f1dSLionel Sambuc StringRef Filename,
245*0a6a1f1dSLionel Sambuc const FileEntry *File) {
246*0a6a1f1dSLionel Sambuc // No errors for indirect modules. This may be a bit of a problem for modules
247*0a6a1f1dSLionel Sambuc // with no source files.
248*0a6a1f1dSLionel Sambuc if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
249*0a6a1f1dSLionel Sambuc return;
250*0a6a1f1dSLionel Sambuc
251*0a6a1f1dSLionel Sambuc if (RequestingModule)
252*0a6a1f1dSLionel Sambuc resolveUses(RequestingModule, /*Complain=*/false);
253*0a6a1f1dSLionel Sambuc
254*0a6a1f1dSLionel Sambuc bool Excluded = false;
255*0a6a1f1dSLionel Sambuc Module *Private = nullptr;
256*0a6a1f1dSLionel Sambuc Module *NotUsed = nullptr;
257*0a6a1f1dSLionel Sambuc
258*0a6a1f1dSLionel Sambuc HeadersMap::iterator Known = findKnownHeader(File);
259*0a6a1f1dSLionel Sambuc if (Known != Headers.end()) {
260*0a6a1f1dSLionel Sambuc for (const KnownHeader &Header : Known->second) {
261*0a6a1f1dSLionel Sambuc // If 'File' is part of 'RequestingModule' we can definitely include it.
262*0a6a1f1dSLionel Sambuc if (Header.getModule() == RequestingModule)
263*0a6a1f1dSLionel Sambuc return;
264*0a6a1f1dSLionel Sambuc
265*0a6a1f1dSLionel Sambuc // Remember private headers for later printing of a diagnostic.
266*0a6a1f1dSLionel Sambuc if (violatesPrivateInclude(RequestingModule, File, Header.getRole(),
267*0a6a1f1dSLionel Sambuc Header.getModule())) {
268*0a6a1f1dSLionel Sambuc Private = Header.getModule();
269*0a6a1f1dSLionel Sambuc continue;
270*0a6a1f1dSLionel Sambuc }
271*0a6a1f1dSLionel Sambuc
272*0a6a1f1dSLionel Sambuc // If uses need to be specified explicitly, we are only allowed to return
273*0a6a1f1dSLionel Sambuc // modules that are explicitly used by the requesting module.
274*0a6a1f1dSLionel Sambuc if (RequestingModule && LangOpts.ModulesDeclUse &&
275*0a6a1f1dSLionel Sambuc !directlyUses(RequestingModule, Header.getModule())) {
276*0a6a1f1dSLionel Sambuc NotUsed = Header.getModule();
277*0a6a1f1dSLionel Sambuc continue;
278*0a6a1f1dSLionel Sambuc }
279*0a6a1f1dSLionel Sambuc
280*0a6a1f1dSLionel Sambuc // We have found a module that we can happily use.
281*0a6a1f1dSLionel Sambuc return;
282*0a6a1f1dSLionel Sambuc }
283*0a6a1f1dSLionel Sambuc
284*0a6a1f1dSLionel Sambuc Excluded = true;
285*0a6a1f1dSLionel Sambuc }
286*0a6a1f1dSLionel Sambuc
287*0a6a1f1dSLionel Sambuc // We have found a header, but it is private.
288*0a6a1f1dSLionel Sambuc if (Private) {
289*0a6a1f1dSLionel Sambuc Diags.Report(FilenameLoc, diag::error_use_of_private_header_outside_module)
290*0a6a1f1dSLionel Sambuc << Filename;
291*0a6a1f1dSLionel Sambuc return;
292*0a6a1f1dSLionel Sambuc }
293*0a6a1f1dSLionel Sambuc
294*0a6a1f1dSLionel Sambuc // We have found a module, but we don't use it.
295*0a6a1f1dSLionel Sambuc if (NotUsed) {
296*0a6a1f1dSLionel Sambuc Diags.Report(FilenameLoc, diag::error_undeclared_use_of_module)
297*0a6a1f1dSLionel Sambuc << RequestingModule->getFullModuleName() << Filename;
298*0a6a1f1dSLionel Sambuc return;
299*0a6a1f1dSLionel Sambuc }
300*0a6a1f1dSLionel Sambuc
301*0a6a1f1dSLionel Sambuc if (Excluded || isHeaderInUmbrellaDirs(File))
302*0a6a1f1dSLionel Sambuc return;
303*0a6a1f1dSLionel Sambuc
304*0a6a1f1dSLionel Sambuc // At this point, only non-modular includes remain.
305*0a6a1f1dSLionel Sambuc
306*0a6a1f1dSLionel Sambuc if (LangOpts.ModulesStrictDeclUse) {
307*0a6a1f1dSLionel Sambuc Diags.Report(FilenameLoc, diag::error_undeclared_use_of_module)
308*0a6a1f1dSLionel Sambuc << RequestingModule->getFullModuleName() << Filename;
309*0a6a1f1dSLionel Sambuc } else if (RequestingModule) {
310*0a6a1f1dSLionel Sambuc diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
311*0a6a1f1dSLionel Sambuc diag::warn_non_modular_include_in_framework_module :
312*0a6a1f1dSLionel Sambuc diag::warn_non_modular_include_in_module;
313*0a6a1f1dSLionel Sambuc Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName();
314*0a6a1f1dSLionel Sambuc }
315*0a6a1f1dSLionel Sambuc }
316*0a6a1f1dSLionel Sambuc
317*0a6a1f1dSLionel Sambuc ModuleMap::KnownHeader
findModuleForHeader(const FileEntry * File,Module * RequestingModule,bool IncludeTextualHeaders)318*0a6a1f1dSLionel Sambuc ModuleMap::findModuleForHeader(const FileEntry *File,
319*0a6a1f1dSLionel Sambuc Module *RequestingModule,
320*0a6a1f1dSLionel Sambuc bool IncludeTextualHeaders) {
321*0a6a1f1dSLionel Sambuc HeadersMap::iterator Known = findKnownHeader(File);
322*0a6a1f1dSLionel Sambuc
323*0a6a1f1dSLionel Sambuc auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
324*0a6a1f1dSLionel Sambuc if (!IncludeTextualHeaders && (R.getRole() & ModuleMap::TextualHeader))
325*0a6a1f1dSLionel Sambuc return ModuleMap::KnownHeader();
326*0a6a1f1dSLionel Sambuc return R;
327*0a6a1f1dSLionel Sambuc };
328*0a6a1f1dSLionel Sambuc
329*0a6a1f1dSLionel Sambuc if (Known != Headers.end()) {
330*0a6a1f1dSLionel Sambuc ModuleMap::KnownHeader Result;
331*0a6a1f1dSLionel Sambuc
332*0a6a1f1dSLionel Sambuc // Iterate over all modules that 'File' is part of to find the best fit.
333*0a6a1f1dSLionel Sambuc for (SmallVectorImpl<KnownHeader>::iterator I = Known->second.begin(),
334*0a6a1f1dSLionel Sambuc E = Known->second.end();
335*0a6a1f1dSLionel Sambuc I != E; ++I) {
336*0a6a1f1dSLionel Sambuc // Cannot use a module if it is unavailable.
337*0a6a1f1dSLionel Sambuc if (!I->getModule()->isAvailable())
338*0a6a1f1dSLionel Sambuc continue;
339*0a6a1f1dSLionel Sambuc
340*0a6a1f1dSLionel Sambuc // If 'File' is part of 'RequestingModule', 'RequestingModule' is the
341*0a6a1f1dSLionel Sambuc // module we are looking for.
342*0a6a1f1dSLionel Sambuc if (I->getModule() == RequestingModule)
343*0a6a1f1dSLionel Sambuc return MakeResult(*I);
344*0a6a1f1dSLionel Sambuc
345*0a6a1f1dSLionel Sambuc // If uses need to be specified explicitly, we are only allowed to return
346*0a6a1f1dSLionel Sambuc // modules that are explicitly used by the requesting module.
347*0a6a1f1dSLionel Sambuc if (RequestingModule && LangOpts.ModulesDeclUse &&
348*0a6a1f1dSLionel Sambuc !directlyUses(RequestingModule, I->getModule()))
349*0a6a1f1dSLionel Sambuc continue;
350*0a6a1f1dSLionel Sambuc
351*0a6a1f1dSLionel Sambuc // Prefer a public header over a private header.
352*0a6a1f1dSLionel Sambuc if (!Result || (Result.getRole() & ModuleMap::PrivateHeader))
353*0a6a1f1dSLionel Sambuc Result = *I;
354*0a6a1f1dSLionel Sambuc }
355*0a6a1f1dSLionel Sambuc return MakeResult(Result);
356*0a6a1f1dSLionel Sambuc }
357*0a6a1f1dSLionel Sambuc
358*0a6a1f1dSLionel Sambuc SmallVector<const DirectoryEntry *, 2> SkippedDirs;
359*0a6a1f1dSLionel Sambuc KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
360*0a6a1f1dSLionel Sambuc if (H) {
361*0a6a1f1dSLionel Sambuc Module *Result = H.getModule();
362f4a2713aSLionel Sambuc
363f4a2713aSLionel Sambuc // Search up the module stack until we find a module with an umbrella
364f4a2713aSLionel Sambuc // directory.
365f4a2713aSLionel Sambuc Module *UmbrellaModule = Result;
366f4a2713aSLionel Sambuc while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
367f4a2713aSLionel Sambuc UmbrellaModule = UmbrellaModule->Parent;
368f4a2713aSLionel Sambuc
369f4a2713aSLionel Sambuc if (UmbrellaModule->InferSubmodules) {
370*0a6a1f1dSLionel Sambuc const FileEntry *UmbrellaModuleMap =
371*0a6a1f1dSLionel Sambuc getModuleMapFileForUniquing(UmbrellaModule);
372*0a6a1f1dSLionel Sambuc
373f4a2713aSLionel Sambuc // Infer submodules for each of the directories we found between
374f4a2713aSLionel Sambuc // the directory of the umbrella header and the directory where
375f4a2713aSLionel Sambuc // the actual header is located.
376f4a2713aSLionel Sambuc bool Explicit = UmbrellaModule->InferExplicitSubmodules;
377f4a2713aSLionel Sambuc
378f4a2713aSLionel Sambuc for (unsigned I = SkippedDirs.size(); I != 0; --I) {
379f4a2713aSLionel Sambuc // Find or create the module that corresponds to this directory name.
380f4a2713aSLionel Sambuc SmallString<32> NameBuf;
381f4a2713aSLionel Sambuc StringRef Name = sanitizeFilenameAsIdentifier(
382*0a6a1f1dSLionel Sambuc llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
383f4a2713aSLionel Sambuc Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
384f4a2713aSLionel Sambuc Explicit).first;
385*0a6a1f1dSLionel Sambuc InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
386*0a6a1f1dSLionel Sambuc Result->IsInferred = true;
387f4a2713aSLionel Sambuc
388f4a2713aSLionel Sambuc // Associate the module and the directory.
389f4a2713aSLionel Sambuc UmbrellaDirs[SkippedDirs[I-1]] = Result;
390f4a2713aSLionel Sambuc
391f4a2713aSLionel Sambuc // If inferred submodules export everything they import, add a
392f4a2713aSLionel Sambuc // wildcard to the set of exports.
393f4a2713aSLionel Sambuc if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
394*0a6a1f1dSLionel Sambuc Result->Exports.push_back(Module::ExportDecl(nullptr, true));
395f4a2713aSLionel Sambuc }
396f4a2713aSLionel Sambuc
397f4a2713aSLionel Sambuc // Infer a submodule with the same name as this header file.
398f4a2713aSLionel Sambuc SmallString<32> NameBuf;
399f4a2713aSLionel Sambuc StringRef Name = sanitizeFilenameAsIdentifier(
400f4a2713aSLionel Sambuc llvm::sys::path::stem(File->getName()), NameBuf);
401f4a2713aSLionel Sambuc Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
402f4a2713aSLionel Sambuc Explicit).first;
403*0a6a1f1dSLionel Sambuc InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
404*0a6a1f1dSLionel Sambuc Result->IsInferred = true;
405f4a2713aSLionel Sambuc Result->addTopHeader(File);
406f4a2713aSLionel Sambuc
407f4a2713aSLionel Sambuc // If inferred submodules export everything they import, add a
408f4a2713aSLionel Sambuc // wildcard to the set of exports.
409f4a2713aSLionel Sambuc if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
410*0a6a1f1dSLionel Sambuc Result->Exports.push_back(Module::ExportDecl(nullptr, true));
411f4a2713aSLionel Sambuc } else {
412f4a2713aSLionel Sambuc // Record each of the directories we stepped through as being part of
413f4a2713aSLionel Sambuc // the module we found, since the umbrella header covers them all.
414f4a2713aSLionel Sambuc for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
415f4a2713aSLionel Sambuc UmbrellaDirs[SkippedDirs[I]] = Result;
416f4a2713aSLionel Sambuc }
417f4a2713aSLionel Sambuc
418f4a2713aSLionel Sambuc Headers[File].push_back(KnownHeader(Result, NormalHeader));
419f4a2713aSLionel Sambuc
420f4a2713aSLionel Sambuc // If a header corresponds to an unavailable module, don't report
421f4a2713aSLionel Sambuc // that it maps to anything.
422f4a2713aSLionel Sambuc if (!Result->isAvailable())
423f4a2713aSLionel Sambuc return KnownHeader();
424f4a2713aSLionel Sambuc
425*0a6a1f1dSLionel Sambuc return MakeResult(Headers[File].back());
426f4a2713aSLionel Sambuc }
427f4a2713aSLionel Sambuc
428f4a2713aSLionel Sambuc return KnownHeader();
429f4a2713aSLionel Sambuc }
430f4a2713aSLionel Sambuc
isHeaderInUnavailableModule(const FileEntry * Header) const431f4a2713aSLionel Sambuc bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
432*0a6a1f1dSLionel Sambuc return isHeaderUnavailableInModule(Header, nullptr);
433*0a6a1f1dSLionel Sambuc }
434*0a6a1f1dSLionel Sambuc
435*0a6a1f1dSLionel Sambuc bool
isHeaderUnavailableInModule(const FileEntry * Header,const Module * RequestingModule) const436*0a6a1f1dSLionel Sambuc ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
437*0a6a1f1dSLionel Sambuc const Module *RequestingModule) const {
438f4a2713aSLionel Sambuc HeadersMap::const_iterator Known = Headers.find(Header);
439f4a2713aSLionel Sambuc if (Known != Headers.end()) {
440f4a2713aSLionel Sambuc for (SmallVectorImpl<KnownHeader>::const_iterator
441f4a2713aSLionel Sambuc I = Known->second.begin(),
442f4a2713aSLionel Sambuc E = Known->second.end();
443f4a2713aSLionel Sambuc I != E; ++I) {
444*0a6a1f1dSLionel Sambuc if (I->isAvailable() && (!RequestingModule ||
445*0a6a1f1dSLionel Sambuc I->getModule()->isSubModuleOf(RequestingModule)))
446f4a2713aSLionel Sambuc return false;
447f4a2713aSLionel Sambuc }
448f4a2713aSLionel Sambuc return true;
449f4a2713aSLionel Sambuc }
450f4a2713aSLionel Sambuc
451f4a2713aSLionel Sambuc const DirectoryEntry *Dir = Header->getDir();
452f4a2713aSLionel Sambuc SmallVector<const DirectoryEntry *, 2> SkippedDirs;
453f4a2713aSLionel Sambuc StringRef DirName = Dir->getName();
454f4a2713aSLionel Sambuc
455*0a6a1f1dSLionel Sambuc auto IsUnavailable = [&](const Module *M) {
456*0a6a1f1dSLionel Sambuc return !M->isAvailable() && (!RequestingModule ||
457*0a6a1f1dSLionel Sambuc M->isSubModuleOf(RequestingModule));
458*0a6a1f1dSLionel Sambuc };
459*0a6a1f1dSLionel Sambuc
460f4a2713aSLionel Sambuc // Keep walking up the directory hierarchy, looking for a directory with
461f4a2713aSLionel Sambuc // an umbrella header.
462f4a2713aSLionel Sambuc do {
463f4a2713aSLionel Sambuc llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
464f4a2713aSLionel Sambuc = UmbrellaDirs.find(Dir);
465f4a2713aSLionel Sambuc if (KnownDir != UmbrellaDirs.end()) {
466f4a2713aSLionel Sambuc Module *Found = KnownDir->second;
467*0a6a1f1dSLionel Sambuc if (IsUnavailable(Found))
468f4a2713aSLionel Sambuc return true;
469f4a2713aSLionel Sambuc
470f4a2713aSLionel Sambuc // Search up the module stack until we find a module with an umbrella
471f4a2713aSLionel Sambuc // directory.
472f4a2713aSLionel Sambuc Module *UmbrellaModule = Found;
473f4a2713aSLionel Sambuc while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
474f4a2713aSLionel Sambuc UmbrellaModule = UmbrellaModule->Parent;
475f4a2713aSLionel Sambuc
476f4a2713aSLionel Sambuc if (UmbrellaModule->InferSubmodules) {
477f4a2713aSLionel Sambuc for (unsigned I = SkippedDirs.size(); I != 0; --I) {
478f4a2713aSLionel Sambuc // Find or create the module that corresponds to this directory name.
479f4a2713aSLionel Sambuc SmallString<32> NameBuf;
480f4a2713aSLionel Sambuc StringRef Name = sanitizeFilenameAsIdentifier(
481f4a2713aSLionel Sambuc llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
482f4a2713aSLionel Sambuc NameBuf);
483f4a2713aSLionel Sambuc Found = lookupModuleQualified(Name, Found);
484f4a2713aSLionel Sambuc if (!Found)
485f4a2713aSLionel Sambuc return false;
486*0a6a1f1dSLionel Sambuc if (IsUnavailable(Found))
487f4a2713aSLionel Sambuc return true;
488f4a2713aSLionel Sambuc }
489f4a2713aSLionel Sambuc
490f4a2713aSLionel Sambuc // Infer a submodule with the same name as this header file.
491f4a2713aSLionel Sambuc SmallString<32> NameBuf;
492f4a2713aSLionel Sambuc StringRef Name = sanitizeFilenameAsIdentifier(
493f4a2713aSLionel Sambuc llvm::sys::path::stem(Header->getName()),
494f4a2713aSLionel Sambuc NameBuf);
495f4a2713aSLionel Sambuc Found = lookupModuleQualified(Name, Found);
496f4a2713aSLionel Sambuc if (!Found)
497f4a2713aSLionel Sambuc return false;
498f4a2713aSLionel Sambuc }
499f4a2713aSLionel Sambuc
500*0a6a1f1dSLionel Sambuc return IsUnavailable(Found);
501f4a2713aSLionel Sambuc }
502f4a2713aSLionel Sambuc
503f4a2713aSLionel Sambuc SkippedDirs.push_back(Dir);
504f4a2713aSLionel Sambuc
505f4a2713aSLionel Sambuc // Retrieve our parent path.
506f4a2713aSLionel Sambuc DirName = llvm::sys::path::parent_path(DirName);
507f4a2713aSLionel Sambuc if (DirName.empty())
508f4a2713aSLionel Sambuc break;
509f4a2713aSLionel Sambuc
510f4a2713aSLionel Sambuc // Resolve the parent path to a directory entry.
511f4a2713aSLionel Sambuc Dir = SourceMgr.getFileManager().getDirectory(DirName);
512f4a2713aSLionel Sambuc } while (Dir);
513f4a2713aSLionel Sambuc
514f4a2713aSLionel Sambuc return false;
515f4a2713aSLionel Sambuc }
516f4a2713aSLionel Sambuc
findModule(StringRef Name) const517f4a2713aSLionel Sambuc Module *ModuleMap::findModule(StringRef Name) const {
518f4a2713aSLionel Sambuc llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
519f4a2713aSLionel Sambuc if (Known != Modules.end())
520f4a2713aSLionel Sambuc return Known->getValue();
521f4a2713aSLionel Sambuc
522*0a6a1f1dSLionel Sambuc return nullptr;
523f4a2713aSLionel Sambuc }
524f4a2713aSLionel Sambuc
lookupModuleUnqualified(StringRef Name,Module * Context) const525f4a2713aSLionel Sambuc Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
526f4a2713aSLionel Sambuc Module *Context) const {
527f4a2713aSLionel Sambuc for(; Context; Context = Context->Parent) {
528f4a2713aSLionel Sambuc if (Module *Sub = lookupModuleQualified(Name, Context))
529f4a2713aSLionel Sambuc return Sub;
530f4a2713aSLionel Sambuc }
531f4a2713aSLionel Sambuc
532f4a2713aSLionel Sambuc return findModule(Name);
533f4a2713aSLionel Sambuc }
534f4a2713aSLionel Sambuc
lookupModuleQualified(StringRef Name,Module * Context) const535f4a2713aSLionel Sambuc Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
536f4a2713aSLionel Sambuc if (!Context)
537f4a2713aSLionel Sambuc return findModule(Name);
538f4a2713aSLionel Sambuc
539f4a2713aSLionel Sambuc return Context->findSubmodule(Name);
540f4a2713aSLionel Sambuc }
541f4a2713aSLionel Sambuc
542f4a2713aSLionel Sambuc std::pair<Module *, bool>
findOrCreateModule(StringRef Name,Module * Parent,bool IsFramework,bool IsExplicit)543f4a2713aSLionel Sambuc ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework,
544f4a2713aSLionel Sambuc bool IsExplicit) {
545f4a2713aSLionel Sambuc // Try to find an existing module with this name.
546f4a2713aSLionel Sambuc if (Module *Sub = lookupModuleQualified(Name, Parent))
547f4a2713aSLionel Sambuc return std::make_pair(Sub, false);
548f4a2713aSLionel Sambuc
549f4a2713aSLionel Sambuc // Create a new module with this name.
550*0a6a1f1dSLionel Sambuc Module *Result = new Module(Name, SourceLocation(), Parent,
551*0a6a1f1dSLionel Sambuc IsFramework, IsExplicit);
552f4a2713aSLionel Sambuc if (LangOpts.CurrentModule == Name) {
553f4a2713aSLionel Sambuc SourceModule = Result;
554f4a2713aSLionel Sambuc SourceModuleName = Name;
555f4a2713aSLionel Sambuc }
556f4a2713aSLionel Sambuc if (!Parent) {
557f4a2713aSLionel Sambuc Modules[Name] = Result;
558f4a2713aSLionel Sambuc if (!LangOpts.CurrentModule.empty() && !CompilingModule &&
559f4a2713aSLionel Sambuc Name == LangOpts.CurrentModule) {
560f4a2713aSLionel Sambuc CompilingModule = Result;
561f4a2713aSLionel Sambuc }
562f4a2713aSLionel Sambuc }
563f4a2713aSLionel Sambuc return std::make_pair(Result, true);
564f4a2713aSLionel Sambuc }
565f4a2713aSLionel Sambuc
566f4a2713aSLionel Sambuc /// \brief For a framework module, infer the framework against which we
567f4a2713aSLionel Sambuc /// should link.
inferFrameworkLink(Module * Mod,const DirectoryEntry * FrameworkDir,FileManager & FileMgr)568f4a2713aSLionel Sambuc static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
569f4a2713aSLionel Sambuc FileManager &FileMgr) {
570f4a2713aSLionel Sambuc assert(Mod->IsFramework && "Can only infer linking for framework modules");
571f4a2713aSLionel Sambuc assert(!Mod->isSubFramework() &&
572f4a2713aSLionel Sambuc "Can only infer linking for top-level frameworks");
573f4a2713aSLionel Sambuc
574f4a2713aSLionel Sambuc SmallString<128> LibName;
575f4a2713aSLionel Sambuc LibName += FrameworkDir->getName();
576f4a2713aSLionel Sambuc llvm::sys::path::append(LibName, Mod->Name);
577f4a2713aSLionel Sambuc if (FileMgr.getFile(LibName)) {
578f4a2713aSLionel Sambuc Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
579f4a2713aSLionel Sambuc /*IsFramework=*/true));
580f4a2713aSLionel Sambuc }
581f4a2713aSLionel Sambuc }
582f4a2713aSLionel Sambuc
583f4a2713aSLionel Sambuc Module *
inferFrameworkModule(StringRef ModuleName,const DirectoryEntry * FrameworkDir,bool IsSystem,Module * Parent)584f4a2713aSLionel Sambuc ModuleMap::inferFrameworkModule(StringRef ModuleName,
585f4a2713aSLionel Sambuc const DirectoryEntry *FrameworkDir,
586f4a2713aSLionel Sambuc bool IsSystem,
587f4a2713aSLionel Sambuc Module *Parent) {
588*0a6a1f1dSLionel Sambuc Attributes Attrs;
589*0a6a1f1dSLionel Sambuc Attrs.IsSystem = IsSystem;
590*0a6a1f1dSLionel Sambuc return inferFrameworkModule(ModuleName, FrameworkDir, Attrs, Parent);
591*0a6a1f1dSLionel Sambuc }
592*0a6a1f1dSLionel Sambuc
inferFrameworkModule(StringRef ModuleName,const DirectoryEntry * FrameworkDir,Attributes Attrs,Module * Parent)593*0a6a1f1dSLionel Sambuc Module *ModuleMap::inferFrameworkModule(StringRef ModuleName,
594*0a6a1f1dSLionel Sambuc const DirectoryEntry *FrameworkDir,
595*0a6a1f1dSLionel Sambuc Attributes Attrs, Module *Parent) {
596*0a6a1f1dSLionel Sambuc
597f4a2713aSLionel Sambuc // Check whether we've already found this module.
598f4a2713aSLionel Sambuc if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
599f4a2713aSLionel Sambuc return Mod;
600f4a2713aSLionel Sambuc
601f4a2713aSLionel Sambuc FileManager &FileMgr = SourceMgr.getFileManager();
602f4a2713aSLionel Sambuc
603f4a2713aSLionel Sambuc // If the framework has a parent path from which we're allowed to infer
604f4a2713aSLionel Sambuc // a framework module, do so.
605*0a6a1f1dSLionel Sambuc const FileEntry *ModuleMapFile = nullptr;
606f4a2713aSLionel Sambuc if (!Parent) {
607f4a2713aSLionel Sambuc // Determine whether we're allowed to infer a module map.
608f4a2713aSLionel Sambuc
609f4a2713aSLionel Sambuc // Note: as an egregious but useful hack we use the real path here, because
610f4a2713aSLionel Sambuc // we might be looking at an embedded framework that symlinks out to a
611f4a2713aSLionel Sambuc // top-level framework, and we need to infer as if we were naming the
612f4a2713aSLionel Sambuc // top-level framework.
613f4a2713aSLionel Sambuc StringRef FrameworkDirName
614f4a2713aSLionel Sambuc = SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
615f4a2713aSLionel Sambuc
616*0a6a1f1dSLionel Sambuc // In case this is a case-insensitive filesystem, make sure the canonical
617*0a6a1f1dSLionel Sambuc // directory name matches ModuleName exactly. Modules are case-sensitive.
618*0a6a1f1dSLionel Sambuc // FIXME: we should be able to give a fix-it hint for the correct spelling.
619*0a6a1f1dSLionel Sambuc if (llvm::sys::path::stem(FrameworkDirName) != ModuleName)
620*0a6a1f1dSLionel Sambuc return nullptr;
621*0a6a1f1dSLionel Sambuc
622f4a2713aSLionel Sambuc bool canInfer = false;
623f4a2713aSLionel Sambuc if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
624f4a2713aSLionel Sambuc // Figure out the parent path.
625f4a2713aSLionel Sambuc StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
626f4a2713aSLionel Sambuc if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) {
627f4a2713aSLionel Sambuc // Check whether we have already looked into the parent directory
628f4a2713aSLionel Sambuc // for a module map.
629f4a2713aSLionel Sambuc llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
630f4a2713aSLionel Sambuc inferred = InferredDirectories.find(ParentDir);
631f4a2713aSLionel Sambuc if (inferred == InferredDirectories.end()) {
632f4a2713aSLionel Sambuc // We haven't looked here before. Load a module map, if there is
633f4a2713aSLionel Sambuc // one.
634*0a6a1f1dSLionel Sambuc bool IsFrameworkDir = Parent.endswith(".framework");
635*0a6a1f1dSLionel Sambuc if (const FileEntry *ModMapFile =
636*0a6a1f1dSLionel Sambuc HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) {
637*0a6a1f1dSLionel Sambuc parseModuleMapFile(ModMapFile, Attrs.IsSystem, ParentDir);
638f4a2713aSLionel Sambuc inferred = InferredDirectories.find(ParentDir);
639f4a2713aSLionel Sambuc }
640f4a2713aSLionel Sambuc
641f4a2713aSLionel Sambuc if (inferred == InferredDirectories.end())
642f4a2713aSLionel Sambuc inferred = InferredDirectories.insert(
643f4a2713aSLionel Sambuc std::make_pair(ParentDir, InferredDirectory())).first;
644f4a2713aSLionel Sambuc }
645f4a2713aSLionel Sambuc
646f4a2713aSLionel Sambuc if (inferred->second.InferModules) {
647f4a2713aSLionel Sambuc // We're allowed to infer for this directory, but make sure it's okay
648f4a2713aSLionel Sambuc // to infer this particular module.
649f4a2713aSLionel Sambuc StringRef Name = llvm::sys::path::stem(FrameworkDirName);
650f4a2713aSLionel Sambuc canInfer = std::find(inferred->second.ExcludedModules.begin(),
651f4a2713aSLionel Sambuc inferred->second.ExcludedModules.end(),
652f4a2713aSLionel Sambuc Name) == inferred->second.ExcludedModules.end();
653f4a2713aSLionel Sambuc
654*0a6a1f1dSLionel Sambuc Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
655*0a6a1f1dSLionel Sambuc Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
656*0a6a1f1dSLionel Sambuc Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
657*0a6a1f1dSLionel Sambuc ModuleMapFile = inferred->second.ModuleMapFile;
658f4a2713aSLionel Sambuc }
659f4a2713aSLionel Sambuc }
660f4a2713aSLionel Sambuc }
661f4a2713aSLionel Sambuc
662f4a2713aSLionel Sambuc // If we're not allowed to infer a framework module, don't.
663f4a2713aSLionel Sambuc if (!canInfer)
664*0a6a1f1dSLionel Sambuc return nullptr;
665*0a6a1f1dSLionel Sambuc } else
666*0a6a1f1dSLionel Sambuc ModuleMapFile = getModuleMapFileForUniquing(Parent);
667f4a2713aSLionel Sambuc
668f4a2713aSLionel Sambuc
669f4a2713aSLionel Sambuc // Look for an umbrella header.
670f4a2713aSLionel Sambuc SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
671f4a2713aSLionel Sambuc llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
672f4a2713aSLionel Sambuc const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName);
673f4a2713aSLionel Sambuc
674f4a2713aSLionel Sambuc // FIXME: If there's no umbrella header, we could probably scan the
675f4a2713aSLionel Sambuc // framework to load *everything*. But, it's not clear that this is a good
676f4a2713aSLionel Sambuc // idea.
677f4a2713aSLionel Sambuc if (!UmbrellaHeader)
678*0a6a1f1dSLionel Sambuc return nullptr;
679f4a2713aSLionel Sambuc
680f4a2713aSLionel Sambuc Module *Result = new Module(ModuleName, SourceLocation(), Parent,
681f4a2713aSLionel Sambuc /*IsFramework=*/true, /*IsExplicit=*/false);
682*0a6a1f1dSLionel Sambuc InferredModuleAllowedBy[Result] = ModuleMapFile;
683*0a6a1f1dSLionel Sambuc Result->IsInferred = true;
684f4a2713aSLionel Sambuc if (LangOpts.CurrentModule == ModuleName) {
685f4a2713aSLionel Sambuc SourceModule = Result;
686f4a2713aSLionel Sambuc SourceModuleName = ModuleName;
687f4a2713aSLionel Sambuc }
688*0a6a1f1dSLionel Sambuc
689*0a6a1f1dSLionel Sambuc Result->IsSystem |= Attrs.IsSystem;
690*0a6a1f1dSLionel Sambuc Result->IsExternC |= Attrs.IsExternC;
691*0a6a1f1dSLionel Sambuc Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
692f4a2713aSLionel Sambuc
693f4a2713aSLionel Sambuc if (!Parent)
694f4a2713aSLionel Sambuc Modules[ModuleName] = Result;
695f4a2713aSLionel Sambuc
696f4a2713aSLionel Sambuc // umbrella header "umbrella-header-name"
697f4a2713aSLionel Sambuc Result->Umbrella = UmbrellaHeader;
698f4a2713aSLionel Sambuc Headers[UmbrellaHeader].push_back(KnownHeader(Result, NormalHeader));
699f4a2713aSLionel Sambuc UmbrellaDirs[UmbrellaHeader->getDir()] = Result;
700f4a2713aSLionel Sambuc
701f4a2713aSLionel Sambuc // export *
702*0a6a1f1dSLionel Sambuc Result->Exports.push_back(Module::ExportDecl(nullptr, true));
703f4a2713aSLionel Sambuc
704f4a2713aSLionel Sambuc // module * { export * }
705f4a2713aSLionel Sambuc Result->InferSubmodules = true;
706f4a2713aSLionel Sambuc Result->InferExportWildcard = true;
707f4a2713aSLionel Sambuc
708f4a2713aSLionel Sambuc // Look for subframeworks.
709*0a6a1f1dSLionel Sambuc std::error_code EC;
710f4a2713aSLionel Sambuc SmallString<128> SubframeworksDirName
711f4a2713aSLionel Sambuc = StringRef(FrameworkDir->getName());
712f4a2713aSLionel Sambuc llvm::sys::path::append(SubframeworksDirName, "Frameworks");
713f4a2713aSLionel Sambuc llvm::sys::path::native(SubframeworksDirName);
714f4a2713aSLionel Sambuc for (llvm::sys::fs::directory_iterator
715f4a2713aSLionel Sambuc Dir(SubframeworksDirName.str(), EC), DirEnd;
716f4a2713aSLionel Sambuc Dir != DirEnd && !EC; Dir.increment(EC)) {
717f4a2713aSLionel Sambuc if (!StringRef(Dir->path()).endswith(".framework"))
718f4a2713aSLionel Sambuc continue;
719f4a2713aSLionel Sambuc
720f4a2713aSLionel Sambuc if (const DirectoryEntry *SubframeworkDir
721f4a2713aSLionel Sambuc = FileMgr.getDirectory(Dir->path())) {
722f4a2713aSLionel Sambuc // Note: as an egregious but useful hack, we use the real path here and
723f4a2713aSLionel Sambuc // check whether it is actually a subdirectory of the parent directory.
724f4a2713aSLionel Sambuc // This will not be the case if the 'subframework' is actually a symlink
725f4a2713aSLionel Sambuc // out to a top-level framework.
726f4a2713aSLionel Sambuc StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir);
727f4a2713aSLionel Sambuc bool FoundParent = false;
728f4a2713aSLionel Sambuc do {
729f4a2713aSLionel Sambuc // Get the parent directory name.
730f4a2713aSLionel Sambuc SubframeworkDirName
731f4a2713aSLionel Sambuc = llvm::sys::path::parent_path(SubframeworkDirName);
732f4a2713aSLionel Sambuc if (SubframeworkDirName.empty())
733f4a2713aSLionel Sambuc break;
734f4a2713aSLionel Sambuc
735f4a2713aSLionel Sambuc if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) {
736f4a2713aSLionel Sambuc FoundParent = true;
737f4a2713aSLionel Sambuc break;
738f4a2713aSLionel Sambuc }
739f4a2713aSLionel Sambuc } while (true);
740f4a2713aSLionel Sambuc
741f4a2713aSLionel Sambuc if (!FoundParent)
742f4a2713aSLionel Sambuc continue;
743f4a2713aSLionel Sambuc
744f4a2713aSLionel Sambuc // FIXME: Do we want to warn about subframeworks without umbrella headers?
745f4a2713aSLionel Sambuc SmallString<32> NameBuf;
746f4a2713aSLionel Sambuc inferFrameworkModule(sanitizeFilenameAsIdentifier(
747f4a2713aSLionel Sambuc llvm::sys::path::stem(Dir->path()), NameBuf),
748*0a6a1f1dSLionel Sambuc SubframeworkDir, Attrs, Result);
749f4a2713aSLionel Sambuc }
750f4a2713aSLionel Sambuc }
751f4a2713aSLionel Sambuc
752f4a2713aSLionel Sambuc // If the module is a top-level framework, automatically link against the
753f4a2713aSLionel Sambuc // framework.
754f4a2713aSLionel Sambuc if (!Result->isSubFramework()) {
755f4a2713aSLionel Sambuc inferFrameworkLink(Result, FrameworkDir, FileMgr);
756f4a2713aSLionel Sambuc }
757f4a2713aSLionel Sambuc
758f4a2713aSLionel Sambuc return Result;
759f4a2713aSLionel Sambuc }
760f4a2713aSLionel Sambuc
setUmbrellaHeader(Module * Mod,const FileEntry * UmbrellaHeader)761f4a2713aSLionel Sambuc void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){
762f4a2713aSLionel Sambuc Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
763f4a2713aSLionel Sambuc Mod->Umbrella = UmbrellaHeader;
764f4a2713aSLionel Sambuc UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
765f4a2713aSLionel Sambuc }
766f4a2713aSLionel Sambuc
setUmbrellaDir(Module * Mod,const DirectoryEntry * UmbrellaDir)767f4a2713aSLionel Sambuc void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) {
768f4a2713aSLionel Sambuc Mod->Umbrella = UmbrellaDir;
769f4a2713aSLionel Sambuc UmbrellaDirs[UmbrellaDir] = Mod;
770f4a2713aSLionel Sambuc }
771f4a2713aSLionel Sambuc
headerRoleToKind(ModuleMap::ModuleHeaderRole Role)772*0a6a1f1dSLionel Sambuc static Module::HeaderKind headerRoleToKind(ModuleMap::ModuleHeaderRole Role) {
773*0a6a1f1dSLionel Sambuc switch ((int)Role) {
774*0a6a1f1dSLionel Sambuc default: llvm_unreachable("unknown header role");
775*0a6a1f1dSLionel Sambuc case ModuleMap::NormalHeader:
776*0a6a1f1dSLionel Sambuc return Module::HK_Normal;
777*0a6a1f1dSLionel Sambuc case ModuleMap::PrivateHeader:
778*0a6a1f1dSLionel Sambuc return Module::HK_Private;
779*0a6a1f1dSLionel Sambuc case ModuleMap::TextualHeader:
780*0a6a1f1dSLionel Sambuc return Module::HK_Textual;
781*0a6a1f1dSLionel Sambuc case ModuleMap::PrivateHeader | ModuleMap::TextualHeader:
782*0a6a1f1dSLionel Sambuc return Module::HK_PrivateTextual;
783f4a2713aSLionel Sambuc }
784*0a6a1f1dSLionel Sambuc }
785*0a6a1f1dSLionel Sambuc
addHeader(Module * Mod,Module::Header Header,ModuleHeaderRole Role)786*0a6a1f1dSLionel Sambuc void ModuleMap::addHeader(Module *Mod, Module::Header Header,
787*0a6a1f1dSLionel Sambuc ModuleHeaderRole Role) {
788*0a6a1f1dSLionel Sambuc if (!(Role & TextualHeader)) {
789*0a6a1f1dSLionel Sambuc bool isCompilingModuleHeader = Mod->getTopLevelModule() == CompilingModule;
790*0a6a1f1dSLionel Sambuc HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
791*0a6a1f1dSLionel Sambuc isCompilingModuleHeader);
792*0a6a1f1dSLionel Sambuc }
793*0a6a1f1dSLionel Sambuc Headers[Header.Entry].push_back(KnownHeader(Mod, Role));
794*0a6a1f1dSLionel Sambuc
795*0a6a1f1dSLionel Sambuc Mod->Headers[headerRoleToKind(Role)].push_back(std::move(Header));
796*0a6a1f1dSLionel Sambuc }
797*0a6a1f1dSLionel Sambuc
excludeHeader(Module * Mod,Module::Header Header)798*0a6a1f1dSLionel Sambuc void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
799*0a6a1f1dSLionel Sambuc // Add this as a known header so we won't implicitly add it to any
800*0a6a1f1dSLionel Sambuc // umbrella directory module.
801*0a6a1f1dSLionel Sambuc // FIXME: Should we only exclude it from umbrella modules within the
802*0a6a1f1dSLionel Sambuc // specified module?
803*0a6a1f1dSLionel Sambuc (void) Headers[Header.Entry];
804*0a6a1f1dSLionel Sambuc
805*0a6a1f1dSLionel Sambuc Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
806f4a2713aSLionel Sambuc }
807f4a2713aSLionel Sambuc
808f4a2713aSLionel Sambuc const FileEntry *
getContainingModuleMapFile(const Module * Module) const809*0a6a1f1dSLionel Sambuc ModuleMap::getContainingModuleMapFile(const Module *Module) const {
810f4a2713aSLionel Sambuc if (Module->DefinitionLoc.isInvalid())
811*0a6a1f1dSLionel Sambuc return nullptr;
812f4a2713aSLionel Sambuc
813f4a2713aSLionel Sambuc return SourceMgr.getFileEntryForID(
814f4a2713aSLionel Sambuc SourceMgr.getFileID(Module->DefinitionLoc));
815f4a2713aSLionel Sambuc }
816f4a2713aSLionel Sambuc
getModuleMapFileForUniquing(const Module * M) const817*0a6a1f1dSLionel Sambuc const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
818*0a6a1f1dSLionel Sambuc if (M->IsInferred) {
819*0a6a1f1dSLionel Sambuc assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
820*0a6a1f1dSLionel Sambuc return InferredModuleAllowedBy.find(M)->second;
821*0a6a1f1dSLionel Sambuc }
822*0a6a1f1dSLionel Sambuc return getContainingModuleMapFile(M);
823*0a6a1f1dSLionel Sambuc }
824*0a6a1f1dSLionel Sambuc
setInferredModuleAllowedBy(Module * M,const FileEntry * ModMap)825*0a6a1f1dSLionel Sambuc void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
826*0a6a1f1dSLionel Sambuc assert(M->IsInferred && "module not inferred");
827*0a6a1f1dSLionel Sambuc InferredModuleAllowedBy[M] = ModMap;
828*0a6a1f1dSLionel Sambuc }
829*0a6a1f1dSLionel Sambuc
dump()830f4a2713aSLionel Sambuc void ModuleMap::dump() {
831f4a2713aSLionel Sambuc llvm::errs() << "Modules:";
832f4a2713aSLionel Sambuc for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
833f4a2713aSLionel Sambuc MEnd = Modules.end();
834f4a2713aSLionel Sambuc M != MEnd; ++M)
835f4a2713aSLionel Sambuc M->getValue()->print(llvm::errs(), 2);
836f4a2713aSLionel Sambuc
837f4a2713aSLionel Sambuc llvm::errs() << "Headers:";
838f4a2713aSLionel Sambuc for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
839f4a2713aSLionel Sambuc H != HEnd; ++H) {
840f4a2713aSLionel Sambuc llvm::errs() << " \"" << H->first->getName() << "\" -> ";
841f4a2713aSLionel Sambuc for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
842f4a2713aSLionel Sambuc E = H->second.end();
843f4a2713aSLionel Sambuc I != E; ++I) {
844f4a2713aSLionel Sambuc if (I != H->second.begin())
845f4a2713aSLionel Sambuc llvm::errs() << ",";
846f4a2713aSLionel Sambuc llvm::errs() << I->getModule()->getFullModuleName();
847f4a2713aSLionel Sambuc }
848f4a2713aSLionel Sambuc llvm::errs() << "\n";
849f4a2713aSLionel Sambuc }
850f4a2713aSLionel Sambuc }
851f4a2713aSLionel Sambuc
resolveExports(Module * Mod,bool Complain)852f4a2713aSLionel Sambuc bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
853f4a2713aSLionel Sambuc bool HadError = false;
854f4a2713aSLionel Sambuc for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) {
855f4a2713aSLionel Sambuc Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I],
856f4a2713aSLionel Sambuc Complain);
857f4a2713aSLionel Sambuc if (Export.getPointer() || Export.getInt())
858f4a2713aSLionel Sambuc Mod->Exports.push_back(Export);
859f4a2713aSLionel Sambuc else
860f4a2713aSLionel Sambuc HadError = true;
861f4a2713aSLionel Sambuc }
862f4a2713aSLionel Sambuc Mod->UnresolvedExports.clear();
863f4a2713aSLionel Sambuc return HadError;
864f4a2713aSLionel Sambuc }
865f4a2713aSLionel Sambuc
resolveUses(Module * Mod,bool Complain)866f4a2713aSLionel Sambuc bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
867f4a2713aSLionel Sambuc bool HadError = false;
868f4a2713aSLionel Sambuc for (unsigned I = 0, N = Mod->UnresolvedDirectUses.size(); I != N; ++I) {
869f4a2713aSLionel Sambuc Module *DirectUse =
870f4a2713aSLionel Sambuc resolveModuleId(Mod->UnresolvedDirectUses[I], Mod, Complain);
871f4a2713aSLionel Sambuc if (DirectUse)
872f4a2713aSLionel Sambuc Mod->DirectUses.push_back(DirectUse);
873f4a2713aSLionel Sambuc else
874f4a2713aSLionel Sambuc HadError = true;
875f4a2713aSLionel Sambuc }
876f4a2713aSLionel Sambuc Mod->UnresolvedDirectUses.clear();
877f4a2713aSLionel Sambuc return HadError;
878f4a2713aSLionel Sambuc }
879f4a2713aSLionel Sambuc
resolveConflicts(Module * Mod,bool Complain)880f4a2713aSLionel Sambuc bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
881f4a2713aSLionel Sambuc bool HadError = false;
882f4a2713aSLionel Sambuc for (unsigned I = 0, N = Mod->UnresolvedConflicts.size(); I != N; ++I) {
883f4a2713aSLionel Sambuc Module *OtherMod = resolveModuleId(Mod->UnresolvedConflicts[I].Id,
884f4a2713aSLionel Sambuc Mod, Complain);
885f4a2713aSLionel Sambuc if (!OtherMod) {
886f4a2713aSLionel Sambuc HadError = true;
887f4a2713aSLionel Sambuc continue;
888f4a2713aSLionel Sambuc }
889f4a2713aSLionel Sambuc
890f4a2713aSLionel Sambuc Module::Conflict Conflict;
891f4a2713aSLionel Sambuc Conflict.Other = OtherMod;
892f4a2713aSLionel Sambuc Conflict.Message = Mod->UnresolvedConflicts[I].Message;
893f4a2713aSLionel Sambuc Mod->Conflicts.push_back(Conflict);
894f4a2713aSLionel Sambuc }
895f4a2713aSLionel Sambuc Mod->UnresolvedConflicts.clear();
896f4a2713aSLionel Sambuc return HadError;
897f4a2713aSLionel Sambuc }
898f4a2713aSLionel Sambuc
inferModuleFromLocation(FullSourceLoc Loc)899f4a2713aSLionel Sambuc Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) {
900f4a2713aSLionel Sambuc if (Loc.isInvalid())
901*0a6a1f1dSLionel Sambuc return nullptr;
902f4a2713aSLionel Sambuc
903f4a2713aSLionel Sambuc // Use the expansion location to determine which module we're in.
904f4a2713aSLionel Sambuc FullSourceLoc ExpansionLoc = Loc.getExpansionLoc();
905f4a2713aSLionel Sambuc if (!ExpansionLoc.isFileID())
906*0a6a1f1dSLionel Sambuc return nullptr;
907f4a2713aSLionel Sambuc
908f4a2713aSLionel Sambuc const SourceManager &SrcMgr = Loc.getManager();
909f4a2713aSLionel Sambuc FileID ExpansionFileID = ExpansionLoc.getFileID();
910f4a2713aSLionel Sambuc
911f4a2713aSLionel Sambuc while (const FileEntry *ExpansionFile
912f4a2713aSLionel Sambuc = SrcMgr.getFileEntryForID(ExpansionFileID)) {
913f4a2713aSLionel Sambuc // Find the module that owns this header (if any).
914f4a2713aSLionel Sambuc if (Module *Mod = findModuleForHeader(ExpansionFile).getModule())
915f4a2713aSLionel Sambuc return Mod;
916f4a2713aSLionel Sambuc
917f4a2713aSLionel Sambuc // No module owns this header, so look up the inclusion chain to see if
918f4a2713aSLionel Sambuc // any included header has an associated module.
919f4a2713aSLionel Sambuc SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID);
920f4a2713aSLionel Sambuc if (IncludeLoc.isInvalid())
921*0a6a1f1dSLionel Sambuc return nullptr;
922f4a2713aSLionel Sambuc
923f4a2713aSLionel Sambuc ExpansionFileID = SrcMgr.getFileID(IncludeLoc);
924f4a2713aSLionel Sambuc }
925f4a2713aSLionel Sambuc
926*0a6a1f1dSLionel Sambuc return nullptr;
927f4a2713aSLionel Sambuc }
928f4a2713aSLionel Sambuc
929f4a2713aSLionel Sambuc //----------------------------------------------------------------------------//
930f4a2713aSLionel Sambuc // Module map file parser
931f4a2713aSLionel Sambuc //----------------------------------------------------------------------------//
932f4a2713aSLionel Sambuc
933f4a2713aSLionel Sambuc namespace clang {
934f4a2713aSLionel Sambuc /// \brief A token in a module map file.
935f4a2713aSLionel Sambuc struct MMToken {
936f4a2713aSLionel Sambuc enum TokenKind {
937f4a2713aSLionel Sambuc Comma,
938f4a2713aSLionel Sambuc ConfigMacros,
939f4a2713aSLionel Sambuc Conflict,
940f4a2713aSLionel Sambuc EndOfFile,
941f4a2713aSLionel Sambuc HeaderKeyword,
942f4a2713aSLionel Sambuc Identifier,
943f4a2713aSLionel Sambuc Exclaim,
944f4a2713aSLionel Sambuc ExcludeKeyword,
945f4a2713aSLionel Sambuc ExplicitKeyword,
946f4a2713aSLionel Sambuc ExportKeyword,
947f4a2713aSLionel Sambuc ExternKeyword,
948f4a2713aSLionel Sambuc FrameworkKeyword,
949f4a2713aSLionel Sambuc LinkKeyword,
950f4a2713aSLionel Sambuc ModuleKeyword,
951f4a2713aSLionel Sambuc Period,
952f4a2713aSLionel Sambuc PrivateKeyword,
953f4a2713aSLionel Sambuc UmbrellaKeyword,
954f4a2713aSLionel Sambuc UseKeyword,
955f4a2713aSLionel Sambuc RequiresKeyword,
956f4a2713aSLionel Sambuc Star,
957f4a2713aSLionel Sambuc StringLiteral,
958*0a6a1f1dSLionel Sambuc TextualKeyword,
959f4a2713aSLionel Sambuc LBrace,
960f4a2713aSLionel Sambuc RBrace,
961f4a2713aSLionel Sambuc LSquare,
962f4a2713aSLionel Sambuc RSquare
963f4a2713aSLionel Sambuc } Kind;
964f4a2713aSLionel Sambuc
965f4a2713aSLionel Sambuc unsigned Location;
966f4a2713aSLionel Sambuc unsigned StringLength;
967f4a2713aSLionel Sambuc const char *StringData;
968f4a2713aSLionel Sambuc
clearclang::MMToken969f4a2713aSLionel Sambuc void clear() {
970f4a2713aSLionel Sambuc Kind = EndOfFile;
971f4a2713aSLionel Sambuc Location = 0;
972f4a2713aSLionel Sambuc StringLength = 0;
973*0a6a1f1dSLionel Sambuc StringData = nullptr;
974f4a2713aSLionel Sambuc }
975f4a2713aSLionel Sambuc
isclang::MMToken976f4a2713aSLionel Sambuc bool is(TokenKind K) const { return Kind == K; }
977f4a2713aSLionel Sambuc
getLocationclang::MMToken978f4a2713aSLionel Sambuc SourceLocation getLocation() const {
979f4a2713aSLionel Sambuc return SourceLocation::getFromRawEncoding(Location);
980f4a2713aSLionel Sambuc }
981f4a2713aSLionel Sambuc
getStringclang::MMToken982f4a2713aSLionel Sambuc StringRef getString() const {
983f4a2713aSLionel Sambuc return StringRef(StringData, StringLength);
984f4a2713aSLionel Sambuc }
985f4a2713aSLionel Sambuc };
986f4a2713aSLionel Sambuc
987f4a2713aSLionel Sambuc class ModuleMapParser {
988f4a2713aSLionel Sambuc Lexer &L;
989f4a2713aSLionel Sambuc SourceManager &SourceMgr;
990f4a2713aSLionel Sambuc
991f4a2713aSLionel Sambuc /// \brief Default target information, used only for string literal
992f4a2713aSLionel Sambuc /// parsing.
993f4a2713aSLionel Sambuc const TargetInfo *Target;
994f4a2713aSLionel Sambuc
995f4a2713aSLionel Sambuc DiagnosticsEngine &Diags;
996f4a2713aSLionel Sambuc ModuleMap ⤅
997f4a2713aSLionel Sambuc
998*0a6a1f1dSLionel Sambuc /// \brief The current module map file.
999*0a6a1f1dSLionel Sambuc const FileEntry *ModuleMapFile;
1000*0a6a1f1dSLionel Sambuc
1001*0a6a1f1dSLionel Sambuc /// \brief The directory that file names in this module map file should
1002*0a6a1f1dSLionel Sambuc /// be resolved relative to.
1003f4a2713aSLionel Sambuc const DirectoryEntry *Directory;
1004f4a2713aSLionel Sambuc
1005f4a2713aSLionel Sambuc /// \brief The directory containing Clang-supplied headers.
1006f4a2713aSLionel Sambuc const DirectoryEntry *BuiltinIncludeDir;
1007f4a2713aSLionel Sambuc
1008f4a2713aSLionel Sambuc /// \brief Whether this module map is in a system header directory.
1009f4a2713aSLionel Sambuc bool IsSystem;
1010f4a2713aSLionel Sambuc
1011f4a2713aSLionel Sambuc /// \brief Whether an error occurred.
1012f4a2713aSLionel Sambuc bool HadError;
1013f4a2713aSLionel Sambuc
1014f4a2713aSLionel Sambuc /// \brief Stores string data for the various string literals referenced
1015f4a2713aSLionel Sambuc /// during parsing.
1016f4a2713aSLionel Sambuc llvm::BumpPtrAllocator StringData;
1017f4a2713aSLionel Sambuc
1018f4a2713aSLionel Sambuc /// \brief The current token.
1019f4a2713aSLionel Sambuc MMToken Tok;
1020f4a2713aSLionel Sambuc
1021f4a2713aSLionel Sambuc /// \brief The active module.
1022f4a2713aSLionel Sambuc Module *ActiveModule;
1023f4a2713aSLionel Sambuc
1024f4a2713aSLionel Sambuc /// \brief Consume the current token and return its location.
1025f4a2713aSLionel Sambuc SourceLocation consumeToken();
1026f4a2713aSLionel Sambuc
1027f4a2713aSLionel Sambuc /// \brief Skip tokens until we reach the a token with the given kind
1028f4a2713aSLionel Sambuc /// (or the end of the file).
1029f4a2713aSLionel Sambuc void skipUntil(MMToken::TokenKind K);
1030f4a2713aSLionel Sambuc
1031f4a2713aSLionel Sambuc typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId;
1032f4a2713aSLionel Sambuc bool parseModuleId(ModuleId &Id);
1033f4a2713aSLionel Sambuc void parseModuleDecl();
1034f4a2713aSLionel Sambuc void parseExternModuleDecl();
1035f4a2713aSLionel Sambuc void parseRequiresDecl();
1036f4a2713aSLionel Sambuc void parseHeaderDecl(clang::MMToken::TokenKind,
1037f4a2713aSLionel Sambuc SourceLocation LeadingLoc);
1038f4a2713aSLionel Sambuc void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
1039f4a2713aSLionel Sambuc void parseExportDecl();
1040f4a2713aSLionel Sambuc void parseUseDecl();
1041f4a2713aSLionel Sambuc void parseLinkDecl();
1042f4a2713aSLionel Sambuc void parseConfigMacros();
1043f4a2713aSLionel Sambuc void parseConflict();
1044f4a2713aSLionel Sambuc void parseInferredModuleDecl(bool Framework, bool Explicit);
1045f4a2713aSLionel Sambuc
1046*0a6a1f1dSLionel Sambuc typedef ModuleMap::Attributes Attributes;
1047*0a6a1f1dSLionel Sambuc bool parseOptionalAttributes(Attributes &Attrs);
1048f4a2713aSLionel Sambuc
1049f4a2713aSLionel Sambuc public:
ModuleMapParser(Lexer & L,SourceManager & SourceMgr,const TargetInfo * Target,DiagnosticsEngine & Diags,ModuleMap & Map,const FileEntry * ModuleMapFile,const DirectoryEntry * Directory,const DirectoryEntry * BuiltinIncludeDir,bool IsSystem)1050f4a2713aSLionel Sambuc explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
1051f4a2713aSLionel Sambuc const TargetInfo *Target,
1052f4a2713aSLionel Sambuc DiagnosticsEngine &Diags,
1053f4a2713aSLionel Sambuc ModuleMap &Map,
1054*0a6a1f1dSLionel Sambuc const FileEntry *ModuleMapFile,
1055f4a2713aSLionel Sambuc const DirectoryEntry *Directory,
1056f4a2713aSLionel Sambuc const DirectoryEntry *BuiltinIncludeDir,
1057f4a2713aSLionel Sambuc bool IsSystem)
1058f4a2713aSLionel Sambuc : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
1059*0a6a1f1dSLionel Sambuc ModuleMapFile(ModuleMapFile), Directory(Directory),
1060*0a6a1f1dSLionel Sambuc BuiltinIncludeDir(BuiltinIncludeDir), IsSystem(IsSystem),
1061*0a6a1f1dSLionel Sambuc HadError(false), ActiveModule(nullptr)
1062f4a2713aSLionel Sambuc {
1063f4a2713aSLionel Sambuc Tok.clear();
1064f4a2713aSLionel Sambuc consumeToken();
1065f4a2713aSLionel Sambuc }
1066f4a2713aSLionel Sambuc
1067f4a2713aSLionel Sambuc bool parseModuleMapFile();
1068f4a2713aSLionel Sambuc };
1069f4a2713aSLionel Sambuc }
1070f4a2713aSLionel Sambuc
consumeToken()1071f4a2713aSLionel Sambuc SourceLocation ModuleMapParser::consumeToken() {
1072f4a2713aSLionel Sambuc retry:
1073f4a2713aSLionel Sambuc SourceLocation Result = Tok.getLocation();
1074f4a2713aSLionel Sambuc Tok.clear();
1075f4a2713aSLionel Sambuc
1076f4a2713aSLionel Sambuc Token LToken;
1077f4a2713aSLionel Sambuc L.LexFromRawLexer(LToken);
1078f4a2713aSLionel Sambuc Tok.Location = LToken.getLocation().getRawEncoding();
1079f4a2713aSLionel Sambuc switch (LToken.getKind()) {
1080*0a6a1f1dSLionel Sambuc case tok::raw_identifier: {
1081*0a6a1f1dSLionel Sambuc StringRef RI = LToken.getRawIdentifier();
1082*0a6a1f1dSLionel Sambuc Tok.StringData = RI.data();
1083*0a6a1f1dSLionel Sambuc Tok.StringLength = RI.size();
1084*0a6a1f1dSLionel Sambuc Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
1085f4a2713aSLionel Sambuc .Case("config_macros", MMToken::ConfigMacros)
1086f4a2713aSLionel Sambuc .Case("conflict", MMToken::Conflict)
1087f4a2713aSLionel Sambuc .Case("exclude", MMToken::ExcludeKeyword)
1088f4a2713aSLionel Sambuc .Case("explicit", MMToken::ExplicitKeyword)
1089f4a2713aSLionel Sambuc .Case("export", MMToken::ExportKeyword)
1090f4a2713aSLionel Sambuc .Case("extern", MMToken::ExternKeyword)
1091f4a2713aSLionel Sambuc .Case("framework", MMToken::FrameworkKeyword)
1092f4a2713aSLionel Sambuc .Case("header", MMToken::HeaderKeyword)
1093f4a2713aSLionel Sambuc .Case("link", MMToken::LinkKeyword)
1094f4a2713aSLionel Sambuc .Case("module", MMToken::ModuleKeyword)
1095f4a2713aSLionel Sambuc .Case("private", MMToken::PrivateKeyword)
1096f4a2713aSLionel Sambuc .Case("requires", MMToken::RequiresKeyword)
1097*0a6a1f1dSLionel Sambuc .Case("textual", MMToken::TextualKeyword)
1098f4a2713aSLionel Sambuc .Case("umbrella", MMToken::UmbrellaKeyword)
1099f4a2713aSLionel Sambuc .Case("use", MMToken::UseKeyword)
1100f4a2713aSLionel Sambuc .Default(MMToken::Identifier);
1101f4a2713aSLionel Sambuc break;
1102*0a6a1f1dSLionel Sambuc }
1103f4a2713aSLionel Sambuc
1104f4a2713aSLionel Sambuc case tok::comma:
1105f4a2713aSLionel Sambuc Tok.Kind = MMToken::Comma;
1106f4a2713aSLionel Sambuc break;
1107f4a2713aSLionel Sambuc
1108f4a2713aSLionel Sambuc case tok::eof:
1109f4a2713aSLionel Sambuc Tok.Kind = MMToken::EndOfFile;
1110f4a2713aSLionel Sambuc break;
1111f4a2713aSLionel Sambuc
1112f4a2713aSLionel Sambuc case tok::l_brace:
1113f4a2713aSLionel Sambuc Tok.Kind = MMToken::LBrace;
1114f4a2713aSLionel Sambuc break;
1115f4a2713aSLionel Sambuc
1116f4a2713aSLionel Sambuc case tok::l_square:
1117f4a2713aSLionel Sambuc Tok.Kind = MMToken::LSquare;
1118f4a2713aSLionel Sambuc break;
1119f4a2713aSLionel Sambuc
1120f4a2713aSLionel Sambuc case tok::period:
1121f4a2713aSLionel Sambuc Tok.Kind = MMToken::Period;
1122f4a2713aSLionel Sambuc break;
1123f4a2713aSLionel Sambuc
1124f4a2713aSLionel Sambuc case tok::r_brace:
1125f4a2713aSLionel Sambuc Tok.Kind = MMToken::RBrace;
1126f4a2713aSLionel Sambuc break;
1127f4a2713aSLionel Sambuc
1128f4a2713aSLionel Sambuc case tok::r_square:
1129f4a2713aSLionel Sambuc Tok.Kind = MMToken::RSquare;
1130f4a2713aSLionel Sambuc break;
1131f4a2713aSLionel Sambuc
1132f4a2713aSLionel Sambuc case tok::star:
1133f4a2713aSLionel Sambuc Tok.Kind = MMToken::Star;
1134f4a2713aSLionel Sambuc break;
1135f4a2713aSLionel Sambuc
1136f4a2713aSLionel Sambuc case tok::exclaim:
1137f4a2713aSLionel Sambuc Tok.Kind = MMToken::Exclaim;
1138f4a2713aSLionel Sambuc break;
1139f4a2713aSLionel Sambuc
1140f4a2713aSLionel Sambuc case tok::string_literal: {
1141f4a2713aSLionel Sambuc if (LToken.hasUDSuffix()) {
1142f4a2713aSLionel Sambuc Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
1143f4a2713aSLionel Sambuc HadError = true;
1144f4a2713aSLionel Sambuc goto retry;
1145f4a2713aSLionel Sambuc }
1146f4a2713aSLionel Sambuc
1147f4a2713aSLionel Sambuc // Parse the string literal.
1148f4a2713aSLionel Sambuc LangOptions LangOpts;
1149*0a6a1f1dSLionel Sambuc StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
1150f4a2713aSLionel Sambuc if (StringLiteral.hadError)
1151f4a2713aSLionel Sambuc goto retry;
1152f4a2713aSLionel Sambuc
1153f4a2713aSLionel Sambuc // Copy the string literal into our string data allocator.
1154f4a2713aSLionel Sambuc unsigned Length = StringLiteral.GetStringLength();
1155f4a2713aSLionel Sambuc char *Saved = StringData.Allocate<char>(Length + 1);
1156f4a2713aSLionel Sambuc memcpy(Saved, StringLiteral.GetString().data(), Length);
1157f4a2713aSLionel Sambuc Saved[Length] = 0;
1158f4a2713aSLionel Sambuc
1159f4a2713aSLionel Sambuc // Form the token.
1160f4a2713aSLionel Sambuc Tok.Kind = MMToken::StringLiteral;
1161f4a2713aSLionel Sambuc Tok.StringData = Saved;
1162f4a2713aSLionel Sambuc Tok.StringLength = Length;
1163f4a2713aSLionel Sambuc break;
1164f4a2713aSLionel Sambuc }
1165f4a2713aSLionel Sambuc
1166f4a2713aSLionel Sambuc case tok::comment:
1167f4a2713aSLionel Sambuc goto retry;
1168f4a2713aSLionel Sambuc
1169f4a2713aSLionel Sambuc default:
1170f4a2713aSLionel Sambuc Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token);
1171f4a2713aSLionel Sambuc HadError = true;
1172f4a2713aSLionel Sambuc goto retry;
1173f4a2713aSLionel Sambuc }
1174f4a2713aSLionel Sambuc
1175f4a2713aSLionel Sambuc return Result;
1176f4a2713aSLionel Sambuc }
1177f4a2713aSLionel Sambuc
skipUntil(MMToken::TokenKind K)1178f4a2713aSLionel Sambuc void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
1179f4a2713aSLionel Sambuc unsigned braceDepth = 0;
1180f4a2713aSLionel Sambuc unsigned squareDepth = 0;
1181f4a2713aSLionel Sambuc do {
1182f4a2713aSLionel Sambuc switch (Tok.Kind) {
1183f4a2713aSLionel Sambuc case MMToken::EndOfFile:
1184f4a2713aSLionel Sambuc return;
1185f4a2713aSLionel Sambuc
1186f4a2713aSLionel Sambuc case MMToken::LBrace:
1187f4a2713aSLionel Sambuc if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1188f4a2713aSLionel Sambuc return;
1189f4a2713aSLionel Sambuc
1190f4a2713aSLionel Sambuc ++braceDepth;
1191f4a2713aSLionel Sambuc break;
1192f4a2713aSLionel Sambuc
1193f4a2713aSLionel Sambuc case MMToken::LSquare:
1194f4a2713aSLionel Sambuc if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
1195f4a2713aSLionel Sambuc return;
1196f4a2713aSLionel Sambuc
1197f4a2713aSLionel Sambuc ++squareDepth;
1198f4a2713aSLionel Sambuc break;
1199f4a2713aSLionel Sambuc
1200f4a2713aSLionel Sambuc case MMToken::RBrace:
1201f4a2713aSLionel Sambuc if (braceDepth > 0)
1202f4a2713aSLionel Sambuc --braceDepth;
1203f4a2713aSLionel Sambuc else if (Tok.is(K))
1204f4a2713aSLionel Sambuc return;
1205f4a2713aSLionel Sambuc break;
1206f4a2713aSLionel Sambuc
1207f4a2713aSLionel Sambuc case MMToken::RSquare:
1208f4a2713aSLionel Sambuc if (squareDepth > 0)
1209f4a2713aSLionel Sambuc --squareDepth;
1210f4a2713aSLionel Sambuc else if (Tok.is(K))
1211f4a2713aSLionel Sambuc return;
1212f4a2713aSLionel Sambuc break;
1213f4a2713aSLionel Sambuc
1214f4a2713aSLionel Sambuc default:
1215f4a2713aSLionel Sambuc if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
1216f4a2713aSLionel Sambuc return;
1217f4a2713aSLionel Sambuc break;
1218f4a2713aSLionel Sambuc }
1219f4a2713aSLionel Sambuc
1220f4a2713aSLionel Sambuc consumeToken();
1221f4a2713aSLionel Sambuc } while (true);
1222f4a2713aSLionel Sambuc }
1223f4a2713aSLionel Sambuc
1224f4a2713aSLionel Sambuc /// \brief Parse a module-id.
1225f4a2713aSLionel Sambuc ///
1226f4a2713aSLionel Sambuc /// module-id:
1227f4a2713aSLionel Sambuc /// identifier
1228f4a2713aSLionel Sambuc /// identifier '.' module-id
1229f4a2713aSLionel Sambuc ///
1230f4a2713aSLionel Sambuc /// \returns true if an error occurred, false otherwise.
parseModuleId(ModuleId & Id)1231f4a2713aSLionel Sambuc bool ModuleMapParser::parseModuleId(ModuleId &Id) {
1232f4a2713aSLionel Sambuc Id.clear();
1233f4a2713aSLionel Sambuc do {
1234*0a6a1f1dSLionel Sambuc if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
1235f4a2713aSLionel Sambuc Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation()));
1236f4a2713aSLionel Sambuc consumeToken();
1237f4a2713aSLionel Sambuc } else {
1238f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
1239f4a2713aSLionel Sambuc return true;
1240f4a2713aSLionel Sambuc }
1241f4a2713aSLionel Sambuc
1242f4a2713aSLionel Sambuc if (!Tok.is(MMToken::Period))
1243f4a2713aSLionel Sambuc break;
1244f4a2713aSLionel Sambuc
1245f4a2713aSLionel Sambuc consumeToken();
1246f4a2713aSLionel Sambuc } while (true);
1247f4a2713aSLionel Sambuc
1248f4a2713aSLionel Sambuc return false;
1249f4a2713aSLionel Sambuc }
1250f4a2713aSLionel Sambuc
1251f4a2713aSLionel Sambuc namespace {
1252f4a2713aSLionel Sambuc /// \brief Enumerates the known attributes.
1253f4a2713aSLionel Sambuc enum AttributeKind {
1254f4a2713aSLionel Sambuc /// \brief An unknown attribute.
1255f4a2713aSLionel Sambuc AT_unknown,
1256f4a2713aSLionel Sambuc /// \brief The 'system' attribute.
1257f4a2713aSLionel Sambuc AT_system,
1258*0a6a1f1dSLionel Sambuc /// \brief The 'extern_c' attribute.
1259*0a6a1f1dSLionel Sambuc AT_extern_c,
1260f4a2713aSLionel Sambuc /// \brief The 'exhaustive' attribute.
1261f4a2713aSLionel Sambuc AT_exhaustive
1262f4a2713aSLionel Sambuc };
1263f4a2713aSLionel Sambuc }
1264f4a2713aSLionel Sambuc
1265f4a2713aSLionel Sambuc /// \brief Parse a module declaration.
1266f4a2713aSLionel Sambuc ///
1267f4a2713aSLionel Sambuc /// module-declaration:
1268f4a2713aSLionel Sambuc /// 'extern' 'module' module-id string-literal
1269f4a2713aSLionel Sambuc /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
1270f4a2713aSLionel Sambuc /// { module-member* }
1271f4a2713aSLionel Sambuc ///
1272f4a2713aSLionel Sambuc /// module-member:
1273f4a2713aSLionel Sambuc /// requires-declaration
1274f4a2713aSLionel Sambuc /// header-declaration
1275f4a2713aSLionel Sambuc /// submodule-declaration
1276f4a2713aSLionel Sambuc /// export-declaration
1277f4a2713aSLionel Sambuc /// link-declaration
1278f4a2713aSLionel Sambuc ///
1279f4a2713aSLionel Sambuc /// submodule-declaration:
1280f4a2713aSLionel Sambuc /// module-declaration
1281f4a2713aSLionel Sambuc /// inferred-submodule-declaration
parseModuleDecl()1282f4a2713aSLionel Sambuc void ModuleMapParser::parseModuleDecl() {
1283f4a2713aSLionel Sambuc assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
1284f4a2713aSLionel Sambuc Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
1285f4a2713aSLionel Sambuc if (Tok.is(MMToken::ExternKeyword)) {
1286f4a2713aSLionel Sambuc parseExternModuleDecl();
1287f4a2713aSLionel Sambuc return;
1288f4a2713aSLionel Sambuc }
1289f4a2713aSLionel Sambuc
1290f4a2713aSLionel Sambuc // Parse 'explicit' or 'framework' keyword, if present.
1291f4a2713aSLionel Sambuc SourceLocation ExplicitLoc;
1292f4a2713aSLionel Sambuc bool Explicit = false;
1293f4a2713aSLionel Sambuc bool Framework = false;
1294f4a2713aSLionel Sambuc
1295f4a2713aSLionel Sambuc // Parse 'explicit' keyword, if present.
1296f4a2713aSLionel Sambuc if (Tok.is(MMToken::ExplicitKeyword)) {
1297f4a2713aSLionel Sambuc ExplicitLoc = consumeToken();
1298f4a2713aSLionel Sambuc Explicit = true;
1299f4a2713aSLionel Sambuc }
1300f4a2713aSLionel Sambuc
1301f4a2713aSLionel Sambuc // Parse 'framework' keyword, if present.
1302f4a2713aSLionel Sambuc if (Tok.is(MMToken::FrameworkKeyword)) {
1303f4a2713aSLionel Sambuc consumeToken();
1304f4a2713aSLionel Sambuc Framework = true;
1305f4a2713aSLionel Sambuc }
1306f4a2713aSLionel Sambuc
1307f4a2713aSLionel Sambuc // Parse 'module' keyword.
1308f4a2713aSLionel Sambuc if (!Tok.is(MMToken::ModuleKeyword)) {
1309f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1310f4a2713aSLionel Sambuc consumeToken();
1311f4a2713aSLionel Sambuc HadError = true;
1312f4a2713aSLionel Sambuc return;
1313f4a2713aSLionel Sambuc }
1314f4a2713aSLionel Sambuc consumeToken(); // 'module' keyword
1315f4a2713aSLionel Sambuc
1316f4a2713aSLionel Sambuc // If we have a wildcard for the module name, this is an inferred submodule.
1317f4a2713aSLionel Sambuc // Parse it.
1318f4a2713aSLionel Sambuc if (Tok.is(MMToken::Star))
1319f4a2713aSLionel Sambuc return parseInferredModuleDecl(Framework, Explicit);
1320f4a2713aSLionel Sambuc
1321f4a2713aSLionel Sambuc // Parse the module name.
1322f4a2713aSLionel Sambuc ModuleId Id;
1323f4a2713aSLionel Sambuc if (parseModuleId(Id)) {
1324f4a2713aSLionel Sambuc HadError = true;
1325f4a2713aSLionel Sambuc return;
1326f4a2713aSLionel Sambuc }
1327f4a2713aSLionel Sambuc
1328f4a2713aSLionel Sambuc if (ActiveModule) {
1329f4a2713aSLionel Sambuc if (Id.size() > 1) {
1330f4a2713aSLionel Sambuc Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
1331f4a2713aSLionel Sambuc << SourceRange(Id.front().second, Id.back().second);
1332f4a2713aSLionel Sambuc
1333f4a2713aSLionel Sambuc HadError = true;
1334f4a2713aSLionel Sambuc return;
1335f4a2713aSLionel Sambuc }
1336f4a2713aSLionel Sambuc } else if (Id.size() == 1 && Explicit) {
1337f4a2713aSLionel Sambuc // Top-level modules can't be explicit.
1338f4a2713aSLionel Sambuc Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
1339f4a2713aSLionel Sambuc Explicit = false;
1340f4a2713aSLionel Sambuc ExplicitLoc = SourceLocation();
1341f4a2713aSLionel Sambuc HadError = true;
1342f4a2713aSLionel Sambuc }
1343f4a2713aSLionel Sambuc
1344f4a2713aSLionel Sambuc Module *PreviousActiveModule = ActiveModule;
1345f4a2713aSLionel Sambuc if (Id.size() > 1) {
1346f4a2713aSLionel Sambuc // This module map defines a submodule. Go find the module of which it
1347f4a2713aSLionel Sambuc // is a submodule.
1348*0a6a1f1dSLionel Sambuc ActiveModule = nullptr;
1349*0a6a1f1dSLionel Sambuc const Module *TopLevelModule = nullptr;
1350f4a2713aSLionel Sambuc for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
1351f4a2713aSLionel Sambuc if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
1352*0a6a1f1dSLionel Sambuc if (I == 0)
1353*0a6a1f1dSLionel Sambuc TopLevelModule = Next;
1354f4a2713aSLionel Sambuc ActiveModule = Next;
1355f4a2713aSLionel Sambuc continue;
1356f4a2713aSLionel Sambuc }
1357f4a2713aSLionel Sambuc
1358f4a2713aSLionel Sambuc if (ActiveModule) {
1359f4a2713aSLionel Sambuc Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
1360*0a6a1f1dSLionel Sambuc << Id[I].first
1361*0a6a1f1dSLionel Sambuc << ActiveModule->getTopLevelModule()->getFullModuleName();
1362f4a2713aSLionel Sambuc } else {
1363f4a2713aSLionel Sambuc Diags.Report(Id[I].second, diag::err_mmap_expected_module_name);
1364f4a2713aSLionel Sambuc }
1365f4a2713aSLionel Sambuc HadError = true;
1366f4a2713aSLionel Sambuc return;
1367f4a2713aSLionel Sambuc }
1368*0a6a1f1dSLionel Sambuc
1369*0a6a1f1dSLionel Sambuc if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
1370*0a6a1f1dSLionel Sambuc assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
1371*0a6a1f1dSLionel Sambuc "submodule defined in same file as 'module *' that allowed its "
1372*0a6a1f1dSLionel Sambuc "top-level module");
1373*0a6a1f1dSLionel Sambuc Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
1374*0a6a1f1dSLionel Sambuc }
1375f4a2713aSLionel Sambuc }
1376f4a2713aSLionel Sambuc
1377f4a2713aSLionel Sambuc StringRef ModuleName = Id.back().first;
1378f4a2713aSLionel Sambuc SourceLocation ModuleNameLoc = Id.back().second;
1379f4a2713aSLionel Sambuc
1380f4a2713aSLionel Sambuc // Parse the optional attribute list.
1381f4a2713aSLionel Sambuc Attributes Attrs;
1382f4a2713aSLionel Sambuc parseOptionalAttributes(Attrs);
1383f4a2713aSLionel Sambuc
1384f4a2713aSLionel Sambuc // Parse the opening brace.
1385f4a2713aSLionel Sambuc if (!Tok.is(MMToken::LBrace)) {
1386f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
1387f4a2713aSLionel Sambuc << ModuleName;
1388f4a2713aSLionel Sambuc HadError = true;
1389f4a2713aSLionel Sambuc return;
1390f4a2713aSLionel Sambuc }
1391f4a2713aSLionel Sambuc SourceLocation LBraceLoc = consumeToken();
1392f4a2713aSLionel Sambuc
1393f4a2713aSLionel Sambuc // Determine whether this (sub)module has already been defined.
1394f4a2713aSLionel Sambuc if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
1395f4a2713aSLionel Sambuc if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) {
1396f4a2713aSLionel Sambuc // Skip the module definition.
1397f4a2713aSLionel Sambuc skipUntil(MMToken::RBrace);
1398f4a2713aSLionel Sambuc if (Tok.is(MMToken::RBrace))
1399f4a2713aSLionel Sambuc consumeToken();
1400f4a2713aSLionel Sambuc else {
1401f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1402f4a2713aSLionel Sambuc Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1403f4a2713aSLionel Sambuc HadError = true;
1404f4a2713aSLionel Sambuc }
1405f4a2713aSLionel Sambuc return;
1406f4a2713aSLionel Sambuc }
1407f4a2713aSLionel Sambuc
1408f4a2713aSLionel Sambuc Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
1409f4a2713aSLionel Sambuc << ModuleName;
1410f4a2713aSLionel Sambuc Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
1411f4a2713aSLionel Sambuc
1412f4a2713aSLionel Sambuc // Skip the module definition.
1413f4a2713aSLionel Sambuc skipUntil(MMToken::RBrace);
1414f4a2713aSLionel Sambuc if (Tok.is(MMToken::RBrace))
1415f4a2713aSLionel Sambuc consumeToken();
1416f4a2713aSLionel Sambuc
1417f4a2713aSLionel Sambuc HadError = true;
1418f4a2713aSLionel Sambuc return;
1419f4a2713aSLionel Sambuc }
1420f4a2713aSLionel Sambuc
1421f4a2713aSLionel Sambuc // Start defining this module.
1422f4a2713aSLionel Sambuc ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework,
1423f4a2713aSLionel Sambuc Explicit).first;
1424f4a2713aSLionel Sambuc ActiveModule->DefinitionLoc = ModuleNameLoc;
1425f4a2713aSLionel Sambuc if (Attrs.IsSystem || IsSystem)
1426f4a2713aSLionel Sambuc ActiveModule->IsSystem = true;
1427*0a6a1f1dSLionel Sambuc if (Attrs.IsExternC)
1428*0a6a1f1dSLionel Sambuc ActiveModule->IsExternC = true;
1429*0a6a1f1dSLionel Sambuc ActiveModule->Directory = Directory;
1430f4a2713aSLionel Sambuc
1431f4a2713aSLionel Sambuc bool Done = false;
1432f4a2713aSLionel Sambuc do {
1433f4a2713aSLionel Sambuc switch (Tok.Kind) {
1434f4a2713aSLionel Sambuc case MMToken::EndOfFile:
1435f4a2713aSLionel Sambuc case MMToken::RBrace:
1436f4a2713aSLionel Sambuc Done = true;
1437f4a2713aSLionel Sambuc break;
1438f4a2713aSLionel Sambuc
1439f4a2713aSLionel Sambuc case MMToken::ConfigMacros:
1440f4a2713aSLionel Sambuc parseConfigMacros();
1441f4a2713aSLionel Sambuc break;
1442f4a2713aSLionel Sambuc
1443f4a2713aSLionel Sambuc case MMToken::Conflict:
1444f4a2713aSLionel Sambuc parseConflict();
1445f4a2713aSLionel Sambuc break;
1446f4a2713aSLionel Sambuc
1447f4a2713aSLionel Sambuc case MMToken::ExplicitKeyword:
1448f4a2713aSLionel Sambuc case MMToken::ExternKeyword:
1449f4a2713aSLionel Sambuc case MMToken::FrameworkKeyword:
1450f4a2713aSLionel Sambuc case MMToken::ModuleKeyword:
1451f4a2713aSLionel Sambuc parseModuleDecl();
1452f4a2713aSLionel Sambuc break;
1453f4a2713aSLionel Sambuc
1454f4a2713aSLionel Sambuc case MMToken::ExportKeyword:
1455f4a2713aSLionel Sambuc parseExportDecl();
1456f4a2713aSLionel Sambuc break;
1457f4a2713aSLionel Sambuc
1458f4a2713aSLionel Sambuc case MMToken::UseKeyword:
1459f4a2713aSLionel Sambuc parseUseDecl();
1460f4a2713aSLionel Sambuc break;
1461f4a2713aSLionel Sambuc
1462f4a2713aSLionel Sambuc case MMToken::RequiresKeyword:
1463f4a2713aSLionel Sambuc parseRequiresDecl();
1464f4a2713aSLionel Sambuc break;
1465f4a2713aSLionel Sambuc
1466*0a6a1f1dSLionel Sambuc case MMToken::TextualKeyword:
1467*0a6a1f1dSLionel Sambuc parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
1468*0a6a1f1dSLionel Sambuc break;
1469*0a6a1f1dSLionel Sambuc
1470f4a2713aSLionel Sambuc case MMToken::UmbrellaKeyword: {
1471f4a2713aSLionel Sambuc SourceLocation UmbrellaLoc = consumeToken();
1472f4a2713aSLionel Sambuc if (Tok.is(MMToken::HeaderKeyword))
1473f4a2713aSLionel Sambuc parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
1474f4a2713aSLionel Sambuc else
1475f4a2713aSLionel Sambuc parseUmbrellaDirDecl(UmbrellaLoc);
1476f4a2713aSLionel Sambuc break;
1477f4a2713aSLionel Sambuc }
1478f4a2713aSLionel Sambuc
1479*0a6a1f1dSLionel Sambuc case MMToken::ExcludeKeyword:
1480*0a6a1f1dSLionel Sambuc parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
1481f4a2713aSLionel Sambuc break;
1482f4a2713aSLionel Sambuc
1483*0a6a1f1dSLionel Sambuc case MMToken::PrivateKeyword:
1484*0a6a1f1dSLionel Sambuc parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
1485f4a2713aSLionel Sambuc break;
1486f4a2713aSLionel Sambuc
1487f4a2713aSLionel Sambuc case MMToken::HeaderKeyword:
1488*0a6a1f1dSLionel Sambuc parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
1489f4a2713aSLionel Sambuc break;
1490f4a2713aSLionel Sambuc
1491f4a2713aSLionel Sambuc case MMToken::LinkKeyword:
1492f4a2713aSLionel Sambuc parseLinkDecl();
1493f4a2713aSLionel Sambuc break;
1494f4a2713aSLionel Sambuc
1495f4a2713aSLionel Sambuc default:
1496f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
1497f4a2713aSLionel Sambuc consumeToken();
1498f4a2713aSLionel Sambuc break;
1499f4a2713aSLionel Sambuc }
1500f4a2713aSLionel Sambuc } while (!Done);
1501f4a2713aSLionel Sambuc
1502f4a2713aSLionel Sambuc if (Tok.is(MMToken::RBrace))
1503f4a2713aSLionel Sambuc consumeToken();
1504f4a2713aSLionel Sambuc else {
1505f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
1506f4a2713aSLionel Sambuc Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
1507f4a2713aSLionel Sambuc HadError = true;
1508f4a2713aSLionel Sambuc }
1509f4a2713aSLionel Sambuc
1510f4a2713aSLionel Sambuc // If the active module is a top-level framework, and there are no link
1511f4a2713aSLionel Sambuc // libraries, automatically link against the framework.
1512f4a2713aSLionel Sambuc if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
1513f4a2713aSLionel Sambuc ActiveModule->LinkLibraries.empty()) {
1514f4a2713aSLionel Sambuc inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
1515f4a2713aSLionel Sambuc }
1516f4a2713aSLionel Sambuc
1517*0a6a1f1dSLionel Sambuc // If the module meets all requirements but is still unavailable, mark the
1518*0a6a1f1dSLionel Sambuc // whole tree as unavailable to prevent it from building.
1519*0a6a1f1dSLionel Sambuc if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement &&
1520*0a6a1f1dSLionel Sambuc ActiveModule->Parent) {
1521*0a6a1f1dSLionel Sambuc ActiveModule->getTopLevelModule()->markUnavailable();
1522*0a6a1f1dSLionel Sambuc ActiveModule->getTopLevelModule()->MissingHeaders.append(
1523*0a6a1f1dSLionel Sambuc ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
1524*0a6a1f1dSLionel Sambuc }
1525*0a6a1f1dSLionel Sambuc
1526f4a2713aSLionel Sambuc // We're done parsing this module. Pop back to the previous module.
1527f4a2713aSLionel Sambuc ActiveModule = PreviousActiveModule;
1528f4a2713aSLionel Sambuc }
1529f4a2713aSLionel Sambuc
1530f4a2713aSLionel Sambuc /// \brief Parse an extern module declaration.
1531f4a2713aSLionel Sambuc ///
1532f4a2713aSLionel Sambuc /// extern module-declaration:
1533f4a2713aSLionel Sambuc /// 'extern' 'module' module-id string-literal
parseExternModuleDecl()1534f4a2713aSLionel Sambuc void ModuleMapParser::parseExternModuleDecl() {
1535f4a2713aSLionel Sambuc assert(Tok.is(MMToken::ExternKeyword));
1536f4a2713aSLionel Sambuc consumeToken(); // 'extern' keyword
1537f4a2713aSLionel Sambuc
1538f4a2713aSLionel Sambuc // Parse 'module' keyword.
1539f4a2713aSLionel Sambuc if (!Tok.is(MMToken::ModuleKeyword)) {
1540f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
1541f4a2713aSLionel Sambuc consumeToken();
1542f4a2713aSLionel Sambuc HadError = true;
1543f4a2713aSLionel Sambuc return;
1544f4a2713aSLionel Sambuc }
1545f4a2713aSLionel Sambuc consumeToken(); // 'module' keyword
1546f4a2713aSLionel Sambuc
1547f4a2713aSLionel Sambuc // Parse the module name.
1548f4a2713aSLionel Sambuc ModuleId Id;
1549f4a2713aSLionel Sambuc if (parseModuleId(Id)) {
1550f4a2713aSLionel Sambuc HadError = true;
1551f4a2713aSLionel Sambuc return;
1552f4a2713aSLionel Sambuc }
1553f4a2713aSLionel Sambuc
1554f4a2713aSLionel Sambuc // Parse the referenced module map file name.
1555f4a2713aSLionel Sambuc if (!Tok.is(MMToken::StringLiteral)) {
1556f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
1557f4a2713aSLionel Sambuc HadError = true;
1558f4a2713aSLionel Sambuc return;
1559f4a2713aSLionel Sambuc }
1560f4a2713aSLionel Sambuc std::string FileName = Tok.getString();
1561f4a2713aSLionel Sambuc consumeToken(); // filename
1562f4a2713aSLionel Sambuc
1563f4a2713aSLionel Sambuc StringRef FileNameRef = FileName;
1564f4a2713aSLionel Sambuc SmallString<128> ModuleMapFileName;
1565f4a2713aSLionel Sambuc if (llvm::sys::path::is_relative(FileNameRef)) {
1566f4a2713aSLionel Sambuc ModuleMapFileName += Directory->getName();
1567f4a2713aSLionel Sambuc llvm::sys::path::append(ModuleMapFileName, FileName);
1568f4a2713aSLionel Sambuc FileNameRef = ModuleMapFileName.str();
1569f4a2713aSLionel Sambuc }
1570f4a2713aSLionel Sambuc if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef))
1571*0a6a1f1dSLionel Sambuc Map.parseModuleMapFile(
1572*0a6a1f1dSLionel Sambuc File, /*IsSystem=*/false,
1573*0a6a1f1dSLionel Sambuc Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
1574*0a6a1f1dSLionel Sambuc ? Directory
1575*0a6a1f1dSLionel Sambuc : File->getDir());
1576f4a2713aSLionel Sambuc }
1577f4a2713aSLionel Sambuc
1578f4a2713aSLionel Sambuc /// \brief Parse a requires declaration.
1579f4a2713aSLionel Sambuc ///
1580f4a2713aSLionel Sambuc /// requires-declaration:
1581f4a2713aSLionel Sambuc /// 'requires' feature-list
1582f4a2713aSLionel Sambuc ///
1583f4a2713aSLionel Sambuc /// feature-list:
1584f4a2713aSLionel Sambuc /// feature ',' feature-list
1585f4a2713aSLionel Sambuc /// feature
1586f4a2713aSLionel Sambuc ///
1587f4a2713aSLionel Sambuc /// feature:
1588f4a2713aSLionel Sambuc /// '!'[opt] identifier
parseRequiresDecl()1589f4a2713aSLionel Sambuc void ModuleMapParser::parseRequiresDecl() {
1590f4a2713aSLionel Sambuc assert(Tok.is(MMToken::RequiresKeyword));
1591f4a2713aSLionel Sambuc
1592f4a2713aSLionel Sambuc // Parse 'requires' keyword.
1593f4a2713aSLionel Sambuc consumeToken();
1594f4a2713aSLionel Sambuc
1595f4a2713aSLionel Sambuc // Parse the feature-list.
1596f4a2713aSLionel Sambuc do {
1597f4a2713aSLionel Sambuc bool RequiredState = true;
1598f4a2713aSLionel Sambuc if (Tok.is(MMToken::Exclaim)) {
1599f4a2713aSLionel Sambuc RequiredState = false;
1600f4a2713aSLionel Sambuc consumeToken();
1601f4a2713aSLionel Sambuc }
1602f4a2713aSLionel Sambuc
1603f4a2713aSLionel Sambuc if (!Tok.is(MMToken::Identifier)) {
1604f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
1605f4a2713aSLionel Sambuc HadError = true;
1606f4a2713aSLionel Sambuc return;
1607f4a2713aSLionel Sambuc }
1608f4a2713aSLionel Sambuc
1609f4a2713aSLionel Sambuc // Consume the feature name.
1610f4a2713aSLionel Sambuc std::string Feature = Tok.getString();
1611f4a2713aSLionel Sambuc consumeToken();
1612f4a2713aSLionel Sambuc
1613f4a2713aSLionel Sambuc // Add this feature.
1614f4a2713aSLionel Sambuc ActiveModule->addRequirement(Feature, RequiredState,
1615f4a2713aSLionel Sambuc Map.LangOpts, *Map.Target);
1616f4a2713aSLionel Sambuc
1617f4a2713aSLionel Sambuc if (!Tok.is(MMToken::Comma))
1618f4a2713aSLionel Sambuc break;
1619f4a2713aSLionel Sambuc
1620f4a2713aSLionel Sambuc // Consume the comma.
1621f4a2713aSLionel Sambuc consumeToken();
1622f4a2713aSLionel Sambuc } while (true);
1623f4a2713aSLionel Sambuc }
1624f4a2713aSLionel Sambuc
1625f4a2713aSLionel Sambuc /// \brief Append to \p Paths the set of paths needed to get to the
1626f4a2713aSLionel Sambuc /// subframework in which the given module lives.
appendSubframeworkPaths(Module * Mod,SmallVectorImpl<char> & Path)1627f4a2713aSLionel Sambuc static void appendSubframeworkPaths(Module *Mod,
1628f4a2713aSLionel Sambuc SmallVectorImpl<char> &Path) {
1629f4a2713aSLionel Sambuc // Collect the framework names from the given module to the top-level module.
1630f4a2713aSLionel Sambuc SmallVector<StringRef, 2> Paths;
1631f4a2713aSLionel Sambuc for (; Mod; Mod = Mod->Parent) {
1632f4a2713aSLionel Sambuc if (Mod->IsFramework)
1633f4a2713aSLionel Sambuc Paths.push_back(Mod->Name);
1634f4a2713aSLionel Sambuc }
1635f4a2713aSLionel Sambuc
1636f4a2713aSLionel Sambuc if (Paths.empty())
1637f4a2713aSLionel Sambuc return;
1638f4a2713aSLionel Sambuc
1639f4a2713aSLionel Sambuc // Add Frameworks/Name.framework for each subframework.
1640f4a2713aSLionel Sambuc for (unsigned I = Paths.size() - 1; I != 0; --I)
1641f4a2713aSLionel Sambuc llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework");
1642f4a2713aSLionel Sambuc }
1643f4a2713aSLionel Sambuc
1644f4a2713aSLionel Sambuc /// \brief Parse a header declaration.
1645f4a2713aSLionel Sambuc ///
1646f4a2713aSLionel Sambuc /// header-declaration:
1647*0a6a1f1dSLionel Sambuc /// 'textual'[opt] 'header' string-literal
1648*0a6a1f1dSLionel Sambuc /// 'private' 'textual'[opt] 'header' string-literal
1649*0a6a1f1dSLionel Sambuc /// 'exclude' 'header' string-literal
1650*0a6a1f1dSLionel Sambuc /// 'umbrella' 'header' string-literal
1651*0a6a1f1dSLionel Sambuc ///
1652*0a6a1f1dSLionel Sambuc /// FIXME: Support 'private textual header'.
parseHeaderDecl(MMToken::TokenKind LeadingToken,SourceLocation LeadingLoc)1653f4a2713aSLionel Sambuc void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
1654f4a2713aSLionel Sambuc SourceLocation LeadingLoc) {
1655*0a6a1f1dSLionel Sambuc // We've already consumed the first token.
1656*0a6a1f1dSLionel Sambuc ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
1657*0a6a1f1dSLionel Sambuc if (LeadingToken == MMToken::PrivateKeyword) {
1658*0a6a1f1dSLionel Sambuc Role = ModuleMap::PrivateHeader;
1659*0a6a1f1dSLionel Sambuc // 'private' may optionally be followed by 'textual'.
1660*0a6a1f1dSLionel Sambuc if (Tok.is(MMToken::TextualKeyword)) {
1661*0a6a1f1dSLionel Sambuc LeadingToken = Tok.Kind;
1662f4a2713aSLionel Sambuc consumeToken();
1663*0a6a1f1dSLionel Sambuc }
1664*0a6a1f1dSLionel Sambuc }
1665*0a6a1f1dSLionel Sambuc if (LeadingToken == MMToken::TextualKeyword)
1666*0a6a1f1dSLionel Sambuc Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
1667*0a6a1f1dSLionel Sambuc
1668*0a6a1f1dSLionel Sambuc if (LeadingToken != MMToken::HeaderKeyword) {
1669*0a6a1f1dSLionel Sambuc if (!Tok.is(MMToken::HeaderKeyword)) {
1670*0a6a1f1dSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1671*0a6a1f1dSLionel Sambuc << (LeadingToken == MMToken::PrivateKeyword ? "private" :
1672*0a6a1f1dSLionel Sambuc LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
1673*0a6a1f1dSLionel Sambuc LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
1674*0a6a1f1dSLionel Sambuc return;
1675*0a6a1f1dSLionel Sambuc }
1676*0a6a1f1dSLionel Sambuc consumeToken();
1677*0a6a1f1dSLionel Sambuc }
1678f4a2713aSLionel Sambuc
1679f4a2713aSLionel Sambuc // Parse the header name.
1680f4a2713aSLionel Sambuc if (!Tok.is(MMToken::StringLiteral)) {
1681f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1682f4a2713aSLionel Sambuc << "header";
1683f4a2713aSLionel Sambuc HadError = true;
1684f4a2713aSLionel Sambuc return;
1685f4a2713aSLionel Sambuc }
1686*0a6a1f1dSLionel Sambuc Module::UnresolvedHeaderDirective Header;
1687*0a6a1f1dSLionel Sambuc Header.FileName = Tok.getString();
1688*0a6a1f1dSLionel Sambuc Header.FileNameLoc = consumeToken();
1689f4a2713aSLionel Sambuc
1690f4a2713aSLionel Sambuc // Check whether we already have an umbrella.
1691f4a2713aSLionel Sambuc if (LeadingToken == MMToken::UmbrellaKeyword && ActiveModule->Umbrella) {
1692*0a6a1f1dSLionel Sambuc Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
1693f4a2713aSLionel Sambuc << ActiveModule->getFullModuleName();
1694f4a2713aSLionel Sambuc HadError = true;
1695f4a2713aSLionel Sambuc return;
1696f4a2713aSLionel Sambuc }
1697f4a2713aSLionel Sambuc
1698f4a2713aSLionel Sambuc // Look for this file.
1699*0a6a1f1dSLionel Sambuc const FileEntry *File = nullptr;
1700*0a6a1f1dSLionel Sambuc const FileEntry *BuiltinFile = nullptr;
1701*0a6a1f1dSLionel Sambuc SmallString<128> RelativePathName;
1702*0a6a1f1dSLionel Sambuc if (llvm::sys::path::is_absolute(Header.FileName)) {
1703*0a6a1f1dSLionel Sambuc RelativePathName = Header.FileName;
1704*0a6a1f1dSLionel Sambuc File = SourceMgr.getFileManager().getFile(RelativePathName);
1705f4a2713aSLionel Sambuc } else {
1706f4a2713aSLionel Sambuc // Search for the header file within the search directory.
1707*0a6a1f1dSLionel Sambuc SmallString<128> FullPathName(Directory->getName());
1708*0a6a1f1dSLionel Sambuc unsigned FullPathLength = FullPathName.size();
1709f4a2713aSLionel Sambuc
1710f4a2713aSLionel Sambuc if (ActiveModule->isPartOfFramework()) {
1711*0a6a1f1dSLionel Sambuc appendSubframeworkPaths(ActiveModule, RelativePathName);
1712f4a2713aSLionel Sambuc
1713f4a2713aSLionel Sambuc // Check whether this file is in the public headers.
1714*0a6a1f1dSLionel Sambuc llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
1715*0a6a1f1dSLionel Sambuc llvm::sys::path::append(FullPathName, RelativePathName.str());
1716*0a6a1f1dSLionel Sambuc File = SourceMgr.getFileManager().getFile(FullPathName);
1717f4a2713aSLionel Sambuc
1718f4a2713aSLionel Sambuc if (!File) {
1719f4a2713aSLionel Sambuc // Check whether this file is in the private headers.
1720*0a6a1f1dSLionel Sambuc // FIXME: Should we retain the subframework paths here?
1721*0a6a1f1dSLionel Sambuc RelativePathName.clear();
1722*0a6a1f1dSLionel Sambuc FullPathName.resize(FullPathLength);
1723*0a6a1f1dSLionel Sambuc llvm::sys::path::append(RelativePathName, "PrivateHeaders",
1724*0a6a1f1dSLionel Sambuc Header.FileName);
1725*0a6a1f1dSLionel Sambuc llvm::sys::path::append(FullPathName, RelativePathName.str());
1726*0a6a1f1dSLionel Sambuc File = SourceMgr.getFileManager().getFile(FullPathName);
1727f4a2713aSLionel Sambuc }
1728f4a2713aSLionel Sambuc } else {
1729f4a2713aSLionel Sambuc // Lookup for normal headers.
1730*0a6a1f1dSLionel Sambuc llvm::sys::path::append(RelativePathName, Header.FileName);
1731*0a6a1f1dSLionel Sambuc llvm::sys::path::append(FullPathName, RelativePathName.str());
1732*0a6a1f1dSLionel Sambuc File = SourceMgr.getFileManager().getFile(FullPathName);
1733f4a2713aSLionel Sambuc
1734f4a2713aSLionel Sambuc // If this is a system module with a top-level header, this header
1735f4a2713aSLionel Sambuc // may have a counterpart (or replacement) in the set of headers
1736f4a2713aSLionel Sambuc // supplied by Clang. Find that builtin header.
1737f4a2713aSLionel Sambuc if (ActiveModule->IsSystem && LeadingToken != MMToken::UmbrellaKeyword &&
1738f4a2713aSLionel Sambuc BuiltinIncludeDir && BuiltinIncludeDir != Directory &&
1739*0a6a1f1dSLionel Sambuc isBuiltinHeader(Header.FileName)) {
1740f4a2713aSLionel Sambuc SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName());
1741*0a6a1f1dSLionel Sambuc llvm::sys::path::append(BuiltinPathName, Header.FileName);
1742f4a2713aSLionel Sambuc BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName);
1743f4a2713aSLionel Sambuc
1744f4a2713aSLionel Sambuc // If Clang supplies this header but the underlying system does not,
1745f4a2713aSLionel Sambuc // just silently swap in our builtin version. Otherwise, we'll end
1746f4a2713aSLionel Sambuc // up adding both (later).
1747f4a2713aSLionel Sambuc if (!File && BuiltinFile) {
1748f4a2713aSLionel Sambuc File = BuiltinFile;
1749*0a6a1f1dSLionel Sambuc RelativePathName = BuiltinPathName;
1750*0a6a1f1dSLionel Sambuc BuiltinFile = nullptr;
1751f4a2713aSLionel Sambuc }
1752f4a2713aSLionel Sambuc }
1753f4a2713aSLionel Sambuc }
1754f4a2713aSLionel Sambuc }
1755f4a2713aSLionel Sambuc
1756f4a2713aSLionel Sambuc // FIXME: We shouldn't be eagerly stat'ing every file named in a module map.
1757f4a2713aSLionel Sambuc // Come up with a lazy way to do this.
1758f4a2713aSLionel Sambuc if (File) {
1759f4a2713aSLionel Sambuc if (LeadingToken == MMToken::UmbrellaKeyword) {
1760f4a2713aSLionel Sambuc const DirectoryEntry *UmbrellaDir = File->getDir();
1761f4a2713aSLionel Sambuc if (Module *UmbrellaModule = Map.UmbrellaDirs[UmbrellaDir]) {
1762f4a2713aSLionel Sambuc Diags.Report(LeadingLoc, diag::err_mmap_umbrella_clash)
1763f4a2713aSLionel Sambuc << UmbrellaModule->getFullModuleName();
1764f4a2713aSLionel Sambuc HadError = true;
1765f4a2713aSLionel Sambuc } else {
1766f4a2713aSLionel Sambuc // Record this umbrella header.
1767f4a2713aSLionel Sambuc Map.setUmbrellaHeader(ActiveModule, File);
1768f4a2713aSLionel Sambuc }
1769*0a6a1f1dSLionel Sambuc } else if (LeadingToken == MMToken::ExcludeKeyword) {
1770*0a6a1f1dSLionel Sambuc Module::Header H = {RelativePathName.str(), File};
1771*0a6a1f1dSLionel Sambuc Map.excludeHeader(ActiveModule, H);
1772f4a2713aSLionel Sambuc } else {
1773*0a6a1f1dSLionel Sambuc // If there is a builtin counterpart to this file, add it now, before
1774*0a6a1f1dSLionel Sambuc // the "real" header, so we build the built-in one first when building
1775*0a6a1f1dSLionel Sambuc // the module.
1776*0a6a1f1dSLionel Sambuc if (BuiltinFile) {
1777*0a6a1f1dSLionel Sambuc // FIXME: Taking the name from the FileEntry is unstable and can give
1778*0a6a1f1dSLionel Sambuc // different results depending on how we've previously named that file
1779*0a6a1f1dSLionel Sambuc // in this build.
1780*0a6a1f1dSLionel Sambuc Module::Header H = { BuiltinFile->getName(), BuiltinFile };
1781*0a6a1f1dSLionel Sambuc Map.addHeader(ActiveModule, H, Role);
1782*0a6a1f1dSLionel Sambuc }
1783*0a6a1f1dSLionel Sambuc
1784f4a2713aSLionel Sambuc // Record this header.
1785*0a6a1f1dSLionel Sambuc Module::Header H = { RelativePathName.str(), File };
1786*0a6a1f1dSLionel Sambuc Map.addHeader(ActiveModule, H, Role);
1787f4a2713aSLionel Sambuc }
1788f4a2713aSLionel Sambuc } else if (LeadingToken != MMToken::ExcludeKeyword) {
1789f4a2713aSLionel Sambuc // Ignore excluded header files. They're optional anyway.
1790f4a2713aSLionel Sambuc
1791*0a6a1f1dSLionel Sambuc // If we find a module that has a missing header, we mark this module as
1792*0a6a1f1dSLionel Sambuc // unavailable and store the header directive for displaying diagnostics.
1793*0a6a1f1dSLionel Sambuc Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
1794*0a6a1f1dSLionel Sambuc ActiveModule->markUnavailable();
1795*0a6a1f1dSLionel Sambuc ActiveModule->MissingHeaders.push_back(Header);
1796f4a2713aSLionel Sambuc }
1797f4a2713aSLionel Sambuc }
1798f4a2713aSLionel Sambuc
1799f4a2713aSLionel Sambuc /// \brief Parse an umbrella directory declaration.
1800f4a2713aSLionel Sambuc ///
1801f4a2713aSLionel Sambuc /// umbrella-dir-declaration:
1802f4a2713aSLionel Sambuc /// umbrella string-literal
parseUmbrellaDirDecl(SourceLocation UmbrellaLoc)1803f4a2713aSLionel Sambuc void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
1804f4a2713aSLionel Sambuc // Parse the directory name.
1805f4a2713aSLionel Sambuc if (!Tok.is(MMToken::StringLiteral)) {
1806f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
1807f4a2713aSLionel Sambuc << "umbrella";
1808f4a2713aSLionel Sambuc HadError = true;
1809f4a2713aSLionel Sambuc return;
1810f4a2713aSLionel Sambuc }
1811f4a2713aSLionel Sambuc
1812f4a2713aSLionel Sambuc std::string DirName = Tok.getString();
1813f4a2713aSLionel Sambuc SourceLocation DirNameLoc = consumeToken();
1814f4a2713aSLionel Sambuc
1815f4a2713aSLionel Sambuc // Check whether we already have an umbrella.
1816f4a2713aSLionel Sambuc if (ActiveModule->Umbrella) {
1817f4a2713aSLionel Sambuc Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
1818f4a2713aSLionel Sambuc << ActiveModule->getFullModuleName();
1819f4a2713aSLionel Sambuc HadError = true;
1820f4a2713aSLionel Sambuc return;
1821f4a2713aSLionel Sambuc }
1822f4a2713aSLionel Sambuc
1823f4a2713aSLionel Sambuc // Look for this file.
1824*0a6a1f1dSLionel Sambuc const DirectoryEntry *Dir = nullptr;
1825f4a2713aSLionel Sambuc if (llvm::sys::path::is_absolute(DirName))
1826f4a2713aSLionel Sambuc Dir = SourceMgr.getFileManager().getDirectory(DirName);
1827f4a2713aSLionel Sambuc else {
1828f4a2713aSLionel Sambuc SmallString<128> PathName;
1829f4a2713aSLionel Sambuc PathName = Directory->getName();
1830f4a2713aSLionel Sambuc llvm::sys::path::append(PathName, DirName);
1831f4a2713aSLionel Sambuc Dir = SourceMgr.getFileManager().getDirectory(PathName);
1832f4a2713aSLionel Sambuc }
1833f4a2713aSLionel Sambuc
1834f4a2713aSLionel Sambuc if (!Dir) {
1835f4a2713aSLionel Sambuc Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found)
1836f4a2713aSLionel Sambuc << DirName;
1837f4a2713aSLionel Sambuc HadError = true;
1838f4a2713aSLionel Sambuc return;
1839f4a2713aSLionel Sambuc }
1840f4a2713aSLionel Sambuc
1841f4a2713aSLionel Sambuc if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
1842f4a2713aSLionel Sambuc Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
1843f4a2713aSLionel Sambuc << OwningModule->getFullModuleName();
1844f4a2713aSLionel Sambuc HadError = true;
1845f4a2713aSLionel Sambuc return;
1846f4a2713aSLionel Sambuc }
1847f4a2713aSLionel Sambuc
1848f4a2713aSLionel Sambuc // Record this umbrella directory.
1849f4a2713aSLionel Sambuc Map.setUmbrellaDir(ActiveModule, Dir);
1850f4a2713aSLionel Sambuc }
1851f4a2713aSLionel Sambuc
1852f4a2713aSLionel Sambuc /// \brief Parse a module export declaration.
1853f4a2713aSLionel Sambuc ///
1854f4a2713aSLionel Sambuc /// export-declaration:
1855f4a2713aSLionel Sambuc /// 'export' wildcard-module-id
1856f4a2713aSLionel Sambuc ///
1857f4a2713aSLionel Sambuc /// wildcard-module-id:
1858f4a2713aSLionel Sambuc /// identifier
1859f4a2713aSLionel Sambuc /// '*'
1860f4a2713aSLionel Sambuc /// identifier '.' wildcard-module-id
parseExportDecl()1861f4a2713aSLionel Sambuc void ModuleMapParser::parseExportDecl() {
1862f4a2713aSLionel Sambuc assert(Tok.is(MMToken::ExportKeyword));
1863f4a2713aSLionel Sambuc SourceLocation ExportLoc = consumeToken();
1864f4a2713aSLionel Sambuc
1865f4a2713aSLionel Sambuc // Parse the module-id with an optional wildcard at the end.
1866f4a2713aSLionel Sambuc ModuleId ParsedModuleId;
1867f4a2713aSLionel Sambuc bool Wildcard = false;
1868f4a2713aSLionel Sambuc do {
1869*0a6a1f1dSLionel Sambuc // FIXME: Support string-literal module names here.
1870f4a2713aSLionel Sambuc if (Tok.is(MMToken::Identifier)) {
1871f4a2713aSLionel Sambuc ParsedModuleId.push_back(std::make_pair(Tok.getString(),
1872f4a2713aSLionel Sambuc Tok.getLocation()));
1873f4a2713aSLionel Sambuc consumeToken();
1874f4a2713aSLionel Sambuc
1875f4a2713aSLionel Sambuc if (Tok.is(MMToken::Period)) {
1876f4a2713aSLionel Sambuc consumeToken();
1877f4a2713aSLionel Sambuc continue;
1878f4a2713aSLionel Sambuc }
1879f4a2713aSLionel Sambuc
1880f4a2713aSLionel Sambuc break;
1881f4a2713aSLionel Sambuc }
1882f4a2713aSLionel Sambuc
1883f4a2713aSLionel Sambuc if(Tok.is(MMToken::Star)) {
1884f4a2713aSLionel Sambuc Wildcard = true;
1885f4a2713aSLionel Sambuc consumeToken();
1886f4a2713aSLionel Sambuc break;
1887f4a2713aSLionel Sambuc }
1888f4a2713aSLionel Sambuc
1889f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
1890f4a2713aSLionel Sambuc HadError = true;
1891f4a2713aSLionel Sambuc return;
1892f4a2713aSLionel Sambuc } while (true);
1893f4a2713aSLionel Sambuc
1894f4a2713aSLionel Sambuc Module::UnresolvedExportDecl Unresolved = {
1895f4a2713aSLionel Sambuc ExportLoc, ParsedModuleId, Wildcard
1896f4a2713aSLionel Sambuc };
1897f4a2713aSLionel Sambuc ActiveModule->UnresolvedExports.push_back(Unresolved);
1898f4a2713aSLionel Sambuc }
1899f4a2713aSLionel Sambuc
1900f4a2713aSLionel Sambuc /// \brief Parse a module uses declaration.
1901f4a2713aSLionel Sambuc ///
1902f4a2713aSLionel Sambuc /// uses-declaration:
1903f4a2713aSLionel Sambuc /// 'uses' wildcard-module-id
parseUseDecl()1904f4a2713aSLionel Sambuc void ModuleMapParser::parseUseDecl() {
1905f4a2713aSLionel Sambuc assert(Tok.is(MMToken::UseKeyword));
1906f4a2713aSLionel Sambuc consumeToken();
1907f4a2713aSLionel Sambuc // Parse the module-id.
1908f4a2713aSLionel Sambuc ModuleId ParsedModuleId;
1909*0a6a1f1dSLionel Sambuc parseModuleId(ParsedModuleId);
1910f4a2713aSLionel Sambuc
1911f4a2713aSLionel Sambuc ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
1912f4a2713aSLionel Sambuc }
1913f4a2713aSLionel Sambuc
1914f4a2713aSLionel Sambuc /// \brief Parse a link declaration.
1915f4a2713aSLionel Sambuc ///
1916f4a2713aSLionel Sambuc /// module-declaration:
1917f4a2713aSLionel Sambuc /// 'link' 'framework'[opt] string-literal
parseLinkDecl()1918f4a2713aSLionel Sambuc void ModuleMapParser::parseLinkDecl() {
1919f4a2713aSLionel Sambuc assert(Tok.is(MMToken::LinkKeyword));
1920f4a2713aSLionel Sambuc SourceLocation LinkLoc = consumeToken();
1921f4a2713aSLionel Sambuc
1922f4a2713aSLionel Sambuc // Parse the optional 'framework' keyword.
1923f4a2713aSLionel Sambuc bool IsFramework = false;
1924f4a2713aSLionel Sambuc if (Tok.is(MMToken::FrameworkKeyword)) {
1925f4a2713aSLionel Sambuc consumeToken();
1926f4a2713aSLionel Sambuc IsFramework = true;
1927f4a2713aSLionel Sambuc }
1928f4a2713aSLionel Sambuc
1929f4a2713aSLionel Sambuc // Parse the library name
1930f4a2713aSLionel Sambuc if (!Tok.is(MMToken::StringLiteral)) {
1931f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
1932f4a2713aSLionel Sambuc << IsFramework << SourceRange(LinkLoc);
1933f4a2713aSLionel Sambuc HadError = true;
1934f4a2713aSLionel Sambuc return;
1935f4a2713aSLionel Sambuc }
1936f4a2713aSLionel Sambuc
1937f4a2713aSLionel Sambuc std::string LibraryName = Tok.getString();
1938f4a2713aSLionel Sambuc consumeToken();
1939f4a2713aSLionel Sambuc ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
1940f4a2713aSLionel Sambuc IsFramework));
1941f4a2713aSLionel Sambuc }
1942f4a2713aSLionel Sambuc
1943f4a2713aSLionel Sambuc /// \brief Parse a configuration macro declaration.
1944f4a2713aSLionel Sambuc ///
1945f4a2713aSLionel Sambuc /// module-declaration:
1946f4a2713aSLionel Sambuc /// 'config_macros' attributes[opt] config-macro-list?
1947f4a2713aSLionel Sambuc ///
1948f4a2713aSLionel Sambuc /// config-macro-list:
1949f4a2713aSLionel Sambuc /// identifier (',' identifier)?
parseConfigMacros()1950f4a2713aSLionel Sambuc void ModuleMapParser::parseConfigMacros() {
1951f4a2713aSLionel Sambuc assert(Tok.is(MMToken::ConfigMacros));
1952f4a2713aSLionel Sambuc SourceLocation ConfigMacrosLoc = consumeToken();
1953f4a2713aSLionel Sambuc
1954f4a2713aSLionel Sambuc // Only top-level modules can have configuration macros.
1955f4a2713aSLionel Sambuc if (ActiveModule->Parent) {
1956f4a2713aSLionel Sambuc Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
1957f4a2713aSLionel Sambuc }
1958f4a2713aSLionel Sambuc
1959f4a2713aSLionel Sambuc // Parse the optional attributes.
1960f4a2713aSLionel Sambuc Attributes Attrs;
1961f4a2713aSLionel Sambuc parseOptionalAttributes(Attrs);
1962f4a2713aSLionel Sambuc if (Attrs.IsExhaustive && !ActiveModule->Parent) {
1963f4a2713aSLionel Sambuc ActiveModule->ConfigMacrosExhaustive = true;
1964f4a2713aSLionel Sambuc }
1965f4a2713aSLionel Sambuc
1966f4a2713aSLionel Sambuc // If we don't have an identifier, we're done.
1967*0a6a1f1dSLionel Sambuc // FIXME: Support macros with the same name as a keyword here.
1968f4a2713aSLionel Sambuc if (!Tok.is(MMToken::Identifier))
1969f4a2713aSLionel Sambuc return;
1970f4a2713aSLionel Sambuc
1971f4a2713aSLionel Sambuc // Consume the first identifier.
1972f4a2713aSLionel Sambuc if (!ActiveModule->Parent) {
1973f4a2713aSLionel Sambuc ActiveModule->ConfigMacros.push_back(Tok.getString().str());
1974f4a2713aSLionel Sambuc }
1975f4a2713aSLionel Sambuc consumeToken();
1976f4a2713aSLionel Sambuc
1977f4a2713aSLionel Sambuc do {
1978f4a2713aSLionel Sambuc // If there's a comma, consume it.
1979f4a2713aSLionel Sambuc if (!Tok.is(MMToken::Comma))
1980f4a2713aSLionel Sambuc break;
1981f4a2713aSLionel Sambuc consumeToken();
1982f4a2713aSLionel Sambuc
1983f4a2713aSLionel Sambuc // We expect to see a macro name here.
1984*0a6a1f1dSLionel Sambuc // FIXME: Support macros with the same name as a keyword here.
1985f4a2713aSLionel Sambuc if (!Tok.is(MMToken::Identifier)) {
1986f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
1987f4a2713aSLionel Sambuc break;
1988f4a2713aSLionel Sambuc }
1989f4a2713aSLionel Sambuc
1990f4a2713aSLionel Sambuc // Consume the macro name.
1991f4a2713aSLionel Sambuc if (!ActiveModule->Parent) {
1992f4a2713aSLionel Sambuc ActiveModule->ConfigMacros.push_back(Tok.getString().str());
1993f4a2713aSLionel Sambuc }
1994f4a2713aSLionel Sambuc consumeToken();
1995f4a2713aSLionel Sambuc } while (true);
1996f4a2713aSLionel Sambuc }
1997f4a2713aSLionel Sambuc
1998f4a2713aSLionel Sambuc /// \brief Format a module-id into a string.
formatModuleId(const ModuleId & Id)1999f4a2713aSLionel Sambuc static std::string formatModuleId(const ModuleId &Id) {
2000f4a2713aSLionel Sambuc std::string result;
2001f4a2713aSLionel Sambuc {
2002f4a2713aSLionel Sambuc llvm::raw_string_ostream OS(result);
2003f4a2713aSLionel Sambuc
2004f4a2713aSLionel Sambuc for (unsigned I = 0, N = Id.size(); I != N; ++I) {
2005f4a2713aSLionel Sambuc if (I)
2006f4a2713aSLionel Sambuc OS << ".";
2007f4a2713aSLionel Sambuc OS << Id[I].first;
2008f4a2713aSLionel Sambuc }
2009f4a2713aSLionel Sambuc }
2010f4a2713aSLionel Sambuc
2011f4a2713aSLionel Sambuc return result;
2012f4a2713aSLionel Sambuc }
2013f4a2713aSLionel Sambuc
2014f4a2713aSLionel Sambuc /// \brief Parse a conflict declaration.
2015f4a2713aSLionel Sambuc ///
2016f4a2713aSLionel Sambuc /// module-declaration:
2017f4a2713aSLionel Sambuc /// 'conflict' module-id ',' string-literal
parseConflict()2018f4a2713aSLionel Sambuc void ModuleMapParser::parseConflict() {
2019f4a2713aSLionel Sambuc assert(Tok.is(MMToken::Conflict));
2020f4a2713aSLionel Sambuc SourceLocation ConflictLoc = consumeToken();
2021f4a2713aSLionel Sambuc Module::UnresolvedConflict Conflict;
2022f4a2713aSLionel Sambuc
2023f4a2713aSLionel Sambuc // Parse the module-id.
2024f4a2713aSLionel Sambuc if (parseModuleId(Conflict.Id))
2025f4a2713aSLionel Sambuc return;
2026f4a2713aSLionel Sambuc
2027f4a2713aSLionel Sambuc // Parse the ','.
2028f4a2713aSLionel Sambuc if (!Tok.is(MMToken::Comma)) {
2029f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
2030f4a2713aSLionel Sambuc << SourceRange(ConflictLoc);
2031f4a2713aSLionel Sambuc return;
2032f4a2713aSLionel Sambuc }
2033f4a2713aSLionel Sambuc consumeToken();
2034f4a2713aSLionel Sambuc
2035f4a2713aSLionel Sambuc // Parse the message.
2036f4a2713aSLionel Sambuc if (!Tok.is(MMToken::StringLiteral)) {
2037f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
2038f4a2713aSLionel Sambuc << formatModuleId(Conflict.Id);
2039f4a2713aSLionel Sambuc return;
2040f4a2713aSLionel Sambuc }
2041f4a2713aSLionel Sambuc Conflict.Message = Tok.getString().str();
2042f4a2713aSLionel Sambuc consumeToken();
2043f4a2713aSLionel Sambuc
2044f4a2713aSLionel Sambuc // Add this unresolved conflict.
2045f4a2713aSLionel Sambuc ActiveModule->UnresolvedConflicts.push_back(Conflict);
2046f4a2713aSLionel Sambuc }
2047f4a2713aSLionel Sambuc
2048f4a2713aSLionel Sambuc /// \brief Parse an inferred module declaration (wildcard modules).
2049f4a2713aSLionel Sambuc ///
2050f4a2713aSLionel Sambuc /// module-declaration:
2051f4a2713aSLionel Sambuc /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
2052f4a2713aSLionel Sambuc /// { inferred-module-member* }
2053f4a2713aSLionel Sambuc ///
2054f4a2713aSLionel Sambuc /// inferred-module-member:
2055f4a2713aSLionel Sambuc /// 'export' '*'
2056f4a2713aSLionel Sambuc /// 'exclude' identifier
parseInferredModuleDecl(bool Framework,bool Explicit)2057f4a2713aSLionel Sambuc void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
2058f4a2713aSLionel Sambuc assert(Tok.is(MMToken::Star));
2059f4a2713aSLionel Sambuc SourceLocation StarLoc = consumeToken();
2060f4a2713aSLionel Sambuc bool Failed = false;
2061f4a2713aSLionel Sambuc
2062f4a2713aSLionel Sambuc // Inferred modules must be submodules.
2063f4a2713aSLionel Sambuc if (!ActiveModule && !Framework) {
2064f4a2713aSLionel Sambuc Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
2065f4a2713aSLionel Sambuc Failed = true;
2066f4a2713aSLionel Sambuc }
2067f4a2713aSLionel Sambuc
2068f4a2713aSLionel Sambuc if (ActiveModule) {
2069f4a2713aSLionel Sambuc // Inferred modules must have umbrella directories.
2070*0a6a1f1dSLionel Sambuc if (!Failed && ActiveModule->IsAvailable &&
2071*0a6a1f1dSLionel Sambuc !ActiveModule->getUmbrellaDir()) {
2072f4a2713aSLionel Sambuc Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
2073f4a2713aSLionel Sambuc Failed = true;
2074f4a2713aSLionel Sambuc }
2075f4a2713aSLionel Sambuc
2076f4a2713aSLionel Sambuc // Check for redefinition of an inferred module.
2077f4a2713aSLionel Sambuc if (!Failed && ActiveModule->InferSubmodules) {
2078f4a2713aSLionel Sambuc Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
2079f4a2713aSLionel Sambuc if (ActiveModule->InferredSubmoduleLoc.isValid())
2080f4a2713aSLionel Sambuc Diags.Report(ActiveModule->InferredSubmoduleLoc,
2081f4a2713aSLionel Sambuc diag::note_mmap_prev_definition);
2082f4a2713aSLionel Sambuc Failed = true;
2083f4a2713aSLionel Sambuc }
2084f4a2713aSLionel Sambuc
2085f4a2713aSLionel Sambuc // Check for the 'framework' keyword, which is not permitted here.
2086f4a2713aSLionel Sambuc if (Framework) {
2087f4a2713aSLionel Sambuc Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
2088f4a2713aSLionel Sambuc Framework = false;
2089f4a2713aSLionel Sambuc }
2090f4a2713aSLionel Sambuc } else if (Explicit) {
2091f4a2713aSLionel Sambuc Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
2092f4a2713aSLionel Sambuc Explicit = false;
2093f4a2713aSLionel Sambuc }
2094f4a2713aSLionel Sambuc
2095f4a2713aSLionel Sambuc // If there were any problems with this inferred submodule, skip its body.
2096f4a2713aSLionel Sambuc if (Failed) {
2097f4a2713aSLionel Sambuc if (Tok.is(MMToken::LBrace)) {
2098f4a2713aSLionel Sambuc consumeToken();
2099f4a2713aSLionel Sambuc skipUntil(MMToken::RBrace);
2100f4a2713aSLionel Sambuc if (Tok.is(MMToken::RBrace))
2101f4a2713aSLionel Sambuc consumeToken();
2102f4a2713aSLionel Sambuc }
2103f4a2713aSLionel Sambuc HadError = true;
2104f4a2713aSLionel Sambuc return;
2105f4a2713aSLionel Sambuc }
2106f4a2713aSLionel Sambuc
2107f4a2713aSLionel Sambuc // Parse optional attributes.
2108f4a2713aSLionel Sambuc Attributes Attrs;
2109f4a2713aSLionel Sambuc parseOptionalAttributes(Attrs);
2110f4a2713aSLionel Sambuc
2111f4a2713aSLionel Sambuc if (ActiveModule) {
2112f4a2713aSLionel Sambuc // Note that we have an inferred submodule.
2113f4a2713aSLionel Sambuc ActiveModule->InferSubmodules = true;
2114f4a2713aSLionel Sambuc ActiveModule->InferredSubmoduleLoc = StarLoc;
2115f4a2713aSLionel Sambuc ActiveModule->InferExplicitSubmodules = Explicit;
2116f4a2713aSLionel Sambuc } else {
2117f4a2713aSLionel Sambuc // We'll be inferring framework modules for this directory.
2118f4a2713aSLionel Sambuc Map.InferredDirectories[Directory].InferModules = true;
2119*0a6a1f1dSLionel Sambuc Map.InferredDirectories[Directory].Attrs = Attrs;
2120*0a6a1f1dSLionel Sambuc Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
2121*0a6a1f1dSLionel Sambuc // FIXME: Handle the 'framework' keyword.
2122f4a2713aSLionel Sambuc }
2123f4a2713aSLionel Sambuc
2124f4a2713aSLionel Sambuc // Parse the opening brace.
2125f4a2713aSLionel Sambuc if (!Tok.is(MMToken::LBrace)) {
2126f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
2127f4a2713aSLionel Sambuc HadError = true;
2128f4a2713aSLionel Sambuc return;
2129f4a2713aSLionel Sambuc }
2130f4a2713aSLionel Sambuc SourceLocation LBraceLoc = consumeToken();
2131f4a2713aSLionel Sambuc
2132f4a2713aSLionel Sambuc // Parse the body of the inferred submodule.
2133f4a2713aSLionel Sambuc bool Done = false;
2134f4a2713aSLionel Sambuc do {
2135f4a2713aSLionel Sambuc switch (Tok.Kind) {
2136f4a2713aSLionel Sambuc case MMToken::EndOfFile:
2137f4a2713aSLionel Sambuc case MMToken::RBrace:
2138f4a2713aSLionel Sambuc Done = true;
2139f4a2713aSLionel Sambuc break;
2140f4a2713aSLionel Sambuc
2141f4a2713aSLionel Sambuc case MMToken::ExcludeKeyword: {
2142f4a2713aSLionel Sambuc if (ActiveModule) {
2143f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2144*0a6a1f1dSLionel Sambuc << (ActiveModule != nullptr);
2145f4a2713aSLionel Sambuc consumeToken();
2146f4a2713aSLionel Sambuc break;
2147f4a2713aSLionel Sambuc }
2148f4a2713aSLionel Sambuc
2149f4a2713aSLionel Sambuc consumeToken();
2150*0a6a1f1dSLionel Sambuc // FIXME: Support string-literal module names here.
2151f4a2713aSLionel Sambuc if (!Tok.is(MMToken::Identifier)) {
2152f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
2153f4a2713aSLionel Sambuc break;
2154f4a2713aSLionel Sambuc }
2155f4a2713aSLionel Sambuc
2156f4a2713aSLionel Sambuc Map.InferredDirectories[Directory].ExcludedModules
2157f4a2713aSLionel Sambuc .push_back(Tok.getString());
2158f4a2713aSLionel Sambuc consumeToken();
2159f4a2713aSLionel Sambuc break;
2160f4a2713aSLionel Sambuc }
2161f4a2713aSLionel Sambuc
2162f4a2713aSLionel Sambuc case MMToken::ExportKeyword:
2163f4a2713aSLionel Sambuc if (!ActiveModule) {
2164f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2165*0a6a1f1dSLionel Sambuc << (ActiveModule != nullptr);
2166f4a2713aSLionel Sambuc consumeToken();
2167f4a2713aSLionel Sambuc break;
2168f4a2713aSLionel Sambuc }
2169f4a2713aSLionel Sambuc
2170f4a2713aSLionel Sambuc consumeToken();
2171f4a2713aSLionel Sambuc if (Tok.is(MMToken::Star))
2172f4a2713aSLionel Sambuc ActiveModule->InferExportWildcard = true;
2173f4a2713aSLionel Sambuc else
2174f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(),
2175f4a2713aSLionel Sambuc diag::err_mmap_expected_export_wildcard);
2176f4a2713aSLionel Sambuc consumeToken();
2177f4a2713aSLionel Sambuc break;
2178f4a2713aSLionel Sambuc
2179f4a2713aSLionel Sambuc case MMToken::ExplicitKeyword:
2180f4a2713aSLionel Sambuc case MMToken::ModuleKeyword:
2181f4a2713aSLionel Sambuc case MMToken::HeaderKeyword:
2182f4a2713aSLionel Sambuc case MMToken::PrivateKeyword:
2183f4a2713aSLionel Sambuc case MMToken::UmbrellaKeyword:
2184f4a2713aSLionel Sambuc default:
2185f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
2186*0a6a1f1dSLionel Sambuc << (ActiveModule != nullptr);
2187f4a2713aSLionel Sambuc consumeToken();
2188f4a2713aSLionel Sambuc break;
2189f4a2713aSLionel Sambuc }
2190f4a2713aSLionel Sambuc } while (!Done);
2191f4a2713aSLionel Sambuc
2192f4a2713aSLionel Sambuc if (Tok.is(MMToken::RBrace))
2193f4a2713aSLionel Sambuc consumeToken();
2194f4a2713aSLionel Sambuc else {
2195f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
2196f4a2713aSLionel Sambuc Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
2197f4a2713aSLionel Sambuc HadError = true;
2198f4a2713aSLionel Sambuc }
2199f4a2713aSLionel Sambuc }
2200f4a2713aSLionel Sambuc
2201f4a2713aSLionel Sambuc /// \brief Parse optional attributes.
2202f4a2713aSLionel Sambuc ///
2203f4a2713aSLionel Sambuc /// attributes:
2204f4a2713aSLionel Sambuc /// attribute attributes
2205f4a2713aSLionel Sambuc /// attribute
2206f4a2713aSLionel Sambuc ///
2207f4a2713aSLionel Sambuc /// attribute:
2208f4a2713aSLionel Sambuc /// [ identifier ]
2209f4a2713aSLionel Sambuc ///
2210f4a2713aSLionel Sambuc /// \param Attrs Will be filled in with the parsed attributes.
2211f4a2713aSLionel Sambuc ///
2212f4a2713aSLionel Sambuc /// \returns true if an error occurred, false otherwise.
parseOptionalAttributes(Attributes & Attrs)2213f4a2713aSLionel Sambuc bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
2214f4a2713aSLionel Sambuc bool HadError = false;
2215f4a2713aSLionel Sambuc
2216f4a2713aSLionel Sambuc while (Tok.is(MMToken::LSquare)) {
2217f4a2713aSLionel Sambuc // Consume the '['.
2218f4a2713aSLionel Sambuc SourceLocation LSquareLoc = consumeToken();
2219f4a2713aSLionel Sambuc
2220f4a2713aSLionel Sambuc // Check whether we have an attribute name here.
2221f4a2713aSLionel Sambuc if (!Tok.is(MMToken::Identifier)) {
2222f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
2223f4a2713aSLionel Sambuc skipUntil(MMToken::RSquare);
2224f4a2713aSLionel Sambuc if (Tok.is(MMToken::RSquare))
2225f4a2713aSLionel Sambuc consumeToken();
2226f4a2713aSLionel Sambuc HadError = true;
2227f4a2713aSLionel Sambuc }
2228f4a2713aSLionel Sambuc
2229f4a2713aSLionel Sambuc // Decode the attribute name.
2230f4a2713aSLionel Sambuc AttributeKind Attribute
2231f4a2713aSLionel Sambuc = llvm::StringSwitch<AttributeKind>(Tok.getString())
2232f4a2713aSLionel Sambuc .Case("exhaustive", AT_exhaustive)
2233*0a6a1f1dSLionel Sambuc .Case("extern_c", AT_extern_c)
2234f4a2713aSLionel Sambuc .Case("system", AT_system)
2235f4a2713aSLionel Sambuc .Default(AT_unknown);
2236f4a2713aSLionel Sambuc switch (Attribute) {
2237f4a2713aSLionel Sambuc case AT_unknown:
2238f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
2239f4a2713aSLionel Sambuc << Tok.getString();
2240f4a2713aSLionel Sambuc break;
2241f4a2713aSLionel Sambuc
2242f4a2713aSLionel Sambuc case AT_system:
2243f4a2713aSLionel Sambuc Attrs.IsSystem = true;
2244f4a2713aSLionel Sambuc break;
2245f4a2713aSLionel Sambuc
2246*0a6a1f1dSLionel Sambuc case AT_extern_c:
2247*0a6a1f1dSLionel Sambuc Attrs.IsExternC = true;
2248*0a6a1f1dSLionel Sambuc break;
2249*0a6a1f1dSLionel Sambuc
2250f4a2713aSLionel Sambuc case AT_exhaustive:
2251f4a2713aSLionel Sambuc Attrs.IsExhaustive = true;
2252f4a2713aSLionel Sambuc break;
2253f4a2713aSLionel Sambuc }
2254f4a2713aSLionel Sambuc consumeToken();
2255f4a2713aSLionel Sambuc
2256f4a2713aSLionel Sambuc // Consume the ']'.
2257f4a2713aSLionel Sambuc if (!Tok.is(MMToken::RSquare)) {
2258f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
2259f4a2713aSLionel Sambuc Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
2260f4a2713aSLionel Sambuc skipUntil(MMToken::RSquare);
2261f4a2713aSLionel Sambuc HadError = true;
2262f4a2713aSLionel Sambuc }
2263f4a2713aSLionel Sambuc
2264f4a2713aSLionel Sambuc if (Tok.is(MMToken::RSquare))
2265f4a2713aSLionel Sambuc consumeToken();
2266f4a2713aSLionel Sambuc }
2267f4a2713aSLionel Sambuc
2268f4a2713aSLionel Sambuc return HadError;
2269f4a2713aSLionel Sambuc }
2270f4a2713aSLionel Sambuc
2271f4a2713aSLionel Sambuc /// \brief Parse a module map file.
2272f4a2713aSLionel Sambuc ///
2273f4a2713aSLionel Sambuc /// module-map-file:
2274f4a2713aSLionel Sambuc /// module-declaration*
parseModuleMapFile()2275f4a2713aSLionel Sambuc bool ModuleMapParser::parseModuleMapFile() {
2276f4a2713aSLionel Sambuc do {
2277f4a2713aSLionel Sambuc switch (Tok.Kind) {
2278f4a2713aSLionel Sambuc case MMToken::EndOfFile:
2279f4a2713aSLionel Sambuc return HadError;
2280f4a2713aSLionel Sambuc
2281f4a2713aSLionel Sambuc case MMToken::ExplicitKeyword:
2282f4a2713aSLionel Sambuc case MMToken::ExternKeyword:
2283f4a2713aSLionel Sambuc case MMToken::ModuleKeyword:
2284f4a2713aSLionel Sambuc case MMToken::FrameworkKeyword:
2285f4a2713aSLionel Sambuc parseModuleDecl();
2286f4a2713aSLionel Sambuc break;
2287f4a2713aSLionel Sambuc
2288f4a2713aSLionel Sambuc case MMToken::Comma:
2289f4a2713aSLionel Sambuc case MMToken::ConfigMacros:
2290f4a2713aSLionel Sambuc case MMToken::Conflict:
2291f4a2713aSLionel Sambuc case MMToken::Exclaim:
2292f4a2713aSLionel Sambuc case MMToken::ExcludeKeyword:
2293f4a2713aSLionel Sambuc case MMToken::ExportKeyword:
2294f4a2713aSLionel Sambuc case MMToken::HeaderKeyword:
2295f4a2713aSLionel Sambuc case MMToken::Identifier:
2296f4a2713aSLionel Sambuc case MMToken::LBrace:
2297f4a2713aSLionel Sambuc case MMToken::LinkKeyword:
2298f4a2713aSLionel Sambuc case MMToken::LSquare:
2299f4a2713aSLionel Sambuc case MMToken::Period:
2300f4a2713aSLionel Sambuc case MMToken::PrivateKeyword:
2301f4a2713aSLionel Sambuc case MMToken::RBrace:
2302f4a2713aSLionel Sambuc case MMToken::RSquare:
2303f4a2713aSLionel Sambuc case MMToken::RequiresKeyword:
2304f4a2713aSLionel Sambuc case MMToken::Star:
2305f4a2713aSLionel Sambuc case MMToken::StringLiteral:
2306*0a6a1f1dSLionel Sambuc case MMToken::TextualKeyword:
2307f4a2713aSLionel Sambuc case MMToken::UmbrellaKeyword:
2308f4a2713aSLionel Sambuc case MMToken::UseKeyword:
2309f4a2713aSLionel Sambuc Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
2310f4a2713aSLionel Sambuc HadError = true;
2311f4a2713aSLionel Sambuc consumeToken();
2312f4a2713aSLionel Sambuc break;
2313f4a2713aSLionel Sambuc }
2314f4a2713aSLionel Sambuc } while (true);
2315f4a2713aSLionel Sambuc }
2316f4a2713aSLionel Sambuc
parseModuleMapFile(const FileEntry * File,bool IsSystem,const DirectoryEntry * Dir)2317*0a6a1f1dSLionel Sambuc bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
2318*0a6a1f1dSLionel Sambuc const DirectoryEntry *Dir) {
2319f4a2713aSLionel Sambuc llvm::DenseMap<const FileEntry *, bool>::iterator Known
2320f4a2713aSLionel Sambuc = ParsedModuleMap.find(File);
2321f4a2713aSLionel Sambuc if (Known != ParsedModuleMap.end())
2322f4a2713aSLionel Sambuc return Known->second;
2323f4a2713aSLionel Sambuc
2324*0a6a1f1dSLionel Sambuc assert(Target && "Missing target information");
2325*0a6a1f1dSLionel Sambuc auto FileCharacter = IsSystem ? SrcMgr::C_System : SrcMgr::C_User;
2326*0a6a1f1dSLionel Sambuc FileID ID = SourceMgr.createFileID(File, SourceLocation(), FileCharacter);
2327f4a2713aSLionel Sambuc const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID);
2328f4a2713aSLionel Sambuc if (!Buffer)
2329f4a2713aSLionel Sambuc return ParsedModuleMap[File] = true;
2330f4a2713aSLionel Sambuc
2331f4a2713aSLionel Sambuc // Parse this module map file.
2332f4a2713aSLionel Sambuc Lexer L(ID, SourceMgr.getBuffer(ID), SourceMgr, MMapLangOpts);
2333*0a6a1f1dSLionel Sambuc ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
2334f4a2713aSLionel Sambuc BuiltinIncludeDir, IsSystem);
2335f4a2713aSLionel Sambuc bool Result = Parser.parseModuleMapFile();
2336f4a2713aSLionel Sambuc ParsedModuleMap[File] = Result;
2337f4a2713aSLionel Sambuc return Result;
2338f4a2713aSLionel Sambuc }
2339