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