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