10b57cec5SDimitry Andric //===- ModuleMap.cpp - Describe the layout of modules ---------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines the ModuleMap implementation, which describes the layout
100b57cec5SDimitry Andric // of a module as it relates to headers.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "clang/Lex/ModuleMap.h"
150b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h"
160b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h"
170b57cec5SDimitry Andric #include "clang/Basic/FileManager.h"
180b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
190b57cec5SDimitry Andric #include "clang/Basic/LangOptions.h"
200b57cec5SDimitry Andric #include "clang/Basic/Module.h"
210b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h"
220b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
230b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h"
240b57cec5SDimitry Andric #include "clang/Lex/HeaderSearch.h"
250b57cec5SDimitry Andric #include "clang/Lex/HeaderSearchOptions.h"
260b57cec5SDimitry Andric #include "clang/Lex/LexDiagnostic.h"
270b57cec5SDimitry Andric #include "clang/Lex/Lexer.h"
280b57cec5SDimitry Andric #include "clang/Lex/LiteralSupport.h"
290b57cec5SDimitry Andric #include "clang/Lex/Token.h"
300b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
310b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
320b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
330b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
340b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
350b57cec5SDimitry Andric #include "llvm/ADT/StringMap.h"
360b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
370b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
380b57cec5SDimitry Andric #include "llvm/Support/Allocator.h"
390b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
400b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
410b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
420b57cec5SDimitry Andric #include "llvm/Support/Path.h"
430b57cec5SDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
440b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
450b57cec5SDimitry Andric #include <algorithm>
460b57cec5SDimitry Andric #include <cassert>
470b57cec5SDimitry Andric #include <cstdint>
480b57cec5SDimitry Andric #include <cstring>
49bdd1243dSDimitry Andric #include <optional>
500b57cec5SDimitry Andric #include <string>
510b57cec5SDimitry Andric #include <system_error>
520b57cec5SDimitry Andric #include <utility>
530b57cec5SDimitry Andric
540b57cec5SDimitry Andric using namespace clang;
550b57cec5SDimitry Andric
anchor()560b57cec5SDimitry Andric void ModuleMapCallbacks::anchor() {}
570b57cec5SDimitry Andric
resolveLinkAsDependencies(Module * Mod)580b57cec5SDimitry Andric void ModuleMap::resolveLinkAsDependencies(Module *Mod) {
590b57cec5SDimitry Andric auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name);
600b57cec5SDimitry Andric if (PendingLinkAs != PendingLinkAsModule.end()) {
610b57cec5SDimitry Andric for (auto &Name : PendingLinkAs->second) {
620b57cec5SDimitry Andric auto *M = findModule(Name.getKey());
630b57cec5SDimitry Andric if (M)
640b57cec5SDimitry Andric M->UseExportAsModuleLinkName = true;
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric
addLinkAsDependency(Module * Mod)690b57cec5SDimitry Andric void ModuleMap::addLinkAsDependency(Module *Mod) {
700b57cec5SDimitry Andric if (findModule(Mod->ExportAsModule))
710b57cec5SDimitry Andric Mod->UseExportAsModuleLinkName = true;
720b57cec5SDimitry Andric else
730b57cec5SDimitry Andric PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name);
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric
headerRoleToKind(ModuleHeaderRole Role)760b57cec5SDimitry Andric Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) {
770b57cec5SDimitry Andric switch ((int)Role) {
780b57cec5SDimitry Andric case NormalHeader:
790b57cec5SDimitry Andric return Module::HK_Normal;
800b57cec5SDimitry Andric case PrivateHeader:
810b57cec5SDimitry Andric return Module::HK_Private;
820b57cec5SDimitry Andric case TextualHeader:
830b57cec5SDimitry Andric return Module::HK_Textual;
840b57cec5SDimitry Andric case PrivateHeader | TextualHeader:
850b57cec5SDimitry Andric return Module::HK_PrivateTextual;
86bdd1243dSDimitry Andric case ExcludedHeader:
87bdd1243dSDimitry Andric return Module::HK_Excluded;
880b57cec5SDimitry Andric }
89bdd1243dSDimitry Andric llvm_unreachable("unknown header role");
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric
920b57cec5SDimitry Andric ModuleMap::ModuleHeaderRole
headerKindToRole(Module::HeaderKind Kind)930b57cec5SDimitry Andric ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
940b57cec5SDimitry Andric switch ((int)Kind) {
950b57cec5SDimitry Andric case Module::HK_Normal:
960b57cec5SDimitry Andric return NormalHeader;
970b57cec5SDimitry Andric case Module::HK_Private:
980b57cec5SDimitry Andric return PrivateHeader;
990b57cec5SDimitry Andric case Module::HK_Textual:
1000b57cec5SDimitry Andric return TextualHeader;
1010b57cec5SDimitry Andric case Module::HK_PrivateTextual:
1020b57cec5SDimitry Andric return ModuleHeaderRole(PrivateHeader | TextualHeader);
1030b57cec5SDimitry Andric case Module::HK_Excluded:
104bdd1243dSDimitry Andric return ExcludedHeader;
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric llvm_unreachable("unknown header kind");
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric
isModular(ModuleHeaderRole Role)109bdd1243dSDimitry Andric bool ModuleMap::isModular(ModuleHeaderRole Role) {
110bdd1243dSDimitry Andric return !(Role & (ModuleMap::TextualHeader | ModuleMap::ExcludedHeader));
111bdd1243dSDimitry Andric }
112bdd1243dSDimitry Andric
1130b57cec5SDimitry Andric Module::ExportDecl
resolveExport(Module * Mod,const Module::UnresolvedExportDecl & Unresolved,bool Complain) const1140b57cec5SDimitry Andric ModuleMap::resolveExport(Module *Mod,
1150b57cec5SDimitry Andric const Module::UnresolvedExportDecl &Unresolved,
1160b57cec5SDimitry Andric bool Complain) const {
1170b57cec5SDimitry Andric // We may have just a wildcard.
1180b57cec5SDimitry Andric if (Unresolved.Id.empty()) {
1190b57cec5SDimitry Andric assert(Unresolved.Wildcard && "Invalid unresolved export");
1200b57cec5SDimitry Andric return Module::ExportDecl(nullptr, true);
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric
1230b57cec5SDimitry Andric // Resolve the module-id.
1240b57cec5SDimitry Andric Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
1250b57cec5SDimitry Andric if (!Context)
1260b57cec5SDimitry Andric return {};
1270b57cec5SDimitry Andric
1280b57cec5SDimitry Andric return Module::ExportDecl(Context, Unresolved.Wildcard);
1290b57cec5SDimitry Andric }
1300b57cec5SDimitry Andric
resolveModuleId(const ModuleId & Id,Module * Mod,bool Complain) const1310b57cec5SDimitry Andric Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
1320b57cec5SDimitry Andric bool Complain) const {
1330b57cec5SDimitry Andric // Find the starting module.
1340b57cec5SDimitry Andric Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
1350b57cec5SDimitry Andric if (!Context) {
1360b57cec5SDimitry Andric if (Complain)
1370b57cec5SDimitry Andric Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
1380b57cec5SDimitry Andric << Id[0].first << Mod->getFullModuleName();
1390b57cec5SDimitry Andric
1400b57cec5SDimitry Andric return nullptr;
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric
1430b57cec5SDimitry Andric // Dig into the module path.
1440b57cec5SDimitry Andric for (unsigned I = 1, N = Id.size(); I != N; ++I) {
1450b57cec5SDimitry Andric Module *Sub = lookupModuleQualified(Id[I].first, Context);
1460b57cec5SDimitry Andric if (!Sub) {
1470b57cec5SDimitry Andric if (Complain)
1480b57cec5SDimitry Andric Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
1490b57cec5SDimitry Andric << Id[I].first << Context->getFullModuleName()
1500b57cec5SDimitry Andric << SourceRange(Id[0].second, Id[I-1].second);
1510b57cec5SDimitry Andric
1520b57cec5SDimitry Andric return nullptr;
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric
1550b57cec5SDimitry Andric Context = Sub;
1560b57cec5SDimitry Andric }
1570b57cec5SDimitry Andric
1580b57cec5SDimitry Andric return Context;
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric
1610b57cec5SDimitry Andric /// Append to \p Paths the set of paths needed to get to the
1620b57cec5SDimitry Andric /// subframework in which the given module lives.
appendSubframeworkPaths(Module * Mod,SmallVectorImpl<char> & Path)1630b57cec5SDimitry Andric static void appendSubframeworkPaths(Module *Mod,
1640b57cec5SDimitry Andric SmallVectorImpl<char> &Path) {
1650b57cec5SDimitry Andric // Collect the framework names from the given module to the top-level module.
1660b57cec5SDimitry Andric SmallVector<StringRef, 2> Paths;
1670b57cec5SDimitry Andric for (; Mod; Mod = Mod->Parent) {
1680b57cec5SDimitry Andric if (Mod->IsFramework)
1690b57cec5SDimitry Andric Paths.push_back(Mod->Name);
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric
1720b57cec5SDimitry Andric if (Paths.empty())
1730b57cec5SDimitry Andric return;
1740b57cec5SDimitry Andric
1750b57cec5SDimitry Andric // Add Frameworks/Name.framework for each subframework.
176349cc55cSDimitry Andric for (StringRef Framework : llvm::drop_begin(llvm::reverse(Paths)))
177349cc55cSDimitry Andric llvm::sys::path::append(Path, "Frameworks", Framework + ".framework");
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric
findHeader(Module * M,const Module::UnresolvedHeaderDirective & Header,SmallVectorImpl<char> & RelativePathName,bool & NeedsFramework)180bdd1243dSDimitry Andric OptionalFileEntryRef ModuleMap::findHeader(
1810b57cec5SDimitry Andric Module *M, const Module::UnresolvedHeaderDirective &Header,
1820b57cec5SDimitry Andric SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) {
1830b57cec5SDimitry Andric // Search for the header file within the module's home directory.
184fe013be4SDimitry Andric auto Directory = M->Directory;
1850b57cec5SDimitry Andric SmallString<128> FullPathName(Directory->getName());
1860b57cec5SDimitry Andric
187bdd1243dSDimitry Andric auto GetFile = [&](StringRef Filename) -> OptionalFileEntryRef {
188e8d8bef9SDimitry Andric auto File =
189e8d8bef9SDimitry Andric expectedToOptional(SourceMgr.getFileManager().getFileRef(Filename));
190e8d8bef9SDimitry Andric if (!File || (Header.Size && File->getSize() != *Header.Size) ||
191e8d8bef9SDimitry Andric (Header.ModTime && File->getModificationTime() != *Header.ModTime))
192bdd1243dSDimitry Andric return std::nullopt;
193a7dea167SDimitry Andric return *File;
1940b57cec5SDimitry Andric };
1950b57cec5SDimitry Andric
196bdd1243dSDimitry Andric auto GetFrameworkFile = [&]() -> OptionalFileEntryRef {
1970b57cec5SDimitry Andric unsigned FullPathLength = FullPathName.size();
1980b57cec5SDimitry Andric appendSubframeworkPaths(M, RelativePathName);
1990b57cec5SDimitry Andric unsigned RelativePathLength = RelativePathName.size();
2000b57cec5SDimitry Andric
2010b57cec5SDimitry Andric // Check whether this file is in the public headers.
2020b57cec5SDimitry Andric llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
2030b57cec5SDimitry Andric llvm::sys::path::append(FullPathName, RelativePathName);
204e8d8bef9SDimitry Andric if (auto File = GetFile(FullPathName))
2050b57cec5SDimitry Andric return File;
2060b57cec5SDimitry Andric
2070b57cec5SDimitry Andric // Check whether this file is in the private headers.
2080b57cec5SDimitry Andric // Ideally, private modules in the form 'FrameworkName.Private' should
2090b57cec5SDimitry Andric // be defined as 'module FrameworkName.Private', and not as
2100b57cec5SDimitry Andric // 'framework module FrameworkName.Private', since a 'Private.Framework'
2110b57cec5SDimitry Andric // does not usually exist. However, since both are currently widely used
2120b57cec5SDimitry Andric // for private modules, make sure we find the right path in both cases.
2130b57cec5SDimitry Andric if (M->IsFramework && M->Name == "Private")
2140b57cec5SDimitry Andric RelativePathName.clear();
2150b57cec5SDimitry Andric else
2160b57cec5SDimitry Andric RelativePathName.resize(RelativePathLength);
2170b57cec5SDimitry Andric FullPathName.resize(FullPathLength);
2180b57cec5SDimitry Andric llvm::sys::path::append(RelativePathName, "PrivateHeaders",
2190b57cec5SDimitry Andric Header.FileName);
2200b57cec5SDimitry Andric llvm::sys::path::append(FullPathName, RelativePathName);
2210b57cec5SDimitry Andric return GetFile(FullPathName);
2220b57cec5SDimitry Andric };
2230b57cec5SDimitry Andric
2240b57cec5SDimitry Andric if (llvm::sys::path::is_absolute(Header.FileName)) {
2250b57cec5SDimitry Andric RelativePathName.clear();
2260b57cec5SDimitry Andric RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
2270b57cec5SDimitry Andric return GetFile(Header.FileName);
2280b57cec5SDimitry Andric }
2290b57cec5SDimitry Andric
2300b57cec5SDimitry Andric if (M->isPartOfFramework())
2310b57cec5SDimitry Andric return GetFrameworkFile();
2320b57cec5SDimitry Andric
2330b57cec5SDimitry Andric // Lookup for normal headers.
2340b57cec5SDimitry Andric llvm::sys::path::append(RelativePathName, Header.FileName);
2350b57cec5SDimitry Andric llvm::sys::path::append(FullPathName, RelativePathName);
236e8d8bef9SDimitry Andric auto NormalHdrFile = GetFile(FullPathName);
2370b57cec5SDimitry Andric
238c9157d92SDimitry Andric if (!NormalHdrFile && Directory->getName().ends_with(".framework")) {
2390b57cec5SDimitry Andric // The lack of 'framework' keyword in a module declaration it's a simple
2400b57cec5SDimitry Andric // mistake we can diagnose when the header exists within the proper
2410b57cec5SDimitry Andric // framework style path.
2420b57cec5SDimitry Andric FullPathName.assign(Directory->getName());
2430b57cec5SDimitry Andric RelativePathName.clear();
2440b57cec5SDimitry Andric if (GetFrameworkFile()) {
2450b57cec5SDimitry Andric Diags.Report(Header.FileNameLoc,
2460b57cec5SDimitry Andric diag::warn_mmap_incomplete_framework_module_declaration)
2470b57cec5SDimitry Andric << Header.FileName << M->getFullModuleName();
2480b57cec5SDimitry Andric NeedsFramework = true;
2490b57cec5SDimitry Andric }
250bdd1243dSDimitry Andric return std::nullopt;
2510b57cec5SDimitry Andric }
2520b57cec5SDimitry Andric
2530b57cec5SDimitry Andric return NormalHdrFile;
2540b57cec5SDimitry Andric }
2550b57cec5SDimitry Andric
256c9157d92SDimitry Andric /// Determine whether the given file name is the name of a builtin
257c9157d92SDimitry Andric /// header, supplied by Clang to replace, override, or augment existing system
258c9157d92SDimitry Andric /// headers.
isBuiltinHeaderName(StringRef FileName)259c9157d92SDimitry Andric static bool isBuiltinHeaderName(StringRef FileName) {
260c9157d92SDimitry Andric return llvm::StringSwitch<bool>(FileName)
261c9157d92SDimitry Andric .Case("float.h", true)
262c9157d92SDimitry Andric .Case("iso646.h", true)
263c9157d92SDimitry Andric .Case("limits.h", true)
264c9157d92SDimitry Andric .Case("stdalign.h", true)
265c9157d92SDimitry Andric .Case("stdarg.h", true)
266c9157d92SDimitry Andric .Case("stdatomic.h", true)
267c9157d92SDimitry Andric .Case("stdbool.h", true)
268c9157d92SDimitry Andric .Case("stddef.h", true)
269c9157d92SDimitry Andric .Case("stdint.h", true)
270c9157d92SDimitry Andric .Case("tgmath.h", true)
271c9157d92SDimitry Andric .Case("unwind.h", true)
272c9157d92SDimitry Andric .Default(false);
273c9157d92SDimitry Andric }
274c9157d92SDimitry Andric
275c9157d92SDimitry Andric /// Determine whether the given module name is the name of a builtin
276c9157d92SDimitry Andric /// module that is cyclic with a system module on some platforms.
isBuiltInModuleName(StringRef ModuleName)277c9157d92SDimitry Andric static bool isBuiltInModuleName(StringRef ModuleName) {
278c9157d92SDimitry Andric return llvm::StringSwitch<bool>(ModuleName)
279c9157d92SDimitry Andric .Case("_Builtin_float", true)
280c9157d92SDimitry Andric .Case("_Builtin_inttypes", true)
281c9157d92SDimitry Andric .Case("_Builtin_iso646", true)
282c9157d92SDimitry Andric .Case("_Builtin_limits", true)
283c9157d92SDimitry Andric .Case("_Builtin_stdalign", true)
284c9157d92SDimitry Andric .Case("_Builtin_stdarg", true)
285c9157d92SDimitry Andric .Case("_Builtin_stdatomic", true)
286c9157d92SDimitry Andric .Case("_Builtin_stdbool", true)
287c9157d92SDimitry Andric .Case("_Builtin_stddef", true)
288c9157d92SDimitry Andric .Case("_Builtin_stdint", true)
289c9157d92SDimitry Andric .Case("_Builtin_stdnoreturn", true)
290c9157d92SDimitry Andric .Case("_Builtin_tgmath", true)
291c9157d92SDimitry Andric .Case("_Builtin_unwind", true)
292c9157d92SDimitry Andric .Default(false);
293c9157d92SDimitry Andric }
294c9157d92SDimitry Andric
resolveHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header,bool & NeedsFramework)2950b57cec5SDimitry Andric void ModuleMap::resolveHeader(Module *Mod,
2960b57cec5SDimitry Andric const Module::UnresolvedHeaderDirective &Header,
2970b57cec5SDimitry Andric bool &NeedsFramework) {
2980b57cec5SDimitry Andric SmallString<128> RelativePathName;
299bdd1243dSDimitry Andric if (OptionalFileEntryRef File =
3000b57cec5SDimitry Andric findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
3010b57cec5SDimitry Andric if (Header.IsUmbrella) {
302e8d8bef9SDimitry Andric const DirectoryEntry *UmbrellaDir = &File->getDir().getDirEntry();
3030b57cec5SDimitry Andric if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
3040b57cec5SDimitry Andric Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
3050b57cec5SDimitry Andric << UmbrellaMod->getFullModuleName();
3060b57cec5SDimitry Andric else
3070b57cec5SDimitry Andric // Record this umbrella header.
308fe013be4SDimitry Andric setUmbrellaHeaderAsWritten(Mod, *File, Header.FileName,
309fe013be4SDimitry Andric RelativePathName.str());
3100b57cec5SDimitry Andric } else {
311a58f00eaSDimitry Andric Module::Header H = {Header.FileName, std::string(RelativePathName),
312fe6060f1SDimitry Andric *File};
3130b57cec5SDimitry Andric addHeader(Mod, H, headerKindToRole(Header.Kind));
3140b57cec5SDimitry Andric }
3150b57cec5SDimitry Andric } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
3160b57cec5SDimitry Andric // There's a builtin header but no corresponding on-disk header. Assume
3170b57cec5SDimitry Andric // this was supposed to modularize the builtin header alone.
3180b57cec5SDimitry Andric } else if (Header.Kind == Module::HK_Excluded) {
3190b57cec5SDimitry Andric // Ignore missing excluded header files. They're optional anyway.
3200b57cec5SDimitry Andric } else {
3210b57cec5SDimitry Andric // If we find a module that has a missing header, we mark this module as
3220b57cec5SDimitry Andric // unavailable and store the header directive for displaying diagnostics.
3230b57cec5SDimitry Andric Mod->MissingHeaders.push_back(Header);
3240b57cec5SDimitry Andric // A missing header with stat information doesn't make the module
3250b57cec5SDimitry Andric // unavailable; this keeps our behavior consistent as headers are lazily
3260b57cec5SDimitry Andric // resolved. (Such a module still can't be built though, except from
3270b57cec5SDimitry Andric // preprocessed source.)
3280b57cec5SDimitry Andric if (!Header.Size && !Header.ModTime)
3295ffd83dbSDimitry Andric Mod->markUnavailable(/*Unimportable=*/false);
3300b57cec5SDimitry Andric }
3310b57cec5SDimitry Andric }
3320b57cec5SDimitry Andric
resolveAsBuiltinHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header)3330b57cec5SDimitry Andric bool ModuleMap::resolveAsBuiltinHeader(
3340b57cec5SDimitry Andric Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
3350b57cec5SDimitry Andric if (Header.Kind == Module::HK_Excluded ||
3360b57cec5SDimitry Andric llvm::sys::path::is_absolute(Header.FileName) ||
3370b57cec5SDimitry Andric Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
3380b57cec5SDimitry Andric !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
339c9157d92SDimitry Andric !LangOpts.BuiltinHeadersInSystemModules || !isBuiltinHeaderName(Header.FileName))
3400b57cec5SDimitry Andric return false;
3410b57cec5SDimitry Andric
3420b57cec5SDimitry Andric // This is a system module with a top-level header. This header
3430b57cec5SDimitry Andric // may have a counterpart (or replacement) in the set of headers
3440b57cec5SDimitry Andric // supplied by Clang. Find that builtin header.
3450b57cec5SDimitry Andric SmallString<128> Path;
3460b57cec5SDimitry Andric llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
347bdd1243dSDimitry Andric auto File = SourceMgr.getFileManager().getOptionalFileRef(Path);
3480b57cec5SDimitry Andric if (!File)
3490b57cec5SDimitry Andric return false;
3500b57cec5SDimitry Andric
351c9157d92SDimitry Andric Module::Header H = {Header.FileName, Header.FileName, *File};
3520b57cec5SDimitry Andric auto Role = headerKindToRole(Header.Kind);
3530b57cec5SDimitry Andric addHeader(Mod, H, Role);
3540b57cec5SDimitry Andric return true;
3550b57cec5SDimitry Andric }
3560b57cec5SDimitry Andric
ModuleMap(SourceManager & SourceMgr,DiagnosticsEngine & Diags,const LangOptions & LangOpts,const TargetInfo * Target,HeaderSearch & HeaderInfo)3570b57cec5SDimitry Andric ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
3580b57cec5SDimitry Andric const LangOptions &LangOpts, const TargetInfo *Target,
3590b57cec5SDimitry Andric HeaderSearch &HeaderInfo)
3600b57cec5SDimitry Andric : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
3610b57cec5SDimitry Andric HeaderInfo(HeaderInfo) {
3620b57cec5SDimitry Andric MMapLangOpts.LineComment = true;
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric
~ModuleMap()3650b57cec5SDimitry Andric ModuleMap::~ModuleMap() {
3660b57cec5SDimitry Andric for (auto &M : Modules)
3670b57cec5SDimitry Andric delete M.getValue();
3680b57cec5SDimitry Andric for (auto *M : ShadowModules)
3690b57cec5SDimitry Andric delete M;
3700b57cec5SDimitry Andric }
3710b57cec5SDimitry Andric
setTarget(const TargetInfo & Target)3720b57cec5SDimitry Andric void ModuleMap::setTarget(const TargetInfo &Target) {
3730b57cec5SDimitry Andric assert((!this->Target || this->Target == &Target) &&
3740b57cec5SDimitry Andric "Improper target override");
3750b57cec5SDimitry Andric this->Target = &Target;
3760b57cec5SDimitry Andric }
3770b57cec5SDimitry Andric
3780b57cec5SDimitry Andric /// "Sanitize" a filename so that it can be used as an identifier.
sanitizeFilenameAsIdentifier(StringRef Name,SmallVectorImpl<char> & Buffer)3790b57cec5SDimitry Andric static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
3800b57cec5SDimitry Andric SmallVectorImpl<char> &Buffer) {
3810b57cec5SDimitry Andric if (Name.empty())
3820b57cec5SDimitry Andric return Name;
3830b57cec5SDimitry Andric
384349cc55cSDimitry Andric if (!isValidAsciiIdentifier(Name)) {
3850b57cec5SDimitry Andric // If we don't already have something with the form of an identifier,
3860b57cec5SDimitry Andric // create a buffer with the sanitized name.
3870b57cec5SDimitry Andric Buffer.clear();
3880b57cec5SDimitry Andric if (isDigit(Name[0]))
3890b57cec5SDimitry Andric Buffer.push_back('_');
3900b57cec5SDimitry Andric Buffer.reserve(Buffer.size() + Name.size());
3910b57cec5SDimitry Andric for (unsigned I = 0, N = Name.size(); I != N; ++I) {
392349cc55cSDimitry Andric if (isAsciiIdentifierContinue(Name[I]))
3930b57cec5SDimitry Andric Buffer.push_back(Name[I]);
3940b57cec5SDimitry Andric else
3950b57cec5SDimitry Andric Buffer.push_back('_');
3960b57cec5SDimitry Andric }
3970b57cec5SDimitry Andric
3980b57cec5SDimitry Andric Name = StringRef(Buffer.data(), Buffer.size());
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric
4010b57cec5SDimitry Andric while (llvm::StringSwitch<bool>(Name)
4020b57cec5SDimitry Andric #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
4030b57cec5SDimitry Andric #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
4040b57cec5SDimitry Andric #include "clang/Basic/TokenKinds.def"
4050b57cec5SDimitry Andric .Default(false)) {
4060b57cec5SDimitry Andric if (Name.data() != Buffer.data())
4070b57cec5SDimitry Andric Buffer.append(Name.begin(), Name.end());
4080b57cec5SDimitry Andric Buffer.push_back('_');
4090b57cec5SDimitry Andric Name = StringRef(Buffer.data(), Buffer.size());
4100b57cec5SDimitry Andric }
4110b57cec5SDimitry Andric
4120b57cec5SDimitry Andric return Name;
4130b57cec5SDimitry Andric }
4140b57cec5SDimitry Andric
isBuiltinHeader(FileEntryRef File)415c9157d92SDimitry Andric bool ModuleMap::isBuiltinHeader(FileEntryRef File) {
416c9157d92SDimitry Andric return File.getDir() == BuiltinIncludeDir && LangOpts.BuiltinHeadersInSystemModules &&
417c9157d92SDimitry Andric isBuiltinHeaderName(llvm::sys::path::filename(File.getName()));
4180b57cec5SDimitry Andric }
4190b57cec5SDimitry Andric
shouldImportRelativeToBuiltinIncludeDir(StringRef FileName,Module * Module) const420c9157d92SDimitry Andric bool ModuleMap::shouldImportRelativeToBuiltinIncludeDir(StringRef FileName,
421c9157d92SDimitry Andric Module *Module) const {
422c9157d92SDimitry Andric return LangOpts.BuiltinHeadersInSystemModules && BuiltinIncludeDir &&
423c9157d92SDimitry Andric Module->IsSystem && !Module->isPartOfFramework() &&
424c9157d92SDimitry Andric isBuiltinHeaderName(FileName);
4255ffd83dbSDimitry Andric }
4265ffd83dbSDimitry Andric
findKnownHeader(FileEntryRef File)427c9157d92SDimitry Andric ModuleMap::HeadersMap::iterator ModuleMap::findKnownHeader(FileEntryRef File) {
4280b57cec5SDimitry Andric resolveHeaderDirectives(File);
4290b57cec5SDimitry Andric HeadersMap::iterator Known = Headers.find(File);
4300b57cec5SDimitry Andric if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
4315ffd83dbSDimitry Andric Known == Headers.end() && ModuleMap::isBuiltinHeader(File)) {
4320b57cec5SDimitry Andric HeaderInfo.loadTopLevelSystemModules();
4330b57cec5SDimitry Andric return Headers.find(File);
4340b57cec5SDimitry Andric }
4350b57cec5SDimitry Andric return Known;
4360b57cec5SDimitry Andric }
4370b57cec5SDimitry Andric
findHeaderInUmbrellaDirs(FileEntryRef File,SmallVectorImpl<DirectoryEntryRef> & IntermediateDirs)438fe013be4SDimitry Andric ModuleMap::KnownHeader ModuleMap::findHeaderInUmbrellaDirs(
439fe013be4SDimitry Andric FileEntryRef File, SmallVectorImpl<DirectoryEntryRef> &IntermediateDirs) {
4400b57cec5SDimitry Andric if (UmbrellaDirs.empty())
4410b57cec5SDimitry Andric return {};
4420b57cec5SDimitry Andric
443fe013be4SDimitry Andric OptionalDirectoryEntryRef Dir = File.getDir();
4440b57cec5SDimitry Andric
4450b57cec5SDimitry Andric // Note: as an egregious but useful hack we use the real path here, because
4460b57cec5SDimitry Andric // frameworks moving from top-level frameworks to embedded frameworks tend
4470b57cec5SDimitry Andric // to be symlinked from the top-level location to the embedded location,
4480b57cec5SDimitry Andric // and we need to resolve lookups as if we had found the embedded location.
449fe013be4SDimitry Andric StringRef DirName = SourceMgr.getFileManager().getCanonicalName(*Dir);
4500b57cec5SDimitry Andric
4510b57cec5SDimitry Andric // Keep walking up the directory hierarchy, looking for a directory with
4520b57cec5SDimitry Andric // an umbrella header.
4530b57cec5SDimitry Andric do {
454fe013be4SDimitry Andric auto KnownDir = UmbrellaDirs.find(*Dir);
4550b57cec5SDimitry Andric if (KnownDir != UmbrellaDirs.end())
4560b57cec5SDimitry Andric return KnownHeader(KnownDir->second, NormalHeader);
4570b57cec5SDimitry Andric
458fe013be4SDimitry Andric IntermediateDirs.push_back(*Dir);
4590b57cec5SDimitry Andric
4600b57cec5SDimitry Andric // Retrieve our parent path.
4610b57cec5SDimitry Andric DirName = llvm::sys::path::parent_path(DirName);
4620b57cec5SDimitry Andric if (DirName.empty())
4630b57cec5SDimitry Andric break;
4640b57cec5SDimitry Andric
4650b57cec5SDimitry Andric // Resolve the parent path to a directory entry.
466fe013be4SDimitry Andric Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
4670b57cec5SDimitry Andric } while (Dir);
4680b57cec5SDimitry Andric return {};
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric
violatesPrivateInclude(Module * RequestingModule,const FileEntry * IncFileEnt,ModuleMap::KnownHeader Header)4710b57cec5SDimitry Andric static bool violatesPrivateInclude(Module *RequestingModule,
4720b57cec5SDimitry Andric const FileEntry *IncFileEnt,
4730b57cec5SDimitry Andric ModuleMap::KnownHeader Header) {
4740b57cec5SDimitry Andric #ifndef NDEBUG
4750b57cec5SDimitry Andric if (Header.getRole() & ModuleMap::PrivateHeader) {
4760b57cec5SDimitry Andric // Check for consistency between the module header role
4770b57cec5SDimitry Andric // as obtained from the lookup and as obtained from the module.
4780b57cec5SDimitry Andric // This check is not cheap, so enable it only for debugging.
4790b57cec5SDimitry Andric bool IsPrivate = false;
4800b57cec5SDimitry Andric SmallVectorImpl<Module::Header> *HeaderList[] = {
4810b57cec5SDimitry Andric &Header.getModule()->Headers[Module::HK_Private],
4820b57cec5SDimitry Andric &Header.getModule()->Headers[Module::HK_PrivateTextual]};
4830b57cec5SDimitry Andric for (auto *Hs : HeaderList)
484fcaf7f86SDimitry Andric IsPrivate |= llvm::any_of(
485fcaf7f86SDimitry Andric *Hs, [&](const Module::Header &H) { return H.Entry == IncFileEnt; });
4860b57cec5SDimitry Andric assert(IsPrivate && "inconsistent headers and roles");
4870b57cec5SDimitry Andric }
4880b57cec5SDimitry Andric #endif
4890b57cec5SDimitry Andric return !Header.isAccessibleFrom(RequestingModule);
4900b57cec5SDimitry Andric }
4910b57cec5SDimitry Andric
getTopLevelOrNull(Module * M)4920b57cec5SDimitry Andric static Module *getTopLevelOrNull(Module *M) {
4930b57cec5SDimitry Andric return M ? M->getTopLevelModule() : nullptr;
4940b57cec5SDimitry Andric }
4950b57cec5SDimitry Andric
diagnoseHeaderInclusion(Module * RequestingModule,bool RequestingModuleIsModuleInterface,SourceLocation FilenameLoc,StringRef Filename,FileEntryRef File)4960b57cec5SDimitry Andric void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
4970b57cec5SDimitry Andric bool RequestingModuleIsModuleInterface,
4980b57cec5SDimitry Andric SourceLocation FilenameLoc,
49981ad6265SDimitry Andric StringRef Filename, FileEntryRef File) {
5000b57cec5SDimitry Andric // No errors for indirect modules. This may be a bit of a problem for modules
5010b57cec5SDimitry Andric // with no source files.
5020b57cec5SDimitry Andric if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
5030b57cec5SDimitry Andric return;
5040b57cec5SDimitry Andric
5050b57cec5SDimitry Andric if (RequestingModule) {
5060b57cec5SDimitry Andric resolveUses(RequestingModule, /*Complain=*/false);
507bdd1243dSDimitry Andric resolveHeaderDirectives(RequestingModule, /*File=*/std::nullopt);
5080b57cec5SDimitry Andric }
5090b57cec5SDimitry Andric
5100b57cec5SDimitry Andric bool Excluded = false;
5110b57cec5SDimitry Andric Module *Private = nullptr;
5120b57cec5SDimitry Andric Module *NotUsed = nullptr;
5130b57cec5SDimitry Andric
5140b57cec5SDimitry Andric HeadersMap::iterator Known = findKnownHeader(File);
5150b57cec5SDimitry Andric if (Known != Headers.end()) {
5160b57cec5SDimitry Andric for (const KnownHeader &Header : Known->second) {
517bdd1243dSDimitry Andric // Excluded headers don't really belong to a module.
518bdd1243dSDimitry Andric if (Header.getRole() == ModuleMap::ExcludedHeader) {
519bdd1243dSDimitry Andric Excluded = true;
520bdd1243dSDimitry Andric continue;
521bdd1243dSDimitry Andric }
522bdd1243dSDimitry Andric
5230b57cec5SDimitry Andric // Remember private headers for later printing of a diagnostic.
5240b57cec5SDimitry Andric if (violatesPrivateInclude(RequestingModule, File, Header)) {
5250b57cec5SDimitry Andric Private = Header.getModule();
5260b57cec5SDimitry Andric continue;
5270b57cec5SDimitry Andric }
5280b57cec5SDimitry Andric
5290b57cec5SDimitry Andric // If uses need to be specified explicitly, we are only allowed to return
5300b57cec5SDimitry Andric // modules that are explicitly used by the requesting module.
5310b57cec5SDimitry Andric if (RequestingModule && LangOpts.ModulesDeclUse &&
5320b57cec5SDimitry Andric !RequestingModule->directlyUses(Header.getModule())) {
5330b57cec5SDimitry Andric NotUsed = Header.getModule();
5340b57cec5SDimitry Andric continue;
5350b57cec5SDimitry Andric }
5360b57cec5SDimitry Andric
5370b57cec5SDimitry Andric // We have found a module that we can happily use.
5380b57cec5SDimitry Andric return;
5390b57cec5SDimitry Andric }
5400b57cec5SDimitry Andric
5410b57cec5SDimitry Andric Excluded = true;
5420b57cec5SDimitry Andric }
5430b57cec5SDimitry Andric
5440b57cec5SDimitry Andric // We have found a header, but it is private.
5450b57cec5SDimitry Andric if (Private) {
5460b57cec5SDimitry Andric Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
5470b57cec5SDimitry Andric << Filename;
5480b57cec5SDimitry Andric return;
5490b57cec5SDimitry Andric }
5500b57cec5SDimitry Andric
5510b57cec5SDimitry Andric // We have found a module, but we don't use it.
5520b57cec5SDimitry Andric if (NotUsed) {
553fe013be4SDimitry Andric Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module_indirect)
554fe013be4SDimitry Andric << RequestingModule->getTopLevelModule()->Name << Filename
555fe013be4SDimitry Andric << NotUsed->Name;
5560b57cec5SDimitry Andric return;
5570b57cec5SDimitry Andric }
5580b57cec5SDimitry Andric
5590b57cec5SDimitry Andric if (Excluded || isHeaderInUmbrellaDirs(File))
5600b57cec5SDimitry Andric return;
5610b57cec5SDimitry Andric
5620b57cec5SDimitry Andric // At this point, only non-modular includes remain.
5630b57cec5SDimitry Andric
5640b57cec5SDimitry Andric if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
5650b57cec5SDimitry Andric Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5660b57cec5SDimitry Andric << RequestingModule->getTopLevelModule()->Name << Filename;
5670b57cec5SDimitry Andric } else if (RequestingModule && RequestingModuleIsModuleInterface &&
5680b57cec5SDimitry Andric LangOpts.isCompilingModule()) {
5690b57cec5SDimitry Andric // Do not diagnose when we are not compiling a module.
5700b57cec5SDimitry Andric diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
5710b57cec5SDimitry Andric diag::warn_non_modular_include_in_framework_module :
5720b57cec5SDimitry Andric diag::warn_non_modular_include_in_module;
5730b57cec5SDimitry Andric Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
57481ad6265SDimitry Andric << File.getName();
5750b57cec5SDimitry Andric }
5760b57cec5SDimitry Andric }
5770b57cec5SDimitry Andric
isBetterKnownHeader(const ModuleMap::KnownHeader & New,const ModuleMap::KnownHeader & Old)5780b57cec5SDimitry Andric static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
5790b57cec5SDimitry Andric const ModuleMap::KnownHeader &Old) {
5800b57cec5SDimitry Andric // Prefer available modules.
5815ffd83dbSDimitry Andric // FIXME: Considering whether the module is available rather than merely
5825ffd83dbSDimitry Andric // importable is non-hermetic and can result in surprising behavior for
5835ffd83dbSDimitry Andric // prebuilt modules. Consider only checking for importability here.
5840b57cec5SDimitry Andric if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
5850b57cec5SDimitry Andric return true;
5860b57cec5SDimitry Andric
5870b57cec5SDimitry Andric // Prefer a public header over a private header.
5880b57cec5SDimitry Andric if ((New.getRole() & ModuleMap::PrivateHeader) !=
5890b57cec5SDimitry Andric (Old.getRole() & ModuleMap::PrivateHeader))
5900b57cec5SDimitry Andric return !(New.getRole() & ModuleMap::PrivateHeader);
5910b57cec5SDimitry Andric
5920b57cec5SDimitry Andric // Prefer a non-textual header over a textual header.
5930b57cec5SDimitry Andric if ((New.getRole() & ModuleMap::TextualHeader) !=
5940b57cec5SDimitry Andric (Old.getRole() & ModuleMap::TextualHeader))
5950b57cec5SDimitry Andric return !(New.getRole() & ModuleMap::TextualHeader);
5960b57cec5SDimitry Andric
597bdd1243dSDimitry Andric // Prefer a non-excluded header over an excluded header.
598bdd1243dSDimitry Andric if ((New.getRole() == ModuleMap::ExcludedHeader) !=
599bdd1243dSDimitry Andric (Old.getRole() == ModuleMap::ExcludedHeader))
600bdd1243dSDimitry Andric return New.getRole() != ModuleMap::ExcludedHeader;
601bdd1243dSDimitry Andric
6020b57cec5SDimitry Andric // Don't have a reason to choose between these. Just keep the first one.
6030b57cec5SDimitry Andric return false;
6040b57cec5SDimitry Andric }
6050b57cec5SDimitry Andric
findModuleForHeader(FileEntryRef File,bool AllowTextual,bool AllowExcluded)606fe013be4SDimitry Andric ModuleMap::KnownHeader ModuleMap::findModuleForHeader(FileEntryRef File,
607bdd1243dSDimitry Andric bool AllowTextual,
608bdd1243dSDimitry Andric bool AllowExcluded) {
6090b57cec5SDimitry Andric auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
6100b57cec5SDimitry Andric if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
6110b57cec5SDimitry Andric return {};
6120b57cec5SDimitry Andric return R;
6130b57cec5SDimitry Andric };
6140b57cec5SDimitry Andric
6150b57cec5SDimitry Andric HeadersMap::iterator Known = findKnownHeader(File);
6160b57cec5SDimitry Andric if (Known != Headers.end()) {
6170b57cec5SDimitry Andric ModuleMap::KnownHeader Result;
6180b57cec5SDimitry Andric // Iterate over all modules that 'File' is part of to find the best fit.
6190b57cec5SDimitry Andric for (KnownHeader &H : Known->second) {
620bdd1243dSDimitry Andric // Cannot use a module if the header is excluded in it.
621bdd1243dSDimitry Andric if (!AllowExcluded && H.getRole() == ModuleMap::ExcludedHeader)
622bdd1243dSDimitry Andric continue;
6230b57cec5SDimitry Andric // Prefer a header from the source module over all others.
6240b57cec5SDimitry Andric if (H.getModule()->getTopLevelModule() == SourceModule)
6250b57cec5SDimitry Andric return MakeResult(H);
6260b57cec5SDimitry Andric if (!Result || isBetterKnownHeader(H, Result))
6270b57cec5SDimitry Andric Result = H;
6280b57cec5SDimitry Andric }
6290b57cec5SDimitry Andric return MakeResult(Result);
6300b57cec5SDimitry Andric }
6310b57cec5SDimitry Andric
6320b57cec5SDimitry Andric return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
6330b57cec5SDimitry Andric }
6340b57cec5SDimitry Andric
6350b57cec5SDimitry Andric ModuleMap::KnownHeader
findOrCreateModuleForHeaderInUmbrellaDir(FileEntryRef File)636fe013be4SDimitry Andric ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(FileEntryRef File) {
6370b57cec5SDimitry Andric assert(!Headers.count(File) && "already have a module for this header");
6380b57cec5SDimitry Andric
639fe013be4SDimitry Andric SmallVector<DirectoryEntryRef, 2> SkippedDirs;
6400b57cec5SDimitry Andric KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
6410b57cec5SDimitry Andric if (H) {
6420b57cec5SDimitry Andric Module *Result = H.getModule();
6430b57cec5SDimitry Andric
6440b57cec5SDimitry Andric // Search up the module stack until we find a module with an umbrella
6450b57cec5SDimitry Andric // directory.
6460b57cec5SDimitry Andric Module *UmbrellaModule = Result;
647fe013be4SDimitry Andric while (!UmbrellaModule->getEffectiveUmbrellaDir() && UmbrellaModule->Parent)
6480b57cec5SDimitry Andric UmbrellaModule = UmbrellaModule->Parent;
6490b57cec5SDimitry Andric
6500b57cec5SDimitry Andric if (UmbrellaModule->InferSubmodules) {
651c9157d92SDimitry Andric OptionalFileEntryRef UmbrellaModuleMap =
6520b57cec5SDimitry Andric getModuleMapFileForUniquing(UmbrellaModule);
6530b57cec5SDimitry Andric
6540b57cec5SDimitry Andric // Infer submodules for each of the directories we found between
6550b57cec5SDimitry Andric // the directory of the umbrella header and the directory where
6560b57cec5SDimitry Andric // the actual header is located.
6570b57cec5SDimitry Andric bool Explicit = UmbrellaModule->InferExplicitSubmodules;
6580b57cec5SDimitry Andric
659fe013be4SDimitry Andric for (DirectoryEntryRef SkippedDir : llvm::reverse(SkippedDirs)) {
6600b57cec5SDimitry Andric // Find or create the module that corresponds to this directory name.
6610b57cec5SDimitry Andric SmallString<32> NameBuf;
6620b57cec5SDimitry Andric StringRef Name = sanitizeFilenameAsIdentifier(
663fe013be4SDimitry Andric llvm::sys::path::stem(SkippedDir.getName()), NameBuf);
6640b57cec5SDimitry Andric Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6650b57cec5SDimitry Andric Explicit).first;
6660b57cec5SDimitry Andric InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
6670b57cec5SDimitry Andric Result->IsInferred = true;
6680b57cec5SDimitry Andric
6690b57cec5SDimitry Andric // Associate the module and the directory.
670349cc55cSDimitry Andric UmbrellaDirs[SkippedDir] = Result;
6710b57cec5SDimitry Andric
6720b57cec5SDimitry Andric // If inferred submodules export everything they import, add a
6730b57cec5SDimitry Andric // wildcard to the set of exports.
6740b57cec5SDimitry Andric if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
6750b57cec5SDimitry Andric Result->Exports.push_back(Module::ExportDecl(nullptr, true));
6760b57cec5SDimitry Andric }
6770b57cec5SDimitry Andric
6780b57cec5SDimitry Andric // Infer a submodule with the same name as this header file.
6790b57cec5SDimitry Andric SmallString<32> NameBuf;
6800b57cec5SDimitry Andric StringRef Name = sanitizeFilenameAsIdentifier(
681fe013be4SDimitry Andric llvm::sys::path::stem(File.getName()), NameBuf);
6820b57cec5SDimitry Andric Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6830b57cec5SDimitry Andric Explicit).first;
6840b57cec5SDimitry Andric InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
6850b57cec5SDimitry Andric Result->IsInferred = true;
6860b57cec5SDimitry Andric Result->addTopHeader(File);
6870b57cec5SDimitry Andric
6880b57cec5SDimitry Andric // If inferred submodules export everything they import, add a
6890b57cec5SDimitry Andric // wildcard to the set of exports.
6900b57cec5SDimitry Andric if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
6910b57cec5SDimitry Andric Result->Exports.push_back(Module::ExportDecl(nullptr, true));
6920b57cec5SDimitry Andric } else {
6930b57cec5SDimitry Andric // Record each of the directories we stepped through as being part of
6940b57cec5SDimitry Andric // the module we found, since the umbrella header covers them all.
6950b57cec5SDimitry Andric for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
6960b57cec5SDimitry Andric UmbrellaDirs[SkippedDirs[I]] = Result;
6970b57cec5SDimitry Andric }
6980b57cec5SDimitry Andric
6990b57cec5SDimitry Andric KnownHeader Header(Result, NormalHeader);
7000b57cec5SDimitry Andric Headers[File].push_back(Header);
7010b57cec5SDimitry Andric return Header;
7020b57cec5SDimitry Andric }
7030b57cec5SDimitry Andric
7040b57cec5SDimitry Andric return {};
7050b57cec5SDimitry Andric }
7060b57cec5SDimitry Andric
7070b57cec5SDimitry Andric ArrayRef<ModuleMap::KnownHeader>
findAllModulesForHeader(FileEntryRef File)708fe013be4SDimitry Andric ModuleMap::findAllModulesForHeader(FileEntryRef File) {
7095ffd83dbSDimitry Andric HeadersMap::iterator Known = findKnownHeader(File);
7105ffd83dbSDimitry Andric if (Known != Headers.end())
7115ffd83dbSDimitry Andric return Known->second;
7125ffd83dbSDimitry Andric
7135ffd83dbSDimitry Andric if (findOrCreateModuleForHeaderInUmbrellaDir(File))
7145ffd83dbSDimitry Andric return Headers.find(File)->second;
7155ffd83dbSDimitry Andric
716bdd1243dSDimitry Andric return std::nullopt;
7175ffd83dbSDimitry Andric }
7185ffd83dbSDimitry Andric
7195ffd83dbSDimitry Andric ArrayRef<ModuleMap::KnownHeader>
findResolvedModulesForHeader(FileEntryRef File) const720c9157d92SDimitry Andric ModuleMap::findResolvedModulesForHeader(FileEntryRef File) const {
7215ffd83dbSDimitry Andric // FIXME: Is this necessary?
7220b57cec5SDimitry Andric resolveHeaderDirectives(File);
7230b57cec5SDimitry Andric auto It = Headers.find(File);
7240b57cec5SDimitry Andric if (It == Headers.end())
725bdd1243dSDimitry Andric return std::nullopt;
7260b57cec5SDimitry Andric return It->second;
7270b57cec5SDimitry Andric }
7280b57cec5SDimitry Andric
isHeaderInUnavailableModule(FileEntryRef Header) const729fe013be4SDimitry Andric bool ModuleMap::isHeaderInUnavailableModule(FileEntryRef Header) const {
7300b57cec5SDimitry Andric return isHeaderUnavailableInModule(Header, nullptr);
7310b57cec5SDimitry Andric }
7320b57cec5SDimitry Andric
isHeaderUnavailableInModule(FileEntryRef Header,const Module * RequestingModule) const733fe013be4SDimitry Andric bool ModuleMap::isHeaderUnavailableInModule(
734fe013be4SDimitry Andric FileEntryRef Header, const Module *RequestingModule) const {
7350b57cec5SDimitry Andric resolveHeaderDirectives(Header);
7360b57cec5SDimitry Andric HeadersMap::const_iterator Known = Headers.find(Header);
7370b57cec5SDimitry Andric if (Known != Headers.end()) {
7380b57cec5SDimitry Andric for (SmallVectorImpl<KnownHeader>::const_iterator
7390b57cec5SDimitry Andric I = Known->second.begin(),
7400b57cec5SDimitry Andric E = Known->second.end();
7410b57cec5SDimitry Andric I != E; ++I) {
7420b57cec5SDimitry Andric
743bdd1243dSDimitry Andric if (I->getRole() == ModuleMap::ExcludedHeader)
744bdd1243dSDimitry Andric continue;
745bdd1243dSDimitry Andric
7460b57cec5SDimitry Andric if (I->isAvailable() &&
7470b57cec5SDimitry Andric (!RequestingModule ||
7480b57cec5SDimitry Andric I->getModule()->isSubModuleOf(RequestingModule))) {
7490b57cec5SDimitry Andric // When no requesting module is available, the caller is looking if a
7500b57cec5SDimitry Andric // header is part a module by only looking into the module map. This is
7510b57cec5SDimitry Andric // done by warn_uncovered_module_header checks; don't consider textual
7520b57cec5SDimitry Andric // headers part of it in this mode, otherwise we get misleading warnings
7530b57cec5SDimitry Andric // that a umbrella header is not including a textual header.
7540b57cec5SDimitry Andric if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
7550b57cec5SDimitry Andric continue;
7560b57cec5SDimitry Andric return false;
7570b57cec5SDimitry Andric }
7580b57cec5SDimitry Andric }
7590b57cec5SDimitry Andric return true;
7600b57cec5SDimitry Andric }
7610b57cec5SDimitry Andric
762fe013be4SDimitry Andric OptionalDirectoryEntryRef Dir = Header.getDir();
763fe013be4SDimitry Andric SmallVector<DirectoryEntryRef, 2> SkippedDirs;
7640b57cec5SDimitry Andric StringRef DirName = Dir->getName();
7650b57cec5SDimitry Andric
7660b57cec5SDimitry Andric auto IsUnavailable = [&](const Module *M) {
7670b57cec5SDimitry Andric return !M->isAvailable() && (!RequestingModule ||
7680b57cec5SDimitry Andric M->isSubModuleOf(RequestingModule));
7690b57cec5SDimitry Andric };
7700b57cec5SDimitry Andric
7710b57cec5SDimitry Andric // Keep walking up the directory hierarchy, looking for a directory with
7720b57cec5SDimitry Andric // an umbrella header.
7730b57cec5SDimitry Andric do {
774fe013be4SDimitry Andric auto KnownDir = UmbrellaDirs.find(*Dir);
7750b57cec5SDimitry Andric if (KnownDir != UmbrellaDirs.end()) {
7760b57cec5SDimitry Andric Module *Found = KnownDir->second;
7770b57cec5SDimitry Andric if (IsUnavailable(Found))
7780b57cec5SDimitry Andric return true;
7790b57cec5SDimitry Andric
7800b57cec5SDimitry Andric // Search up the module stack until we find a module with an umbrella
7810b57cec5SDimitry Andric // directory.
7820b57cec5SDimitry Andric Module *UmbrellaModule = Found;
783fe013be4SDimitry Andric while (!UmbrellaModule->getEffectiveUmbrellaDir() &&
784fe013be4SDimitry Andric UmbrellaModule->Parent)
7850b57cec5SDimitry Andric UmbrellaModule = UmbrellaModule->Parent;
7860b57cec5SDimitry Andric
7870b57cec5SDimitry Andric if (UmbrellaModule->InferSubmodules) {
788fe013be4SDimitry Andric for (DirectoryEntryRef SkippedDir : llvm::reverse(SkippedDirs)) {
7890b57cec5SDimitry Andric // Find or create the module that corresponds to this directory name.
7900b57cec5SDimitry Andric SmallString<32> NameBuf;
7910b57cec5SDimitry Andric StringRef Name = sanitizeFilenameAsIdentifier(
792fe013be4SDimitry Andric llvm::sys::path::stem(SkippedDir.getName()), NameBuf);
7930b57cec5SDimitry Andric Found = lookupModuleQualified(Name, Found);
7940b57cec5SDimitry Andric if (!Found)
7950b57cec5SDimitry Andric return false;
7960b57cec5SDimitry Andric if (IsUnavailable(Found))
7970b57cec5SDimitry Andric return true;
7980b57cec5SDimitry Andric }
7990b57cec5SDimitry Andric
8000b57cec5SDimitry Andric // Infer a submodule with the same name as this header file.
8010b57cec5SDimitry Andric SmallString<32> NameBuf;
8020b57cec5SDimitry Andric StringRef Name = sanitizeFilenameAsIdentifier(
803fe013be4SDimitry Andric llvm::sys::path::stem(Header.getName()),
8040b57cec5SDimitry Andric NameBuf);
8050b57cec5SDimitry Andric Found = lookupModuleQualified(Name, Found);
8060b57cec5SDimitry Andric if (!Found)
8070b57cec5SDimitry Andric return false;
8080b57cec5SDimitry Andric }
8090b57cec5SDimitry Andric
8100b57cec5SDimitry Andric return IsUnavailable(Found);
8110b57cec5SDimitry Andric }
8120b57cec5SDimitry Andric
813fe013be4SDimitry Andric SkippedDirs.push_back(*Dir);
8140b57cec5SDimitry Andric
8150b57cec5SDimitry Andric // Retrieve our parent path.
8160b57cec5SDimitry Andric DirName = llvm::sys::path::parent_path(DirName);
8170b57cec5SDimitry Andric if (DirName.empty())
8180b57cec5SDimitry Andric break;
8190b57cec5SDimitry Andric
8200b57cec5SDimitry Andric // Resolve the parent path to a directory entry.
821fe013be4SDimitry Andric Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
8220b57cec5SDimitry Andric } while (Dir);
8230b57cec5SDimitry Andric
8240b57cec5SDimitry Andric return false;
8250b57cec5SDimitry Andric }
8260b57cec5SDimitry Andric
findModule(StringRef Name) const8270b57cec5SDimitry Andric Module *ModuleMap::findModule(StringRef Name) const {
8280b57cec5SDimitry Andric llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
8290b57cec5SDimitry Andric if (Known != Modules.end())
8300b57cec5SDimitry Andric return Known->getValue();
8310b57cec5SDimitry Andric
8320b57cec5SDimitry Andric return nullptr;
8330b57cec5SDimitry Andric }
8340b57cec5SDimitry Andric
lookupModuleUnqualified(StringRef Name,Module * Context) const8350b57cec5SDimitry Andric Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
8360b57cec5SDimitry Andric Module *Context) const {
8370b57cec5SDimitry Andric for(; Context; Context = Context->Parent) {
8380b57cec5SDimitry Andric if (Module *Sub = lookupModuleQualified(Name, Context))
8390b57cec5SDimitry Andric return Sub;
8400b57cec5SDimitry Andric }
8410b57cec5SDimitry Andric
8420b57cec5SDimitry Andric return findModule(Name);
8430b57cec5SDimitry Andric }
8440b57cec5SDimitry Andric
lookupModuleQualified(StringRef Name,Module * Context) const8450b57cec5SDimitry Andric Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
8460b57cec5SDimitry Andric if (!Context)
8470b57cec5SDimitry Andric return findModule(Name);
8480b57cec5SDimitry Andric
8490b57cec5SDimitry Andric return Context->findSubmodule(Name);
8500b57cec5SDimitry Andric }
8510b57cec5SDimitry Andric
findOrCreateModule(StringRef Name,Module * Parent,bool IsFramework,bool IsExplicit)8520b57cec5SDimitry Andric std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
8530b57cec5SDimitry Andric Module *Parent,
8540b57cec5SDimitry Andric bool IsFramework,
8550b57cec5SDimitry Andric bool IsExplicit) {
8560b57cec5SDimitry Andric // Try to find an existing module with this name.
8570b57cec5SDimitry Andric if (Module *Sub = lookupModuleQualified(Name, Parent))
8580b57cec5SDimitry Andric return std::make_pair(Sub, false);
8590b57cec5SDimitry Andric
8600b57cec5SDimitry Andric // Create a new module with this name.
8610b57cec5SDimitry Andric Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
8620b57cec5SDimitry Andric IsExplicit, NumCreatedModules++);
8630b57cec5SDimitry Andric if (!Parent) {
8640b57cec5SDimitry Andric if (LangOpts.CurrentModule == Name)
8650b57cec5SDimitry Andric SourceModule = Result;
8660b57cec5SDimitry Andric Modules[Name] = Result;
8670b57cec5SDimitry Andric ModuleScopeIDs[Result] = CurrentModuleScopeID;
8680b57cec5SDimitry Andric }
8690b57cec5SDimitry Andric return std::make_pair(Result, true);
8700b57cec5SDimitry Andric }
8710b57cec5SDimitry Andric
createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,Module * Parent)8720eae32dcSDimitry Andric Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
8730eae32dcSDimitry Andric Module *Parent) {
8740eae32dcSDimitry Andric auto *Result = new Module("<global>", Loc, Parent, /*IsFramework*/ false,
8750eae32dcSDimitry Andric /*IsExplicit*/ true, NumCreatedModules++);
876fe013be4SDimitry Andric Result->Kind = Module::ExplicitGlobalModuleFragment;
8770eae32dcSDimitry Andric // If the created module isn't owned by a parent, send it to PendingSubmodules
8780eae32dcSDimitry Andric // to wait for its parent.
8790eae32dcSDimitry Andric if (!Result->Parent)
8800eae32dcSDimitry Andric PendingSubmodules.emplace_back(Result);
8810eae32dcSDimitry Andric return Result;
8820b57cec5SDimitry Andric }
8830b57cec5SDimitry Andric
884c9157d92SDimitry Andric Module *
createImplicitGlobalModuleFragmentForModuleUnit(SourceLocation Loc,Module * Parent)885c9157d92SDimitry Andric ModuleMap::createImplicitGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
886c9157d92SDimitry Andric Module *Parent) {
887fe013be4SDimitry Andric assert(Parent && "We should only create an implicit global module fragment "
888fe013be4SDimitry Andric "in a module purview");
889fe013be4SDimitry Andric // Note: Here the `IsExplicit` parameter refers to the semantics in clang
890fe013be4SDimitry Andric // modules. All the non-explicit submodules in clang modules will be exported
891fe013be4SDimitry Andric // too. Here we simplify the implementation by using the concept.
892c9157d92SDimitry Andric auto *Result =
893c9157d92SDimitry Andric new Module("<implicit global>", Loc, Parent, /*IsFramework=*/false,
894c9157d92SDimitry Andric /*IsExplicit=*/false, NumCreatedModules++);
895fe013be4SDimitry Andric Result->Kind = Module::ImplicitGlobalModuleFragment;
896fe013be4SDimitry Andric return Result;
897fe013be4SDimitry Andric }
898fe013be4SDimitry Andric
8990b57cec5SDimitry Andric Module *
createPrivateModuleFragmentForInterfaceUnit(Module * Parent,SourceLocation Loc)9000b57cec5SDimitry Andric ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
9010b57cec5SDimitry Andric SourceLocation Loc) {
9020b57cec5SDimitry Andric auto *Result =
9030b57cec5SDimitry Andric new Module("<private>", Loc, Parent, /*IsFramework*/ false,
9040b57cec5SDimitry Andric /*IsExplicit*/ true, NumCreatedModules++);
9050b57cec5SDimitry Andric Result->Kind = Module::PrivateModuleFragment;
9060b57cec5SDimitry Andric return Result;
9070b57cec5SDimitry Andric }
9080b57cec5SDimitry Andric
createModuleUnitWithKind(SourceLocation Loc,StringRef Name,Module::ModuleKind Kind)909fe013be4SDimitry Andric Module *ModuleMap::createModuleUnitWithKind(SourceLocation Loc, StringRef Name,
910fe013be4SDimitry Andric Module::ModuleKind Kind) {
911fe013be4SDimitry Andric auto *Result =
912fe013be4SDimitry Andric new Module(Name, Loc, nullptr, /*IsFramework*/ false,
913fe013be4SDimitry Andric /*IsExplicit*/ false, NumCreatedModules++);
914fe013be4SDimitry Andric Result->Kind = Kind;
915fe013be4SDimitry Andric
916fe013be4SDimitry Andric // Reparent any current global module fragment as a submodule of this module.
917fe013be4SDimitry Andric for (auto &Submodule : PendingSubmodules) {
918fe013be4SDimitry Andric Submodule->setParent(Result);
919fe013be4SDimitry Andric Submodule.release(); // now owned by parent
920fe013be4SDimitry Andric }
921fe013be4SDimitry Andric PendingSubmodules.clear();
922fe013be4SDimitry Andric return Result;
923fe013be4SDimitry Andric }
924fe013be4SDimitry Andric
createModuleForInterfaceUnit(SourceLocation Loc,StringRef Name)9250b57cec5SDimitry Andric Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
926bdd1243dSDimitry Andric StringRef Name) {
9270b57cec5SDimitry Andric assert(LangOpts.CurrentModule == Name && "module name mismatch");
9280b57cec5SDimitry Andric assert(!Modules[Name] && "redefining existing module");
9290b57cec5SDimitry Andric
9300b57cec5SDimitry Andric auto *Result =
931fe013be4SDimitry Andric createModuleUnitWithKind(Loc, Name, Module::ModuleInterfaceUnit);
9320b57cec5SDimitry Andric Modules[Name] = SourceModule = Result;
9330b57cec5SDimitry Andric
9340b57cec5SDimitry Andric // Mark the main source file as being within the newly-created module so that
9350b57cec5SDimitry Andric // declarations and macros are properly visibility-restricted to it.
936c9157d92SDimitry Andric auto MainFile = SourceMgr.getFileEntryRefForID(SourceMgr.getMainFileID());
9370b57cec5SDimitry Andric assert(MainFile && "no input file for module interface");
938c9157d92SDimitry Andric Headers[*MainFile].push_back(KnownHeader(Result, PrivateHeader));
9390b57cec5SDimitry Andric
9400b57cec5SDimitry Andric return Result;
9410b57cec5SDimitry Andric }
9420b57cec5SDimitry Andric
createModuleForImplementationUnit(SourceLocation Loc,StringRef Name)943fe013be4SDimitry Andric Module *ModuleMap::createModuleForImplementationUnit(SourceLocation Loc,
944fe013be4SDimitry Andric StringRef Name) {
945fe013be4SDimitry Andric assert(LangOpts.CurrentModule == Name && "module name mismatch");
946fe013be4SDimitry Andric // The interface for this implementation must exist and be loaded.
947fe013be4SDimitry Andric assert(Modules[Name] && Modules[Name]->Kind == Module::ModuleInterfaceUnit &&
948fe013be4SDimitry Andric "creating implementation module without an interface");
949fe013be4SDimitry Andric
950fe013be4SDimitry Andric // Create an entry in the modules map to own the implementation unit module.
951fe013be4SDimitry Andric // User module names must not start with a period (so that this cannot clash
952fe013be4SDimitry Andric // with any legal user-defined module name).
953fe013be4SDimitry Andric StringRef IName = ".ImplementationUnit";
954fe013be4SDimitry Andric assert(!Modules[IName] && "multiple implementation units?");
955fe013be4SDimitry Andric
956fe013be4SDimitry Andric auto *Result =
957fe013be4SDimitry Andric createModuleUnitWithKind(Loc, Name, Module::ModuleImplementationUnit);
958fe013be4SDimitry Andric Modules[IName] = SourceModule = Result;
959fe013be4SDimitry Andric
960fe013be4SDimitry Andric // Check that the main file is present.
961fe013be4SDimitry Andric assert(SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()) &&
962fe013be4SDimitry Andric "no input file for module implementation");
963fe013be4SDimitry Andric
964fe013be4SDimitry Andric return Result;
965fe013be4SDimitry Andric }
966fe013be4SDimitry Andric
createHeaderUnit(SourceLocation Loc,StringRef Name,Module::Header H)96781ad6265SDimitry Andric Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name,
96881ad6265SDimitry Andric Module::Header H) {
96981ad6265SDimitry Andric assert(LangOpts.CurrentModule == Name && "module name mismatch");
97081ad6265SDimitry Andric assert(!Modules[Name] && "redefining existing module");
97181ad6265SDimitry Andric
97281ad6265SDimitry Andric auto *Result = new Module(Name, Loc, nullptr, /*IsFramework*/ false,
97381ad6265SDimitry Andric /*IsExplicit*/ false, NumCreatedModules++);
97481ad6265SDimitry Andric Result->Kind = Module::ModuleHeaderUnit;
97581ad6265SDimitry Andric Modules[Name] = SourceModule = Result;
97681ad6265SDimitry Andric addHeader(Result, H, NormalHeader);
97781ad6265SDimitry Andric return Result;
97881ad6265SDimitry Andric }
97981ad6265SDimitry Andric
9800b57cec5SDimitry Andric /// For a framework module, infer the framework against which we
9810b57cec5SDimitry Andric /// should link.
inferFrameworkLink(Module * Mod)982fe013be4SDimitry Andric static void inferFrameworkLink(Module *Mod) {
9830b57cec5SDimitry Andric assert(Mod->IsFramework && "Can only infer linking for framework modules");
9840b57cec5SDimitry Andric assert(!Mod->isSubFramework() &&
9850b57cec5SDimitry Andric "Can only infer linking for top-level frameworks");
9860b57cec5SDimitry Andric
987cdc20ff6SDimitry Andric StringRef FrameworkName(Mod->Name);
988cdc20ff6SDimitry Andric FrameworkName.consume_back("_Private");
989cdc20ff6SDimitry Andric Mod->LinkLibraries.push_back(Module::LinkLibrary(FrameworkName.str(),
9900b57cec5SDimitry Andric /*IsFramework=*/true));
9910b57cec5SDimitry Andric }
9920b57cec5SDimitry Andric
inferFrameworkModule(DirectoryEntryRef FrameworkDir,bool IsSystem,Module * Parent)993fe013be4SDimitry Andric Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
9940b57cec5SDimitry Andric bool IsSystem, Module *Parent) {
9950b57cec5SDimitry Andric Attributes Attrs;
9960b57cec5SDimitry Andric Attrs.IsSystem = IsSystem;
9970b57cec5SDimitry Andric return inferFrameworkModule(FrameworkDir, Attrs, Parent);
9980b57cec5SDimitry Andric }
9990b57cec5SDimitry Andric
inferFrameworkModule(DirectoryEntryRef FrameworkDir,Attributes Attrs,Module * Parent)1000fe013be4SDimitry Andric Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
10010b57cec5SDimitry Andric Attributes Attrs, Module *Parent) {
10020b57cec5SDimitry Andric // Note: as an egregious but useful hack we use the real path here, because
10030b57cec5SDimitry Andric // we might be looking at an embedded framework that symlinks out to a
10040b57cec5SDimitry Andric // top-level framework, and we need to infer as if we were naming the
10050b57cec5SDimitry Andric // top-level framework.
10060b57cec5SDimitry Andric StringRef FrameworkDirName =
10070b57cec5SDimitry Andric SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
10080b57cec5SDimitry Andric
10090b57cec5SDimitry Andric // In case this is a case-insensitive filesystem, use the canonical
10100b57cec5SDimitry Andric // directory name as the ModuleName, since modules are case-sensitive.
10110b57cec5SDimitry Andric // FIXME: we should be able to give a fix-it hint for the correct spelling.
10120b57cec5SDimitry Andric SmallString<32> ModuleNameStorage;
10130b57cec5SDimitry Andric StringRef ModuleName = sanitizeFilenameAsIdentifier(
10140b57cec5SDimitry Andric llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
10150b57cec5SDimitry Andric
10160b57cec5SDimitry Andric // Check whether we've already found this module.
10170b57cec5SDimitry Andric if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
10180b57cec5SDimitry Andric return Mod;
10190b57cec5SDimitry Andric
10200b57cec5SDimitry Andric FileManager &FileMgr = SourceMgr.getFileManager();
10210b57cec5SDimitry Andric
10220b57cec5SDimitry Andric // If the framework has a parent path from which we're allowed to infer
10230b57cec5SDimitry Andric // a framework module, do so.
1024c9157d92SDimitry Andric OptionalFileEntryRef ModuleMapFile;
10250b57cec5SDimitry Andric if (!Parent) {
10260b57cec5SDimitry Andric // Determine whether we're allowed to infer a module map.
10270b57cec5SDimitry Andric bool canInfer = false;
10280b57cec5SDimitry Andric if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
10290b57cec5SDimitry Andric // Figure out the parent path.
10300b57cec5SDimitry Andric StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
1031fe013be4SDimitry Andric if (auto ParentDir = FileMgr.getOptionalDirectoryRef(Parent)) {
10320b57cec5SDimitry Andric // Check whether we have already looked into the parent directory
10330b57cec5SDimitry Andric // for a module map.
10340b57cec5SDimitry Andric llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
1035a7dea167SDimitry Andric inferred = InferredDirectories.find(*ParentDir);
10360b57cec5SDimitry Andric if (inferred == InferredDirectories.end()) {
10370b57cec5SDimitry Andric // We haven't looked here before. Load a module map, if there is
10380b57cec5SDimitry Andric // one.
1039c9157d92SDimitry Andric bool IsFrameworkDir = Parent.ends_with(".framework");
1040fe013be4SDimitry Andric if (OptionalFileEntryRef ModMapFile =
1041a7dea167SDimitry Andric HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) {
1042fe013be4SDimitry Andric parseModuleMapFile(*ModMapFile, Attrs.IsSystem, *ParentDir);
1043a7dea167SDimitry Andric inferred = InferredDirectories.find(*ParentDir);
10440b57cec5SDimitry Andric }
10450b57cec5SDimitry Andric
10460b57cec5SDimitry Andric if (inferred == InferredDirectories.end())
10470b57cec5SDimitry Andric inferred = InferredDirectories.insert(
1048a7dea167SDimitry Andric std::make_pair(*ParentDir, InferredDirectory())).first;
10490b57cec5SDimitry Andric }
10500b57cec5SDimitry Andric
10510b57cec5SDimitry Andric if (inferred->second.InferModules) {
10520b57cec5SDimitry Andric // We're allowed to infer for this directory, but make sure it's okay
10530b57cec5SDimitry Andric // to infer this particular module.
10540b57cec5SDimitry Andric StringRef Name = llvm::sys::path::stem(FrameworkDirName);
1055349cc55cSDimitry Andric canInfer =
1056349cc55cSDimitry Andric !llvm::is_contained(inferred->second.ExcludedModules, Name);
10570b57cec5SDimitry Andric
10580b57cec5SDimitry Andric Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
10590b57cec5SDimitry Andric Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
10600b57cec5SDimitry Andric Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
10610b57cec5SDimitry Andric Attrs.NoUndeclaredIncludes |=
10620b57cec5SDimitry Andric inferred->second.Attrs.NoUndeclaredIncludes;
10630b57cec5SDimitry Andric ModuleMapFile = inferred->second.ModuleMapFile;
10640b57cec5SDimitry Andric }
10650b57cec5SDimitry Andric }
10660b57cec5SDimitry Andric }
10670b57cec5SDimitry Andric
10680b57cec5SDimitry Andric // If we're not allowed to infer a framework module, don't.
10690b57cec5SDimitry Andric if (!canInfer)
10700b57cec5SDimitry Andric return nullptr;
1071bdd1243dSDimitry Andric } else {
1072c9157d92SDimitry Andric ModuleMapFile = getModuleMapFileForUniquing(Parent);
1073bdd1243dSDimitry Andric }
10740b57cec5SDimitry Andric
10750b57cec5SDimitry Andric // Look for an umbrella header.
1076fe013be4SDimitry Andric SmallString<128> UmbrellaName = FrameworkDir.getName();
10770b57cec5SDimitry Andric llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
1078bdd1243dSDimitry Andric auto UmbrellaHeader = FileMgr.getOptionalFileRef(UmbrellaName);
10790b57cec5SDimitry Andric
10800b57cec5SDimitry Andric // FIXME: If there's no umbrella header, we could probably scan the
10810b57cec5SDimitry Andric // framework to load *everything*. But, it's not clear that this is a good
10820b57cec5SDimitry Andric // idea.
10830b57cec5SDimitry Andric if (!UmbrellaHeader)
10840b57cec5SDimitry Andric return nullptr;
10850b57cec5SDimitry Andric
10860b57cec5SDimitry Andric Module *Result = new Module(ModuleName, SourceLocation(), Parent,
10870b57cec5SDimitry Andric /*IsFramework=*/true, /*IsExplicit=*/false,
10880b57cec5SDimitry Andric NumCreatedModules++);
10890b57cec5SDimitry Andric InferredModuleAllowedBy[Result] = ModuleMapFile;
10900b57cec5SDimitry Andric Result->IsInferred = true;
10910b57cec5SDimitry Andric if (!Parent) {
10920b57cec5SDimitry Andric if (LangOpts.CurrentModule == ModuleName)
10930b57cec5SDimitry Andric SourceModule = Result;
10940b57cec5SDimitry Andric Modules[ModuleName] = Result;
10950b57cec5SDimitry Andric ModuleScopeIDs[Result] = CurrentModuleScopeID;
10960b57cec5SDimitry Andric }
10970b57cec5SDimitry Andric
10980b57cec5SDimitry Andric Result->IsSystem |= Attrs.IsSystem;
10990b57cec5SDimitry Andric Result->IsExternC |= Attrs.IsExternC;
11000b57cec5SDimitry Andric Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
11010b57cec5SDimitry Andric Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
11020b57cec5SDimitry Andric Result->Directory = FrameworkDir;
11030b57cec5SDimitry Andric
1104fe6060f1SDimitry Andric // Chop off the first framework bit, as that is implied.
1105fe6060f1SDimitry Andric StringRef RelativePath = UmbrellaName.str().substr(
1106fe6060f1SDimitry Andric Result->getTopLevelModule()->Directory->getName().size());
1107fe6060f1SDimitry Andric RelativePath = llvm::sys::path::relative_path(RelativePath);
1108fe6060f1SDimitry Andric
11090b57cec5SDimitry Andric // umbrella header "umbrella-header-name"
1110fe013be4SDimitry Andric setUmbrellaHeaderAsWritten(Result, *UmbrellaHeader, ModuleName + ".h",
1111fe013be4SDimitry Andric RelativePath);
11120b57cec5SDimitry Andric
11130b57cec5SDimitry Andric // export *
11140b57cec5SDimitry Andric Result->Exports.push_back(Module::ExportDecl(nullptr, true));
11150b57cec5SDimitry Andric
11160b57cec5SDimitry Andric // module * { export * }
11170b57cec5SDimitry Andric Result->InferSubmodules = true;
11180b57cec5SDimitry Andric Result->InferExportWildcard = true;
11190b57cec5SDimitry Andric
11200b57cec5SDimitry Andric // Look for subframeworks.
11210b57cec5SDimitry Andric std::error_code EC;
1122fe013be4SDimitry Andric SmallString<128> SubframeworksDirName = FrameworkDir.getName();
11230b57cec5SDimitry Andric llvm::sys::path::append(SubframeworksDirName, "Frameworks");
11240b57cec5SDimitry Andric llvm::sys::path::native(SubframeworksDirName);
11250b57cec5SDimitry Andric llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
11260b57cec5SDimitry Andric for (llvm::vfs::directory_iterator
11270b57cec5SDimitry Andric Dir = FS.dir_begin(SubframeworksDirName, EC),
11280b57cec5SDimitry Andric DirEnd;
11290b57cec5SDimitry Andric Dir != DirEnd && !EC; Dir.increment(EC)) {
1130c9157d92SDimitry Andric if (!StringRef(Dir->path()).ends_with(".framework"))
11310b57cec5SDimitry Andric continue;
11320b57cec5SDimitry Andric
1133fe013be4SDimitry Andric if (auto SubframeworkDir = FileMgr.getOptionalDirectoryRef(Dir->path())) {
11340b57cec5SDimitry Andric // Note: as an egregious but useful hack, we use the real path here and
11350b57cec5SDimitry Andric // check whether it is actually a subdirectory of the parent directory.
11360b57cec5SDimitry Andric // This will not be the case if the 'subframework' is actually a symlink
11370b57cec5SDimitry Andric // out to a top-level framework.
1138a7dea167SDimitry Andric StringRef SubframeworkDirName =
1139a7dea167SDimitry Andric FileMgr.getCanonicalName(*SubframeworkDir);
11400b57cec5SDimitry Andric bool FoundParent = false;
11410b57cec5SDimitry Andric do {
11420b57cec5SDimitry Andric // Get the parent directory name.
11430b57cec5SDimitry Andric SubframeworkDirName
11440b57cec5SDimitry Andric = llvm::sys::path::parent_path(SubframeworkDirName);
11450b57cec5SDimitry Andric if (SubframeworkDirName.empty())
11460b57cec5SDimitry Andric break;
11470b57cec5SDimitry Andric
1148a7dea167SDimitry Andric if (auto SubDir = FileMgr.getDirectory(SubframeworkDirName)) {
1149a7dea167SDimitry Andric if (*SubDir == FrameworkDir) {
11500b57cec5SDimitry Andric FoundParent = true;
11510b57cec5SDimitry Andric break;
11520b57cec5SDimitry Andric }
1153a7dea167SDimitry Andric }
11540b57cec5SDimitry Andric } while (true);
11550b57cec5SDimitry Andric
11560b57cec5SDimitry Andric if (!FoundParent)
11570b57cec5SDimitry Andric continue;
11580b57cec5SDimitry Andric
11590b57cec5SDimitry Andric // FIXME: Do we want to warn about subframeworks without umbrella headers?
1160a7dea167SDimitry Andric inferFrameworkModule(*SubframeworkDir, Attrs, Result);
11610b57cec5SDimitry Andric }
11620b57cec5SDimitry Andric }
11630b57cec5SDimitry Andric
11640b57cec5SDimitry Andric // If the module is a top-level framework, automatically link against the
11650b57cec5SDimitry Andric // framework.
1166fe013be4SDimitry Andric if (!Result->isSubFramework())
1167fe013be4SDimitry Andric inferFrameworkLink(Result);
11680b57cec5SDimitry Andric
11690b57cec5SDimitry Andric return Result;
11700b57cec5SDimitry Andric }
11710b57cec5SDimitry Andric
createShadowedModule(StringRef Name,bool IsFramework,Module * ShadowingModule)11720b57cec5SDimitry Andric Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
11730b57cec5SDimitry Andric Module *ShadowingModule) {
11740b57cec5SDimitry Andric
11750b57cec5SDimitry Andric // Create a new module with this name.
11760b57cec5SDimitry Andric Module *Result =
11770b57cec5SDimitry Andric new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
11780b57cec5SDimitry Andric /*IsExplicit=*/false, NumCreatedModules++);
11790b57cec5SDimitry Andric Result->ShadowingModule = ShadowingModule;
11805ffd83dbSDimitry Andric Result->markUnavailable(/*Unimportable*/true);
11810b57cec5SDimitry Andric ModuleScopeIDs[Result] = CurrentModuleScopeID;
11820b57cec5SDimitry Andric ShadowModules.push_back(Result);
11830b57cec5SDimitry Andric
11840b57cec5SDimitry Andric return Result;
11850b57cec5SDimitry Andric }
11860b57cec5SDimitry Andric
setUmbrellaHeaderAsWritten(Module * Mod,FileEntryRef UmbrellaHeader,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)1187fe013be4SDimitry Andric void ModuleMap::setUmbrellaHeaderAsWritten(
1188bdd1243dSDimitry Andric Module *Mod, FileEntryRef UmbrellaHeader, const Twine &NameAsWritten,
1189fe6060f1SDimitry Andric const Twine &PathRelativeToRootModuleDirectory) {
11900b57cec5SDimitry Andric Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
1191fe013be4SDimitry Andric Mod->Umbrella = UmbrellaHeader;
11920b57cec5SDimitry Andric Mod->UmbrellaAsWritten = NameAsWritten.str();
1193fe6060f1SDimitry Andric Mod->UmbrellaRelativeToRootModuleDirectory =
1194fe6060f1SDimitry Andric PathRelativeToRootModuleDirectory.str();
1195bdd1243dSDimitry Andric UmbrellaDirs[UmbrellaHeader.getDir()] = Mod;
11960b57cec5SDimitry Andric
11970b57cec5SDimitry Andric // Notify callbacks that we just added a new header.
11980b57cec5SDimitry Andric for (const auto &Cb : Callbacks)
1199fe013be4SDimitry Andric Cb->moduleMapAddUmbrellaHeader(UmbrellaHeader);
12000b57cec5SDimitry Andric }
12010b57cec5SDimitry Andric
setUmbrellaDirAsWritten(Module * Mod,DirectoryEntryRef UmbrellaDir,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)1202fe013be4SDimitry Andric void ModuleMap::setUmbrellaDirAsWritten(
1203fe013be4SDimitry Andric Module *Mod, DirectoryEntryRef UmbrellaDir, const Twine &NameAsWritten,
1204fe6060f1SDimitry Andric const Twine &PathRelativeToRootModuleDirectory) {
1205fe6060f1SDimitry Andric Mod->Umbrella = UmbrellaDir;
12060b57cec5SDimitry Andric Mod->UmbrellaAsWritten = NameAsWritten.str();
1207fe6060f1SDimitry Andric Mod->UmbrellaRelativeToRootModuleDirectory =
1208fe6060f1SDimitry Andric PathRelativeToRootModuleDirectory.str();
12090b57cec5SDimitry Andric UmbrellaDirs[UmbrellaDir] = Mod;
12100b57cec5SDimitry Andric }
12110b57cec5SDimitry Andric
addUnresolvedHeader(Module * Mod,Module::UnresolvedHeaderDirective Header,bool & NeedsFramework)12120b57cec5SDimitry Andric void ModuleMap::addUnresolvedHeader(Module *Mod,
12130b57cec5SDimitry Andric Module::UnresolvedHeaderDirective Header,
12140b57cec5SDimitry Andric bool &NeedsFramework) {
12150b57cec5SDimitry Andric // If there is a builtin counterpart to this file, add it now so it can
12160b57cec5SDimitry Andric // wrap the system header.
12170b57cec5SDimitry Andric if (resolveAsBuiltinHeader(Mod, Header)) {
12180b57cec5SDimitry Andric // If we have both a builtin and system version of the file, the
12190b57cec5SDimitry Andric // builtin version may want to inject macros into the system header, so
12200b57cec5SDimitry Andric // force the system header to be treated as a textual header in this
12210b57cec5SDimitry Andric // case.
12220b57cec5SDimitry Andric Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
12230b57cec5SDimitry Andric headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
12240b57cec5SDimitry Andric Header.HasBuiltinHeader = true;
12250b57cec5SDimitry Andric }
12260b57cec5SDimitry Andric
12270b57cec5SDimitry Andric // If possible, don't stat the header until we need to. This requires the
12280b57cec5SDimitry Andric // user to have provided us with some stat information about the file.
12290b57cec5SDimitry Andric // FIXME: Add support for lazily stat'ing umbrella headers and excluded
12300b57cec5SDimitry Andric // headers.
12310b57cec5SDimitry Andric if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
12320b57cec5SDimitry Andric Header.Kind != Module::HK_Excluded) {
12330b57cec5SDimitry Andric // We expect more variation in mtime than size, so if we're given both,
12340b57cec5SDimitry Andric // use the mtime as the key.
12350b57cec5SDimitry Andric if (Header.ModTime)
12360b57cec5SDimitry Andric LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
12370b57cec5SDimitry Andric else
12380b57cec5SDimitry Andric LazyHeadersBySize[*Header.Size].push_back(Mod);
12390b57cec5SDimitry Andric Mod->UnresolvedHeaders.push_back(Header);
12400b57cec5SDimitry Andric return;
12410b57cec5SDimitry Andric }
12420b57cec5SDimitry Andric
12430b57cec5SDimitry Andric // We don't have stat information or can't defer looking this file up.
12440b57cec5SDimitry Andric // Perform the lookup now.
12450b57cec5SDimitry Andric resolveHeader(Mod, Header, NeedsFramework);
12460b57cec5SDimitry Andric }
12470b57cec5SDimitry Andric
resolveHeaderDirectives(const FileEntry * File) const12480b57cec5SDimitry Andric void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
12490b57cec5SDimitry Andric auto BySize = LazyHeadersBySize.find(File->getSize());
12500b57cec5SDimitry Andric if (BySize != LazyHeadersBySize.end()) {
12510b57cec5SDimitry Andric for (auto *M : BySize->second)
125281ad6265SDimitry Andric resolveHeaderDirectives(M, File);
12530b57cec5SDimitry Andric LazyHeadersBySize.erase(BySize);
12540b57cec5SDimitry Andric }
12550b57cec5SDimitry Andric
12560b57cec5SDimitry Andric auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
12570b57cec5SDimitry Andric if (ByModTime != LazyHeadersByModTime.end()) {
12580b57cec5SDimitry Andric for (auto *M : ByModTime->second)
125981ad6265SDimitry Andric resolveHeaderDirectives(M, File);
12600b57cec5SDimitry Andric LazyHeadersByModTime.erase(ByModTime);
12610b57cec5SDimitry Andric }
12620b57cec5SDimitry Andric }
12630b57cec5SDimitry Andric
resolveHeaderDirectives(Module * Mod,std::optional<const FileEntry * > File) const126481ad6265SDimitry Andric void ModuleMap::resolveHeaderDirectives(
1265bdd1243dSDimitry Andric Module *Mod, std::optional<const FileEntry *> File) const {
12660b57cec5SDimitry Andric bool NeedsFramework = false;
126781ad6265SDimitry Andric SmallVector<Module::UnresolvedHeaderDirective, 1> NewHeaders;
1268bdd1243dSDimitry Andric const auto Size = File ? (*File)->getSize() : 0;
1269bdd1243dSDimitry Andric const auto ModTime = File ? (*File)->getModificationTime() : 0;
127081ad6265SDimitry Andric
127181ad6265SDimitry Andric for (auto &Header : Mod->UnresolvedHeaders) {
127281ad6265SDimitry Andric if (File && ((Header.ModTime && Header.ModTime != ModTime) ||
127381ad6265SDimitry Andric (Header.Size && Header.Size != Size)))
127481ad6265SDimitry Andric NewHeaders.push_back(Header);
127581ad6265SDimitry Andric else
12760b57cec5SDimitry Andric // This operation is logically const; we're just changing how we represent
12770b57cec5SDimitry Andric // the header information for this file.
12780b57cec5SDimitry Andric const_cast<ModuleMap *>(this)->resolveHeader(Mod, Header, NeedsFramework);
127981ad6265SDimitry Andric }
128081ad6265SDimitry Andric Mod->UnresolvedHeaders.swap(NewHeaders);
12810b57cec5SDimitry Andric }
12820b57cec5SDimitry Andric
addHeader(Module * Mod,Module::Header Header,ModuleHeaderRole Role,bool Imported)12830b57cec5SDimitry Andric void ModuleMap::addHeader(Module *Mod, Module::Header Header,
12840b57cec5SDimitry Andric ModuleHeaderRole Role, bool Imported) {
12850b57cec5SDimitry Andric KnownHeader KH(Mod, Role);
12860b57cec5SDimitry Andric
12870b57cec5SDimitry Andric // Only add each header to the headers list once.
12880b57cec5SDimitry Andric // FIXME: Should we diagnose if a header is listed twice in the
12890b57cec5SDimitry Andric // same module definition?
12900b57cec5SDimitry Andric auto &HeaderList = Headers[Header.Entry];
1291349cc55cSDimitry Andric if (llvm::is_contained(HeaderList, KH))
12920b57cec5SDimitry Andric return;
12930b57cec5SDimitry Andric
12940b57cec5SDimitry Andric HeaderList.push_back(KH);
12950b57cec5SDimitry Andric Mod->Headers[headerRoleToKind(Role)].push_back(Header);
12960b57cec5SDimitry Andric
1297c9157d92SDimitry Andric bool isCompilingModuleHeader = Mod->isForBuilding(LangOpts);
12980b57cec5SDimitry Andric if (!Imported || isCompilingModuleHeader) {
12990b57cec5SDimitry Andric // When we import HeaderFileInfo, the external source is expected to
13000b57cec5SDimitry Andric // set the isModuleHeader flag itself.
13010b57cec5SDimitry Andric HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
13020b57cec5SDimitry Andric isCompilingModuleHeader);
13030b57cec5SDimitry Andric }
13040b57cec5SDimitry Andric
13050b57cec5SDimitry Andric // Notify callbacks that we just added a new header.
13060b57cec5SDimitry Andric for (const auto &Cb : Callbacks)
1307fe013be4SDimitry Andric Cb->moduleMapAddHeader(Header.Entry.getName());
13080b57cec5SDimitry Andric }
13090b57cec5SDimitry Andric
1310bdd1243dSDimitry Andric OptionalFileEntryRef
getContainingModuleMapFile(const Module * Module) const13110b57cec5SDimitry Andric ModuleMap::getContainingModuleMapFile(const Module *Module) const {
13120b57cec5SDimitry Andric if (Module->DefinitionLoc.isInvalid())
1313bdd1243dSDimitry Andric return std::nullopt;
13140b57cec5SDimitry Andric
1315bdd1243dSDimitry Andric return SourceMgr.getFileEntryRefForID(
13160b57cec5SDimitry Andric SourceMgr.getFileID(Module->DefinitionLoc));
13170b57cec5SDimitry Andric }
13180b57cec5SDimitry Andric
1319bdd1243dSDimitry Andric OptionalFileEntryRef
getModuleMapFileForUniquing(const Module * M) const1320bdd1243dSDimitry Andric ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
13210b57cec5SDimitry Andric if (M->IsInferred) {
13220b57cec5SDimitry Andric assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
1323c9157d92SDimitry Andric return InferredModuleAllowedBy.find(M)->second;
13240b57cec5SDimitry Andric }
13250b57cec5SDimitry Andric return getContainingModuleMapFile(M);
13260b57cec5SDimitry Andric }
13270b57cec5SDimitry Andric
setInferredModuleAllowedBy(Module * M,OptionalFileEntryRef ModMap)1328c9157d92SDimitry Andric void ModuleMap::setInferredModuleAllowedBy(Module *M,
1329c9157d92SDimitry Andric OptionalFileEntryRef ModMap) {
13300b57cec5SDimitry Andric assert(M->IsInferred && "module not inferred");
13310b57cec5SDimitry Andric InferredModuleAllowedBy[M] = ModMap;
13320b57cec5SDimitry Andric }
13330b57cec5SDimitry Andric
1334bdd1243dSDimitry Andric std::error_code
canonicalizeModuleMapPath(SmallVectorImpl<char> & Path)1335bdd1243dSDimitry Andric ModuleMap::canonicalizeModuleMapPath(SmallVectorImpl<char> &Path) {
1336bdd1243dSDimitry Andric StringRef Dir = llvm::sys::path::parent_path({Path.data(), Path.size()});
1337bdd1243dSDimitry Andric
1338bdd1243dSDimitry Andric // Do not canonicalize within the framework; the module map parser expects
1339bdd1243dSDimitry Andric // Modules/ not Versions/A/Modules.
1340bdd1243dSDimitry Andric if (llvm::sys::path::filename(Dir) == "Modules") {
1341bdd1243dSDimitry Andric StringRef Parent = llvm::sys::path::parent_path(Dir);
1342c9157d92SDimitry Andric if (Parent.ends_with(".framework"))
1343bdd1243dSDimitry Andric Dir = Parent;
1344bdd1243dSDimitry Andric }
1345bdd1243dSDimitry Andric
1346bdd1243dSDimitry Andric FileManager &FM = SourceMgr.getFileManager();
1347fe013be4SDimitry Andric auto DirEntry = FM.getDirectoryRef(Dir.empty() ? "." : Dir);
1348bdd1243dSDimitry Andric if (!DirEntry)
1349fe013be4SDimitry Andric return llvm::errorToErrorCode(DirEntry.takeError());
1350bdd1243dSDimitry Andric
1351bdd1243dSDimitry Andric // Canonicalize the directory.
1352bdd1243dSDimitry Andric StringRef CanonicalDir = FM.getCanonicalName(*DirEntry);
1353fe013be4SDimitry Andric if (CanonicalDir != Dir)
1354fe013be4SDimitry Andric llvm::sys::path::replace_path_prefix(Path, Dir, CanonicalDir);
1355bdd1243dSDimitry Andric
1356bdd1243dSDimitry Andric // In theory, the filename component should also be canonicalized if it
1357bdd1243dSDimitry Andric // on a case-insensitive filesystem. However, the extra canonicalization is
1358bdd1243dSDimitry Andric // expensive and if clang looked up the filename it will always be lowercase.
1359bdd1243dSDimitry Andric
1360bdd1243dSDimitry Andric // Remove ., remove redundant separators, and switch to native separators.
1361bdd1243dSDimitry Andric // This is needed for separators between CanonicalDir and the filename.
1362bdd1243dSDimitry Andric llvm::sys::path::remove_dots(Path);
1363bdd1243dSDimitry Andric
1364bdd1243dSDimitry Andric return std::error_code();
1365bdd1243dSDimitry Andric }
1366bdd1243dSDimitry Andric
addAdditionalModuleMapFile(const Module * M,FileEntryRef ModuleMap)13675ffd83dbSDimitry Andric void ModuleMap::addAdditionalModuleMapFile(const Module *M,
1368c9157d92SDimitry Andric FileEntryRef ModuleMap) {
13695ffd83dbSDimitry Andric AdditionalModMaps[M].insert(ModuleMap);
13705ffd83dbSDimitry Andric }
13715ffd83dbSDimitry Andric
dump()13720b57cec5SDimitry Andric LLVM_DUMP_METHOD void ModuleMap::dump() {
13730b57cec5SDimitry Andric llvm::errs() << "Modules:";
13740b57cec5SDimitry Andric for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
13750b57cec5SDimitry Andric MEnd = Modules.end();
13760b57cec5SDimitry Andric M != MEnd; ++M)
13770b57cec5SDimitry Andric M->getValue()->print(llvm::errs(), 2);
13780b57cec5SDimitry Andric
13790b57cec5SDimitry Andric llvm::errs() << "Headers:";
13800b57cec5SDimitry Andric for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
13810b57cec5SDimitry Andric H != HEnd; ++H) {
1382c9157d92SDimitry Andric llvm::errs() << " \"" << H->first.getName() << "\" -> ";
13830b57cec5SDimitry Andric for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
13840b57cec5SDimitry Andric E = H->second.end();
13850b57cec5SDimitry Andric I != E; ++I) {
13860b57cec5SDimitry Andric if (I != H->second.begin())
13870b57cec5SDimitry Andric llvm::errs() << ",";
13880b57cec5SDimitry Andric llvm::errs() << I->getModule()->getFullModuleName();
13890b57cec5SDimitry Andric }
13900b57cec5SDimitry Andric llvm::errs() << "\n";
13910b57cec5SDimitry Andric }
13920b57cec5SDimitry Andric }
13930b57cec5SDimitry Andric
resolveExports(Module * Mod,bool Complain)13940b57cec5SDimitry Andric bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
13950b57cec5SDimitry Andric auto Unresolved = std::move(Mod->UnresolvedExports);
13960b57cec5SDimitry Andric Mod->UnresolvedExports.clear();
13970b57cec5SDimitry Andric for (auto &UE : Unresolved) {
13980b57cec5SDimitry Andric Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
13990b57cec5SDimitry Andric if (Export.getPointer() || Export.getInt())
14000b57cec5SDimitry Andric Mod->Exports.push_back(Export);
14010b57cec5SDimitry Andric else
14020b57cec5SDimitry Andric Mod->UnresolvedExports.push_back(UE);
14030b57cec5SDimitry Andric }
14040b57cec5SDimitry Andric return !Mod->UnresolvedExports.empty();
14050b57cec5SDimitry Andric }
14060b57cec5SDimitry Andric
resolveUses(Module * Mod,bool Complain)14070b57cec5SDimitry Andric bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
1408c9157d92SDimitry Andric auto *Top = Mod->getTopLevelModule();
1409c9157d92SDimitry Andric auto Unresolved = std::move(Top->UnresolvedDirectUses);
1410c9157d92SDimitry Andric Top->UnresolvedDirectUses.clear();
14110b57cec5SDimitry Andric for (auto &UDU : Unresolved) {
1412c9157d92SDimitry Andric Module *DirectUse = resolveModuleId(UDU, Top, Complain);
14130b57cec5SDimitry Andric if (DirectUse)
1414c9157d92SDimitry Andric Top->DirectUses.push_back(DirectUse);
14150b57cec5SDimitry Andric else
1416c9157d92SDimitry Andric Top->UnresolvedDirectUses.push_back(UDU);
14170b57cec5SDimitry Andric }
1418c9157d92SDimitry Andric return !Top->UnresolvedDirectUses.empty();
14190b57cec5SDimitry Andric }
14200b57cec5SDimitry Andric
resolveConflicts(Module * Mod,bool Complain)14210b57cec5SDimitry Andric bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
14220b57cec5SDimitry Andric auto Unresolved = std::move(Mod->UnresolvedConflicts);
14230b57cec5SDimitry Andric Mod->UnresolvedConflicts.clear();
14240b57cec5SDimitry Andric for (auto &UC : Unresolved) {
14250b57cec5SDimitry Andric if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
14260b57cec5SDimitry Andric Module::Conflict Conflict;
14270b57cec5SDimitry Andric Conflict.Other = OtherMod;
14280b57cec5SDimitry Andric Conflict.Message = UC.Message;
14290b57cec5SDimitry Andric Mod->Conflicts.push_back(Conflict);
14300b57cec5SDimitry Andric } else
14310b57cec5SDimitry Andric Mod->UnresolvedConflicts.push_back(UC);
14320b57cec5SDimitry Andric }
14330b57cec5SDimitry Andric return !Mod->UnresolvedConflicts.empty();
14340b57cec5SDimitry Andric }
14350b57cec5SDimitry Andric
14360b57cec5SDimitry Andric //----------------------------------------------------------------------------//
14370b57cec5SDimitry Andric // Module map file parser
14380b57cec5SDimitry Andric //----------------------------------------------------------------------------//
14390b57cec5SDimitry Andric
14400b57cec5SDimitry Andric namespace clang {
14410b57cec5SDimitry Andric
14420b57cec5SDimitry Andric /// A token in a module map file.
14430b57cec5SDimitry Andric struct MMToken {
14440b57cec5SDimitry Andric enum TokenKind {
14450b57cec5SDimitry Andric Comma,
14460b57cec5SDimitry Andric ConfigMacros,
14470b57cec5SDimitry Andric Conflict,
14480b57cec5SDimitry Andric EndOfFile,
14490b57cec5SDimitry Andric HeaderKeyword,
14500b57cec5SDimitry Andric Identifier,
14510b57cec5SDimitry Andric Exclaim,
14520b57cec5SDimitry Andric ExcludeKeyword,
14530b57cec5SDimitry Andric ExplicitKeyword,
14540b57cec5SDimitry Andric ExportKeyword,
14550b57cec5SDimitry Andric ExportAsKeyword,
14560b57cec5SDimitry Andric ExternKeyword,
14570b57cec5SDimitry Andric FrameworkKeyword,
14580b57cec5SDimitry Andric LinkKeyword,
14590b57cec5SDimitry Andric ModuleKeyword,
14600b57cec5SDimitry Andric Period,
14610b57cec5SDimitry Andric PrivateKeyword,
14620b57cec5SDimitry Andric UmbrellaKeyword,
14630b57cec5SDimitry Andric UseKeyword,
14640b57cec5SDimitry Andric RequiresKeyword,
14650b57cec5SDimitry Andric Star,
14660b57cec5SDimitry Andric StringLiteral,
14670b57cec5SDimitry Andric IntegerLiteral,
14680b57cec5SDimitry Andric TextualKeyword,
14690b57cec5SDimitry Andric LBrace,
14700b57cec5SDimitry Andric RBrace,
14710b57cec5SDimitry Andric LSquare,
14720b57cec5SDimitry Andric RSquare
14730b57cec5SDimitry Andric } Kind;
14740b57cec5SDimitry Andric
1475fe6060f1SDimitry Andric SourceLocation::UIntTy Location;
14760b57cec5SDimitry Andric unsigned StringLength;
14770b57cec5SDimitry Andric union {
14780b57cec5SDimitry Andric // If Kind != IntegerLiteral.
14790b57cec5SDimitry Andric const char *StringData;
14800b57cec5SDimitry Andric
14810b57cec5SDimitry Andric // If Kind == IntegerLiteral.
14820b57cec5SDimitry Andric uint64_t IntegerValue;
14830b57cec5SDimitry Andric };
14840b57cec5SDimitry Andric
clearclang::MMToken14850b57cec5SDimitry Andric void clear() {
14860b57cec5SDimitry Andric Kind = EndOfFile;
14870b57cec5SDimitry Andric Location = 0;
14880b57cec5SDimitry Andric StringLength = 0;
14890b57cec5SDimitry Andric StringData = nullptr;
14900b57cec5SDimitry Andric }
14910b57cec5SDimitry Andric
isclang::MMToken14920b57cec5SDimitry Andric bool is(TokenKind K) const { return Kind == K; }
14930b57cec5SDimitry Andric
getLocationclang::MMToken14940b57cec5SDimitry Andric SourceLocation getLocation() const {
14950b57cec5SDimitry Andric return SourceLocation::getFromRawEncoding(Location);
14960b57cec5SDimitry Andric }
14970b57cec5SDimitry Andric
getIntegerclang::MMToken14980b57cec5SDimitry Andric uint64_t getInteger() const {
14990b57cec5SDimitry Andric return Kind == IntegerLiteral ? IntegerValue : 0;
15000b57cec5SDimitry Andric }
15010b57cec5SDimitry Andric
getStringclang::MMToken15020b57cec5SDimitry Andric StringRef getString() const {
15030b57cec5SDimitry Andric return Kind == IntegerLiteral ? StringRef()
15040b57cec5SDimitry Andric : StringRef(StringData, StringLength);
15050b57cec5SDimitry Andric }
15060b57cec5SDimitry Andric };
15070b57cec5SDimitry Andric
15080b57cec5SDimitry Andric class ModuleMapParser {
15090b57cec5SDimitry Andric Lexer &L;
15100b57cec5SDimitry Andric SourceManager &SourceMgr;
15110b57cec5SDimitry Andric
15120b57cec5SDimitry Andric /// Default target information, used only for string literal
15130b57cec5SDimitry Andric /// parsing.
15140b57cec5SDimitry Andric const TargetInfo *Target;
15150b57cec5SDimitry Andric
15160b57cec5SDimitry Andric DiagnosticsEngine &Diags;
15170b57cec5SDimitry Andric ModuleMap ⤅
15180b57cec5SDimitry Andric
15190b57cec5SDimitry Andric /// The current module map file.
1520c9157d92SDimitry Andric FileEntryRef ModuleMapFile;
15210b57cec5SDimitry Andric
15220b57cec5SDimitry Andric /// Source location of most recent parsed module declaration
15230b57cec5SDimitry Andric SourceLocation CurrModuleDeclLoc;
15240b57cec5SDimitry Andric
15250b57cec5SDimitry Andric /// The directory that file names in this module map file should
15260b57cec5SDimitry Andric /// be resolved relative to.
1527fe013be4SDimitry Andric DirectoryEntryRef Directory;
15280b57cec5SDimitry Andric
15290b57cec5SDimitry Andric /// Whether this module map is in a system header directory.
15300b57cec5SDimitry Andric bool IsSystem;
15310b57cec5SDimitry Andric
15320b57cec5SDimitry Andric /// Whether an error occurred.
15330b57cec5SDimitry Andric bool HadError = false;
15340b57cec5SDimitry Andric
15350b57cec5SDimitry Andric /// Stores string data for the various string literals referenced
15360b57cec5SDimitry Andric /// during parsing.
15370b57cec5SDimitry Andric llvm::BumpPtrAllocator StringData;
15380b57cec5SDimitry Andric
15390b57cec5SDimitry Andric /// The current token.
15400b57cec5SDimitry Andric MMToken Tok;
15410b57cec5SDimitry Andric
15420b57cec5SDimitry Andric /// The active module.
15430b57cec5SDimitry Andric Module *ActiveModule = nullptr;
15440b57cec5SDimitry Andric
15450b57cec5SDimitry Andric /// Whether a module uses the 'requires excluded' hack to mark its
15460b57cec5SDimitry Andric /// contents as 'textual'.
15470b57cec5SDimitry Andric ///
15480b57cec5SDimitry Andric /// On older Darwin SDK versions, 'requires excluded' is used to mark the
15490b57cec5SDimitry Andric /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
15500b57cec5SDimitry Andric /// non-modular headers. For backwards compatibility, we continue to
15510b57cec5SDimitry Andric /// support this idiom for just these modules, and map the headers to
15520b57cec5SDimitry Andric /// 'textual' to match the original intent.
15530b57cec5SDimitry Andric llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
15540b57cec5SDimitry Andric
15550b57cec5SDimitry Andric /// Consume the current token and return its location.
15560b57cec5SDimitry Andric SourceLocation consumeToken();
15570b57cec5SDimitry Andric
15580b57cec5SDimitry Andric /// Skip tokens until we reach the a token with the given kind
15590b57cec5SDimitry Andric /// (or the end of the file).
15600b57cec5SDimitry Andric void skipUntil(MMToken::TokenKind K);
15610b57cec5SDimitry Andric
15620b57cec5SDimitry Andric bool parseModuleId(ModuleId &Id);
15630b57cec5SDimitry Andric void parseModuleDecl();
15640b57cec5SDimitry Andric void parseExternModuleDecl();
15650b57cec5SDimitry Andric void parseRequiresDecl();
15660b57cec5SDimitry Andric void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
15670b57cec5SDimitry Andric void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
15680b57cec5SDimitry Andric void parseExportDecl();
15690b57cec5SDimitry Andric void parseExportAsDecl();
15700b57cec5SDimitry Andric void parseUseDecl();
15710b57cec5SDimitry Andric void parseLinkDecl();
15720b57cec5SDimitry Andric void parseConfigMacros();
15730b57cec5SDimitry Andric void parseConflict();
15740b57cec5SDimitry Andric void parseInferredModuleDecl(bool Framework, bool Explicit);
15750b57cec5SDimitry Andric
15760b57cec5SDimitry Andric /// Private modules are canonicalized as Foo_Private. Clang provides extra
15770b57cec5SDimitry Andric /// module map search logic to find the appropriate private module when PCH
15780b57cec5SDimitry Andric /// is used with implicit module maps. Warn when private modules are written
15790b57cec5SDimitry Andric /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
15800b57cec5SDimitry Andric void diagnosePrivateModules(SourceLocation ExplicitLoc,
15810b57cec5SDimitry Andric SourceLocation FrameworkLoc);
15820b57cec5SDimitry Andric
15830b57cec5SDimitry Andric using Attributes = ModuleMap::Attributes;
15840b57cec5SDimitry Andric
15850b57cec5SDimitry Andric bool parseOptionalAttributes(Attributes &Attrs);
15860b57cec5SDimitry Andric
15870b57cec5SDimitry Andric public:
ModuleMapParser(Lexer & L,SourceManager & SourceMgr,const TargetInfo * Target,DiagnosticsEngine & Diags,ModuleMap & Map,FileEntryRef ModuleMapFile,DirectoryEntryRef Directory,bool IsSystem)15880b57cec5SDimitry Andric explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
15890b57cec5SDimitry Andric const TargetInfo *Target, DiagnosticsEngine &Diags,
1590c9157d92SDimitry Andric ModuleMap &Map, FileEntryRef ModuleMapFile,
1591fe013be4SDimitry Andric DirectoryEntryRef Directory, bool IsSystem)
15920b57cec5SDimitry Andric : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
15930b57cec5SDimitry Andric ModuleMapFile(ModuleMapFile), Directory(Directory),
15940b57cec5SDimitry Andric IsSystem(IsSystem) {
15950b57cec5SDimitry Andric Tok.clear();
15960b57cec5SDimitry Andric consumeToken();
15970b57cec5SDimitry Andric }
15980b57cec5SDimitry Andric
15990b57cec5SDimitry Andric bool parseModuleMapFile();
16000b57cec5SDimitry Andric
terminatedByDirective()16010b57cec5SDimitry Andric bool terminatedByDirective() { return false; }
getLocation()16020b57cec5SDimitry Andric SourceLocation getLocation() { return Tok.getLocation(); }
16030b57cec5SDimitry Andric };
16040b57cec5SDimitry Andric
16050b57cec5SDimitry Andric } // namespace clang
16060b57cec5SDimitry Andric
consumeToken()16070b57cec5SDimitry Andric SourceLocation ModuleMapParser::consumeToken() {
16080b57cec5SDimitry Andric SourceLocation Result = Tok.getLocation();
16090b57cec5SDimitry Andric
16100b57cec5SDimitry Andric retry:
16110b57cec5SDimitry Andric Tok.clear();
16120b57cec5SDimitry Andric Token LToken;
16130b57cec5SDimitry Andric L.LexFromRawLexer(LToken);
16140b57cec5SDimitry Andric Tok.Location = LToken.getLocation().getRawEncoding();
16150b57cec5SDimitry Andric switch (LToken.getKind()) {
16160b57cec5SDimitry Andric case tok::raw_identifier: {
16170b57cec5SDimitry Andric StringRef RI = LToken.getRawIdentifier();
16180b57cec5SDimitry Andric Tok.StringData = RI.data();
16190b57cec5SDimitry Andric Tok.StringLength = RI.size();
16200b57cec5SDimitry Andric Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
16210b57cec5SDimitry Andric .Case("config_macros", MMToken::ConfigMacros)
16220b57cec5SDimitry Andric .Case("conflict", MMToken::Conflict)
16230b57cec5SDimitry Andric .Case("exclude", MMToken::ExcludeKeyword)
16240b57cec5SDimitry Andric .Case("explicit", MMToken::ExplicitKeyword)
16250b57cec5SDimitry Andric .Case("export", MMToken::ExportKeyword)
16260b57cec5SDimitry Andric .Case("export_as", MMToken::ExportAsKeyword)
16270b57cec5SDimitry Andric .Case("extern", MMToken::ExternKeyword)
16280b57cec5SDimitry Andric .Case("framework", MMToken::FrameworkKeyword)
16290b57cec5SDimitry Andric .Case("header", MMToken::HeaderKeyword)
16300b57cec5SDimitry Andric .Case("link", MMToken::LinkKeyword)
16310b57cec5SDimitry Andric .Case("module", MMToken::ModuleKeyword)
16320b57cec5SDimitry Andric .Case("private", MMToken::PrivateKeyword)
16330b57cec5SDimitry Andric .Case("requires", MMToken::RequiresKeyword)
16340b57cec5SDimitry Andric .Case("textual", MMToken::TextualKeyword)
16350b57cec5SDimitry Andric .Case("umbrella", MMToken::UmbrellaKeyword)
16360b57cec5SDimitry Andric .Case("use", MMToken::UseKeyword)
16370b57cec5SDimitry Andric .Default(MMToken::Identifier);
16380b57cec5SDimitry Andric break;
16390b57cec5SDimitry Andric }
16400b57cec5SDimitry Andric
16410b57cec5SDimitry Andric case tok::comma:
16420b57cec5SDimitry Andric Tok.Kind = MMToken::Comma;
16430b57cec5SDimitry Andric break;
16440b57cec5SDimitry Andric
16450b57cec5SDimitry Andric case tok::eof:
16460b57cec5SDimitry Andric Tok.Kind = MMToken::EndOfFile;
16470b57cec5SDimitry Andric break;
16480b57cec5SDimitry Andric
16490b57cec5SDimitry Andric case tok::l_brace:
16500b57cec5SDimitry Andric Tok.Kind = MMToken::LBrace;
16510b57cec5SDimitry Andric break;
16520b57cec5SDimitry Andric
16530b57cec5SDimitry Andric case tok::l_square:
16540b57cec5SDimitry Andric Tok.Kind = MMToken::LSquare;
16550b57cec5SDimitry Andric break;
16560b57cec5SDimitry Andric
16570b57cec5SDimitry Andric case tok::period:
16580b57cec5SDimitry Andric Tok.Kind = MMToken::Period;
16590b57cec5SDimitry Andric break;
16600b57cec5SDimitry Andric
16610b57cec5SDimitry Andric case tok::r_brace:
16620b57cec5SDimitry Andric Tok.Kind = MMToken::RBrace;
16630b57cec5SDimitry Andric break;
16640b57cec5SDimitry Andric
16650b57cec5SDimitry Andric case tok::r_square:
16660b57cec5SDimitry Andric Tok.Kind = MMToken::RSquare;
16670b57cec5SDimitry Andric break;
16680b57cec5SDimitry Andric
16690b57cec5SDimitry Andric case tok::star:
16700b57cec5SDimitry Andric Tok.Kind = MMToken::Star;
16710b57cec5SDimitry Andric break;
16720b57cec5SDimitry Andric
16730b57cec5SDimitry Andric case tok::exclaim:
16740b57cec5SDimitry Andric Tok.Kind = MMToken::Exclaim;
16750b57cec5SDimitry Andric break;
16760b57cec5SDimitry Andric
16770b57cec5SDimitry Andric case tok::string_literal: {
16780b57cec5SDimitry Andric if (LToken.hasUDSuffix()) {
16790b57cec5SDimitry Andric Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
16800b57cec5SDimitry Andric HadError = true;
16810b57cec5SDimitry Andric goto retry;
16820b57cec5SDimitry Andric }
16830b57cec5SDimitry Andric
16840b57cec5SDimitry Andric // Parse the string literal.
16850b57cec5SDimitry Andric LangOptions LangOpts;
16860b57cec5SDimitry Andric StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
16870b57cec5SDimitry Andric if (StringLiteral.hadError)
16880b57cec5SDimitry Andric goto retry;
16890b57cec5SDimitry Andric
16900b57cec5SDimitry Andric // Copy the string literal into our string data allocator.
16910b57cec5SDimitry Andric unsigned Length = StringLiteral.GetStringLength();
16920b57cec5SDimitry Andric char *Saved = StringData.Allocate<char>(Length + 1);
16930b57cec5SDimitry Andric memcpy(Saved, StringLiteral.GetString().data(), Length);
16940b57cec5SDimitry Andric Saved[Length] = 0;
16950b57cec5SDimitry Andric
16960b57cec5SDimitry Andric // Form the token.
16970b57cec5SDimitry Andric Tok.Kind = MMToken::StringLiteral;
16980b57cec5SDimitry Andric Tok.StringData = Saved;
16990b57cec5SDimitry Andric Tok.StringLength = Length;
17000b57cec5SDimitry Andric break;
17010b57cec5SDimitry Andric }
17020b57cec5SDimitry Andric
17030b57cec5SDimitry Andric case tok::numeric_constant: {
17040b57cec5SDimitry Andric // We don't support any suffixes or other complications.
17050b57cec5SDimitry Andric SmallString<32> SpellingBuffer;
17060b57cec5SDimitry Andric SpellingBuffer.resize(LToken.getLength() + 1);
17070b57cec5SDimitry Andric const char *Start = SpellingBuffer.data();
17080b57cec5SDimitry Andric unsigned Length =
170981ad6265SDimitry Andric Lexer::getSpelling(LToken, Start, SourceMgr, Map.LangOpts);
17100b57cec5SDimitry Andric uint64_t Value;
17110b57cec5SDimitry Andric if (StringRef(Start, Length).getAsInteger(0, Value)) {
17120b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
17130b57cec5SDimitry Andric HadError = true;
17140b57cec5SDimitry Andric goto retry;
17150b57cec5SDimitry Andric }
17160b57cec5SDimitry Andric
17170b57cec5SDimitry Andric Tok.Kind = MMToken::IntegerLiteral;
17180b57cec5SDimitry Andric Tok.IntegerValue = Value;
17190b57cec5SDimitry Andric break;
17200b57cec5SDimitry Andric }
17210b57cec5SDimitry Andric
17220b57cec5SDimitry Andric case tok::comment:
17230b57cec5SDimitry Andric goto retry;
17240b57cec5SDimitry Andric
17250b57cec5SDimitry Andric case tok::hash:
17260b57cec5SDimitry Andric // A module map can be terminated prematurely by
17270b57cec5SDimitry Andric // #pragma clang module contents
17280b57cec5SDimitry Andric // When building the module, we'll treat the rest of the file as the
17290b57cec5SDimitry Andric // contents of the module.
17300b57cec5SDimitry Andric {
17310b57cec5SDimitry Andric auto NextIsIdent = [&](StringRef Str) -> bool {
17320b57cec5SDimitry Andric L.LexFromRawLexer(LToken);
17330b57cec5SDimitry Andric return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
17340b57cec5SDimitry Andric LToken.getRawIdentifier() == Str;
17350b57cec5SDimitry Andric };
17360b57cec5SDimitry Andric if (NextIsIdent("pragma") && NextIsIdent("clang") &&
17370b57cec5SDimitry Andric NextIsIdent("module") && NextIsIdent("contents")) {
17380b57cec5SDimitry Andric Tok.Kind = MMToken::EndOfFile;
17390b57cec5SDimitry Andric break;
17400b57cec5SDimitry Andric }
17410b57cec5SDimitry Andric }
1742bdd1243dSDimitry Andric [[fallthrough]];
17430b57cec5SDimitry Andric
17440b57cec5SDimitry Andric default:
17450b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
17460b57cec5SDimitry Andric HadError = true;
17470b57cec5SDimitry Andric goto retry;
17480b57cec5SDimitry Andric }
17490b57cec5SDimitry Andric
17500b57cec5SDimitry Andric return Result;
17510b57cec5SDimitry Andric }
17520b57cec5SDimitry Andric
skipUntil(MMToken::TokenKind K)17530b57cec5SDimitry Andric void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
17540b57cec5SDimitry Andric unsigned braceDepth = 0;
17550b57cec5SDimitry Andric unsigned squareDepth = 0;
17560b57cec5SDimitry Andric do {
17570b57cec5SDimitry Andric switch (Tok.Kind) {
17580b57cec5SDimitry Andric case MMToken::EndOfFile:
17590b57cec5SDimitry Andric return;
17600b57cec5SDimitry Andric
17610b57cec5SDimitry Andric case MMToken::LBrace:
17620b57cec5SDimitry Andric if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
17630b57cec5SDimitry Andric return;
17640b57cec5SDimitry Andric
17650b57cec5SDimitry Andric ++braceDepth;
17660b57cec5SDimitry Andric break;
17670b57cec5SDimitry Andric
17680b57cec5SDimitry Andric case MMToken::LSquare:
17690b57cec5SDimitry Andric if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
17700b57cec5SDimitry Andric return;
17710b57cec5SDimitry Andric
17720b57cec5SDimitry Andric ++squareDepth;
17730b57cec5SDimitry Andric break;
17740b57cec5SDimitry Andric
17750b57cec5SDimitry Andric case MMToken::RBrace:
17760b57cec5SDimitry Andric if (braceDepth > 0)
17770b57cec5SDimitry Andric --braceDepth;
17780b57cec5SDimitry Andric else if (Tok.is(K))
17790b57cec5SDimitry Andric return;
17800b57cec5SDimitry Andric break;
17810b57cec5SDimitry Andric
17820b57cec5SDimitry Andric case MMToken::RSquare:
17830b57cec5SDimitry Andric if (squareDepth > 0)
17840b57cec5SDimitry Andric --squareDepth;
17850b57cec5SDimitry Andric else if (Tok.is(K))
17860b57cec5SDimitry Andric return;
17870b57cec5SDimitry Andric break;
17880b57cec5SDimitry Andric
17890b57cec5SDimitry Andric default:
17900b57cec5SDimitry Andric if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
17910b57cec5SDimitry Andric return;
17920b57cec5SDimitry Andric break;
17930b57cec5SDimitry Andric }
17940b57cec5SDimitry Andric
17950b57cec5SDimitry Andric consumeToken();
17960b57cec5SDimitry Andric } while (true);
17970b57cec5SDimitry Andric }
17980b57cec5SDimitry Andric
17990b57cec5SDimitry Andric /// Parse a module-id.
18000b57cec5SDimitry Andric ///
18010b57cec5SDimitry Andric /// module-id:
18020b57cec5SDimitry Andric /// identifier
18030b57cec5SDimitry Andric /// identifier '.' module-id
18040b57cec5SDimitry Andric ///
18050b57cec5SDimitry Andric /// \returns true if an error occurred, false otherwise.
parseModuleId(ModuleId & Id)18060b57cec5SDimitry Andric bool ModuleMapParser::parseModuleId(ModuleId &Id) {
18070b57cec5SDimitry Andric Id.clear();
18080b57cec5SDimitry Andric do {
18090b57cec5SDimitry Andric if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
18105ffd83dbSDimitry Andric Id.push_back(
18115ffd83dbSDimitry Andric std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
18120b57cec5SDimitry Andric consumeToken();
18130b57cec5SDimitry Andric } else {
18140b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
18150b57cec5SDimitry Andric return true;
18160b57cec5SDimitry Andric }
18170b57cec5SDimitry Andric
18180b57cec5SDimitry Andric if (!Tok.is(MMToken::Period))
18190b57cec5SDimitry Andric break;
18200b57cec5SDimitry Andric
18210b57cec5SDimitry Andric consumeToken();
18220b57cec5SDimitry Andric } while (true);
18230b57cec5SDimitry Andric
18240b57cec5SDimitry Andric return false;
18250b57cec5SDimitry Andric }
18260b57cec5SDimitry Andric
18270b57cec5SDimitry Andric namespace {
18280b57cec5SDimitry Andric
18290b57cec5SDimitry Andric /// Enumerates the known attributes.
18300b57cec5SDimitry Andric enum AttributeKind {
18310b57cec5SDimitry Andric /// An unknown attribute.
18320b57cec5SDimitry Andric AT_unknown,
18330b57cec5SDimitry Andric
18340b57cec5SDimitry Andric /// The 'system' attribute.
18350b57cec5SDimitry Andric AT_system,
18360b57cec5SDimitry Andric
18370b57cec5SDimitry Andric /// The 'extern_c' attribute.
18380b57cec5SDimitry Andric AT_extern_c,
18390b57cec5SDimitry Andric
18400b57cec5SDimitry Andric /// The 'exhaustive' attribute.
18410b57cec5SDimitry Andric AT_exhaustive,
18420b57cec5SDimitry Andric
18430b57cec5SDimitry Andric /// The 'no_undeclared_includes' attribute.
18440b57cec5SDimitry Andric AT_no_undeclared_includes
18450b57cec5SDimitry Andric };
18460b57cec5SDimitry Andric
18470b57cec5SDimitry Andric } // namespace
18480b57cec5SDimitry Andric
18490b57cec5SDimitry Andric /// Private modules are canonicalized as Foo_Private. Clang provides extra
18500b57cec5SDimitry Andric /// module map search logic to find the appropriate private module when PCH
18510b57cec5SDimitry Andric /// is used with implicit module maps. Warn when private modules are written
18520b57cec5SDimitry Andric /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
diagnosePrivateModules(SourceLocation ExplicitLoc,SourceLocation FrameworkLoc)18530b57cec5SDimitry Andric void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
18540b57cec5SDimitry Andric SourceLocation FrameworkLoc) {
18550b57cec5SDimitry Andric auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
18560b57cec5SDimitry Andric const Module *M, SourceRange ReplLoc) {
18570b57cec5SDimitry Andric auto D = Diags.Report(ActiveModule->DefinitionLoc,
18580b57cec5SDimitry Andric diag::note_mmap_rename_top_level_private_module);
18590b57cec5SDimitry Andric D << BadName << M->Name;
18600b57cec5SDimitry Andric D << FixItHint::CreateReplacement(ReplLoc, Canonical);
18610b57cec5SDimitry Andric };
18620b57cec5SDimitry Andric
18630b57cec5SDimitry Andric for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
18640b57cec5SDimitry Andric auto const *M = E->getValue();
18650b57cec5SDimitry Andric if (M->Directory != ActiveModule->Directory)
18660b57cec5SDimitry Andric continue;
18670b57cec5SDimitry Andric
18680b57cec5SDimitry Andric SmallString<128> FullName(ActiveModule->getFullModuleName());
1869c9157d92SDimitry Andric if (!FullName.starts_with(M->Name) && !FullName.ends_with("Private"))
18700b57cec5SDimitry Andric continue;
18710b57cec5SDimitry Andric SmallString<128> FixedPrivModDecl;
18720b57cec5SDimitry Andric SmallString<128> Canonical(M->Name);
18730b57cec5SDimitry Andric Canonical.append("_Private");
18740b57cec5SDimitry Andric
18750b57cec5SDimitry Andric // Foo.Private -> Foo_Private
18760b57cec5SDimitry Andric if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
18770b57cec5SDimitry Andric M->Name == ActiveModule->Parent->Name) {
18780b57cec5SDimitry Andric Diags.Report(ActiveModule->DefinitionLoc,
18790b57cec5SDimitry Andric diag::warn_mmap_mismatched_private_submodule)
18800b57cec5SDimitry Andric << FullName;
18810b57cec5SDimitry Andric
18820b57cec5SDimitry Andric SourceLocation FixItInitBegin = CurrModuleDeclLoc;
18830b57cec5SDimitry Andric if (FrameworkLoc.isValid())
18840b57cec5SDimitry Andric FixItInitBegin = FrameworkLoc;
18850b57cec5SDimitry Andric if (ExplicitLoc.isValid())
18860b57cec5SDimitry Andric FixItInitBegin = ExplicitLoc;
18870b57cec5SDimitry Andric
18880b57cec5SDimitry Andric if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
18890b57cec5SDimitry Andric FixedPrivModDecl.append("framework ");
18900b57cec5SDimitry Andric FixedPrivModDecl.append("module ");
18910b57cec5SDimitry Andric FixedPrivModDecl.append(Canonical);
18920b57cec5SDimitry Andric
18930b57cec5SDimitry Andric GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
18940b57cec5SDimitry Andric SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
18950b57cec5SDimitry Andric continue;
18960b57cec5SDimitry Andric }
18970b57cec5SDimitry Andric
18980b57cec5SDimitry Andric // FooPrivate and whatnots -> Foo_Private
18990b57cec5SDimitry Andric if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
19000b57cec5SDimitry Andric ActiveModule->Name != Canonical) {
19010b57cec5SDimitry Andric Diags.Report(ActiveModule->DefinitionLoc,
19020b57cec5SDimitry Andric diag::warn_mmap_mismatched_private_module_name)
19030b57cec5SDimitry Andric << ActiveModule->Name;
19040b57cec5SDimitry Andric GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
19050b57cec5SDimitry Andric SourceRange(ActiveModule->DefinitionLoc));
19060b57cec5SDimitry Andric }
19070b57cec5SDimitry Andric }
19080b57cec5SDimitry Andric }
19090b57cec5SDimitry Andric
19100b57cec5SDimitry Andric /// Parse a module declaration.
19110b57cec5SDimitry Andric ///
19120b57cec5SDimitry Andric /// module-declaration:
19130b57cec5SDimitry Andric /// 'extern' 'module' module-id string-literal
19140b57cec5SDimitry Andric /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
19150b57cec5SDimitry Andric /// { module-member* }
19160b57cec5SDimitry Andric ///
19170b57cec5SDimitry Andric /// module-member:
19180b57cec5SDimitry Andric /// requires-declaration
19190b57cec5SDimitry Andric /// header-declaration
19200b57cec5SDimitry Andric /// submodule-declaration
19210b57cec5SDimitry Andric /// export-declaration
19220b57cec5SDimitry Andric /// export-as-declaration
19230b57cec5SDimitry Andric /// link-declaration
19240b57cec5SDimitry Andric ///
19250b57cec5SDimitry Andric /// submodule-declaration:
19260b57cec5SDimitry Andric /// module-declaration
19270b57cec5SDimitry Andric /// inferred-submodule-declaration
parseModuleDecl()19280b57cec5SDimitry Andric void ModuleMapParser::parseModuleDecl() {
19290b57cec5SDimitry Andric assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
19300b57cec5SDimitry Andric Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
19310b57cec5SDimitry Andric if (Tok.is(MMToken::ExternKeyword)) {
19320b57cec5SDimitry Andric parseExternModuleDecl();
19330b57cec5SDimitry Andric return;
19340b57cec5SDimitry Andric }
19350b57cec5SDimitry Andric
19360b57cec5SDimitry Andric // Parse 'explicit' or 'framework' keyword, if present.
19370b57cec5SDimitry Andric SourceLocation ExplicitLoc;
19380b57cec5SDimitry Andric SourceLocation FrameworkLoc;
19390b57cec5SDimitry Andric bool Explicit = false;
19400b57cec5SDimitry Andric bool Framework = false;
19410b57cec5SDimitry Andric
19420b57cec5SDimitry Andric // Parse 'explicit' keyword, if present.
19430b57cec5SDimitry Andric if (Tok.is(MMToken::ExplicitKeyword)) {
19440b57cec5SDimitry Andric ExplicitLoc = consumeToken();
19450b57cec5SDimitry Andric Explicit = true;
19460b57cec5SDimitry Andric }
19470b57cec5SDimitry Andric
19480b57cec5SDimitry Andric // Parse 'framework' keyword, if present.
19490b57cec5SDimitry Andric if (Tok.is(MMToken::FrameworkKeyword)) {
19500b57cec5SDimitry Andric FrameworkLoc = consumeToken();
19510b57cec5SDimitry Andric Framework = true;
19520b57cec5SDimitry Andric }
19530b57cec5SDimitry Andric
19540b57cec5SDimitry Andric // Parse 'module' keyword.
19550b57cec5SDimitry Andric if (!Tok.is(MMToken::ModuleKeyword)) {
19560b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
19570b57cec5SDimitry Andric consumeToken();
19580b57cec5SDimitry Andric HadError = true;
19590b57cec5SDimitry Andric return;
19600b57cec5SDimitry Andric }
19610b57cec5SDimitry Andric CurrModuleDeclLoc = consumeToken(); // 'module' keyword
19620b57cec5SDimitry Andric
19630b57cec5SDimitry Andric // If we have a wildcard for the module name, this is an inferred submodule.
19640b57cec5SDimitry Andric // Parse it.
19650b57cec5SDimitry Andric if (Tok.is(MMToken::Star))
19660b57cec5SDimitry Andric return parseInferredModuleDecl(Framework, Explicit);
19670b57cec5SDimitry Andric
19680b57cec5SDimitry Andric // Parse the module name.
19690b57cec5SDimitry Andric ModuleId Id;
19700b57cec5SDimitry Andric if (parseModuleId(Id)) {
19710b57cec5SDimitry Andric HadError = true;
19720b57cec5SDimitry Andric return;
19730b57cec5SDimitry Andric }
19740b57cec5SDimitry Andric
19750b57cec5SDimitry Andric if (ActiveModule) {
19760b57cec5SDimitry Andric if (Id.size() > 1) {
19770b57cec5SDimitry Andric Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
19780b57cec5SDimitry Andric << SourceRange(Id.front().second, Id.back().second);
19790b57cec5SDimitry Andric
19800b57cec5SDimitry Andric HadError = true;
19810b57cec5SDimitry Andric return;
19820b57cec5SDimitry Andric }
19830b57cec5SDimitry Andric } else if (Id.size() == 1 && Explicit) {
19840b57cec5SDimitry Andric // Top-level modules can't be explicit.
19850b57cec5SDimitry Andric Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
19860b57cec5SDimitry Andric Explicit = false;
19870b57cec5SDimitry Andric ExplicitLoc = SourceLocation();
19880b57cec5SDimitry Andric HadError = true;
19890b57cec5SDimitry Andric }
19900b57cec5SDimitry Andric
19910b57cec5SDimitry Andric Module *PreviousActiveModule = ActiveModule;
19920b57cec5SDimitry Andric if (Id.size() > 1) {
19930b57cec5SDimitry Andric // This module map defines a submodule. Go find the module of which it
19940b57cec5SDimitry Andric // is a submodule.
19950b57cec5SDimitry Andric ActiveModule = nullptr;
19960b57cec5SDimitry Andric const Module *TopLevelModule = nullptr;
19970b57cec5SDimitry Andric for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
19980b57cec5SDimitry Andric if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
19990b57cec5SDimitry Andric if (I == 0)
20000b57cec5SDimitry Andric TopLevelModule = Next;
20010b57cec5SDimitry Andric ActiveModule = Next;
20020b57cec5SDimitry Andric continue;
20030b57cec5SDimitry Andric }
20040b57cec5SDimitry Andric
2005e8d8bef9SDimitry Andric Diags.Report(Id[I].second, diag::err_mmap_missing_parent_module)
2006e8d8bef9SDimitry Andric << Id[I].first << (ActiveModule != nullptr)
2007e8d8bef9SDimitry Andric << (ActiveModule
2008e8d8bef9SDimitry Andric ? ActiveModule->getTopLevelModule()->getFullModuleName()
2009e8d8bef9SDimitry Andric : "");
20100b57cec5SDimitry Andric HadError = true;
20110b57cec5SDimitry Andric }
20120b57cec5SDimitry Andric
2013e8d8bef9SDimitry Andric if (TopLevelModule &&
2014e8d8bef9SDimitry Andric ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
20150b57cec5SDimitry Andric assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
20160b57cec5SDimitry Andric "submodule defined in same file as 'module *' that allowed its "
20170b57cec5SDimitry Andric "top-level module");
20180b57cec5SDimitry Andric Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
20190b57cec5SDimitry Andric }
20200b57cec5SDimitry Andric }
20210b57cec5SDimitry Andric
20220b57cec5SDimitry Andric StringRef ModuleName = Id.back().first;
20230b57cec5SDimitry Andric SourceLocation ModuleNameLoc = Id.back().second;
20240b57cec5SDimitry Andric
20250b57cec5SDimitry Andric // Parse the optional attribute list.
20260b57cec5SDimitry Andric Attributes Attrs;
20270b57cec5SDimitry Andric if (parseOptionalAttributes(Attrs))
20280b57cec5SDimitry Andric return;
20290b57cec5SDimitry Andric
20300b57cec5SDimitry Andric // Parse the opening brace.
20310b57cec5SDimitry Andric if (!Tok.is(MMToken::LBrace)) {
20320b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
20330b57cec5SDimitry Andric << ModuleName;
20340b57cec5SDimitry Andric HadError = true;
20350b57cec5SDimitry Andric return;
20360b57cec5SDimitry Andric }
20370b57cec5SDimitry Andric SourceLocation LBraceLoc = consumeToken();
20380b57cec5SDimitry Andric
20390b57cec5SDimitry Andric // Determine whether this (sub)module has already been defined.
20400b57cec5SDimitry Andric Module *ShadowingModule = nullptr;
20410b57cec5SDimitry Andric if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
20420b57cec5SDimitry Andric // We might see a (re)definition of a module that we already have a
2043fe013be4SDimitry Andric // definition for in four cases:
20440b57cec5SDimitry Andric // - If we loaded one definition from an AST file and we've just found a
20450b57cec5SDimitry Andric // corresponding definition in a module map file, or
2046fe013be4SDimitry Andric bool LoadedFromASTFile = Existing->IsFromModuleFile;
2047fe013be4SDimitry Andric // - If we previously inferred this module from different module map file.
2048fe013be4SDimitry Andric bool Inferred = Existing->IsInferred;
2049fe013be4SDimitry Andric // - If we're building a framework that vends a module map, we might've
2050fe013be4SDimitry Andric // previously seen the one in intermediate products and now the system
2051fe013be4SDimitry Andric // one.
2052fe013be4SDimitry Andric // FIXME: If we're parsing module map file that looks like this:
2053fe013be4SDimitry Andric // framework module FW { ... }
2054fe013be4SDimitry Andric // module FW.Sub { ... }
2055fe013be4SDimitry Andric // We can't check the framework qualifier, since it's not attached to
2056fe013be4SDimitry Andric // the definition of Sub. Checking that qualifier on \c Existing is
2057fe013be4SDimitry Andric // not correct either, since we might've previously seen:
2058fe013be4SDimitry Andric // module FW { ... }
2059fe013be4SDimitry Andric // module FW.Sub { ... }
2060fe013be4SDimitry Andric // We should enforce consistency of redefinitions so that we can rely
2061fe013be4SDimitry Andric // that \c Existing is part of a framework iff the redefinition of FW
2062fe013be4SDimitry Andric // we have just skipped had it too. Once we do that, stop checking
2063fe013be4SDimitry Andric // the local framework qualifier and only rely on \c Existing.
2064fe013be4SDimitry Andric bool PartOfFramework = Framework || Existing->isPartOfFramework();
20650b57cec5SDimitry Andric // - If we're building a (preprocessed) module and we've just loaded the
20660b57cec5SDimitry Andric // module map file from which it was created.
20670b57cec5SDimitry Andric bool ParsedAsMainInput =
20680b57cec5SDimitry Andric Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
20690b57cec5SDimitry Andric Map.LangOpts.CurrentModule == ModuleName &&
20700b57cec5SDimitry Andric SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
20710b57cec5SDimitry Andric SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
2072fe013be4SDimitry Andric if (LoadedFromASTFile || Inferred || PartOfFramework || ParsedAsMainInput) {
2073fe013be4SDimitry Andric ActiveModule = PreviousActiveModule;
20740b57cec5SDimitry Andric // Skip the module definition.
20750b57cec5SDimitry Andric skipUntil(MMToken::RBrace);
20760b57cec5SDimitry Andric if (Tok.is(MMToken::RBrace))
20770b57cec5SDimitry Andric consumeToken();
20780b57cec5SDimitry Andric else {
20790b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
20800b57cec5SDimitry Andric Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
20810b57cec5SDimitry Andric HadError = true;
20820b57cec5SDimitry Andric }
20830b57cec5SDimitry Andric return;
20840b57cec5SDimitry Andric }
20850b57cec5SDimitry Andric
20860b57cec5SDimitry Andric if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
20870b57cec5SDimitry Andric ShadowingModule = Existing;
20880b57cec5SDimitry Andric } else {
20890b57cec5SDimitry Andric // This is not a shawdowed module decl, it is an illegal redefinition.
20900b57cec5SDimitry Andric Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
20910b57cec5SDimitry Andric << ModuleName;
20920b57cec5SDimitry Andric Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
20930b57cec5SDimitry Andric
20940b57cec5SDimitry Andric // Skip the module definition.
20950b57cec5SDimitry Andric skipUntil(MMToken::RBrace);
20960b57cec5SDimitry Andric if (Tok.is(MMToken::RBrace))
20970b57cec5SDimitry Andric consumeToken();
20980b57cec5SDimitry Andric
20990b57cec5SDimitry Andric HadError = true;
21000b57cec5SDimitry Andric return;
21010b57cec5SDimitry Andric }
21020b57cec5SDimitry Andric }
21030b57cec5SDimitry Andric
21040b57cec5SDimitry Andric // Start defining this module.
21050b57cec5SDimitry Andric if (ShadowingModule) {
21060b57cec5SDimitry Andric ActiveModule =
21070b57cec5SDimitry Andric Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
21080b57cec5SDimitry Andric } else {
21090b57cec5SDimitry Andric ActiveModule =
21100b57cec5SDimitry Andric Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
21110b57cec5SDimitry Andric .first;
21120b57cec5SDimitry Andric }
21130b57cec5SDimitry Andric
21140b57cec5SDimitry Andric ActiveModule->DefinitionLoc = ModuleNameLoc;
21150b57cec5SDimitry Andric if (Attrs.IsSystem || IsSystem)
21160b57cec5SDimitry Andric ActiveModule->IsSystem = true;
21170b57cec5SDimitry Andric if (Attrs.IsExternC)
21180b57cec5SDimitry Andric ActiveModule->IsExternC = true;
2119bdd1243dSDimitry Andric if (Attrs.NoUndeclaredIncludes)
21200b57cec5SDimitry Andric ActiveModule->NoUndeclaredIncludes = true;
21210b57cec5SDimitry Andric ActiveModule->Directory = Directory;
21220b57cec5SDimitry Andric
2123c9157d92SDimitry Andric StringRef MapFileName(ModuleMapFile.getName());
2124c9157d92SDimitry Andric if (MapFileName.ends_with("module.private.modulemap") ||
2125c9157d92SDimitry Andric MapFileName.ends_with("module_private.map")) {
21260b57cec5SDimitry Andric ActiveModule->ModuleMapIsPrivate = true;
21270b57cec5SDimitry Andric }
21280b57cec5SDimitry Andric
21290b57cec5SDimitry Andric // Private modules named as FooPrivate, Foo.Private or similar are likely a
21300b57cec5SDimitry Andric // user error; provide warnings, notes and fixits to direct users to use
21310b57cec5SDimitry Andric // Foo_Private instead.
21320b57cec5SDimitry Andric SourceLocation StartLoc =
21330b57cec5SDimitry Andric SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
21340b57cec5SDimitry Andric if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
21350b57cec5SDimitry Andric !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
21360b57cec5SDimitry Andric StartLoc) &&
21370b57cec5SDimitry Andric !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
21380b57cec5SDimitry Andric StartLoc) &&
21390b57cec5SDimitry Andric ActiveModule->ModuleMapIsPrivate)
21400b57cec5SDimitry Andric diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
21410b57cec5SDimitry Andric
21420b57cec5SDimitry Andric bool Done = false;
21430b57cec5SDimitry Andric do {
21440b57cec5SDimitry Andric switch (Tok.Kind) {
21450b57cec5SDimitry Andric case MMToken::EndOfFile:
21460b57cec5SDimitry Andric case MMToken::RBrace:
21470b57cec5SDimitry Andric Done = true;
21480b57cec5SDimitry Andric break;
21490b57cec5SDimitry Andric
21500b57cec5SDimitry Andric case MMToken::ConfigMacros:
21510b57cec5SDimitry Andric parseConfigMacros();
21520b57cec5SDimitry Andric break;
21530b57cec5SDimitry Andric
21540b57cec5SDimitry Andric case MMToken::Conflict:
21550b57cec5SDimitry Andric parseConflict();
21560b57cec5SDimitry Andric break;
21570b57cec5SDimitry Andric
21580b57cec5SDimitry Andric case MMToken::ExplicitKeyword:
21590b57cec5SDimitry Andric case MMToken::ExternKeyword:
21600b57cec5SDimitry Andric case MMToken::FrameworkKeyword:
21610b57cec5SDimitry Andric case MMToken::ModuleKeyword:
21620b57cec5SDimitry Andric parseModuleDecl();
21630b57cec5SDimitry Andric break;
21640b57cec5SDimitry Andric
21650b57cec5SDimitry Andric case MMToken::ExportKeyword:
21660b57cec5SDimitry Andric parseExportDecl();
21670b57cec5SDimitry Andric break;
21680b57cec5SDimitry Andric
21690b57cec5SDimitry Andric case MMToken::ExportAsKeyword:
21700b57cec5SDimitry Andric parseExportAsDecl();
21710b57cec5SDimitry Andric break;
21720b57cec5SDimitry Andric
21730b57cec5SDimitry Andric case MMToken::UseKeyword:
21740b57cec5SDimitry Andric parseUseDecl();
21750b57cec5SDimitry Andric break;
21760b57cec5SDimitry Andric
21770b57cec5SDimitry Andric case MMToken::RequiresKeyword:
21780b57cec5SDimitry Andric parseRequiresDecl();
21790b57cec5SDimitry Andric break;
21800b57cec5SDimitry Andric
21810b57cec5SDimitry Andric case MMToken::TextualKeyword:
21820b57cec5SDimitry Andric parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
21830b57cec5SDimitry Andric break;
21840b57cec5SDimitry Andric
21850b57cec5SDimitry Andric case MMToken::UmbrellaKeyword: {
21860b57cec5SDimitry Andric SourceLocation UmbrellaLoc = consumeToken();
21870b57cec5SDimitry Andric if (Tok.is(MMToken::HeaderKeyword))
21880b57cec5SDimitry Andric parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
21890b57cec5SDimitry Andric else
21900b57cec5SDimitry Andric parseUmbrellaDirDecl(UmbrellaLoc);
21910b57cec5SDimitry Andric break;
21920b57cec5SDimitry Andric }
21930b57cec5SDimitry Andric
21940b57cec5SDimitry Andric case MMToken::ExcludeKeyword:
21950b57cec5SDimitry Andric parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
21960b57cec5SDimitry Andric break;
21970b57cec5SDimitry Andric
21980b57cec5SDimitry Andric case MMToken::PrivateKeyword:
21990b57cec5SDimitry Andric parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
22000b57cec5SDimitry Andric break;
22010b57cec5SDimitry Andric
22020b57cec5SDimitry Andric case MMToken::HeaderKeyword:
22030b57cec5SDimitry Andric parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
22040b57cec5SDimitry Andric break;
22050b57cec5SDimitry Andric
22060b57cec5SDimitry Andric case MMToken::LinkKeyword:
22070b57cec5SDimitry Andric parseLinkDecl();
22080b57cec5SDimitry Andric break;
22090b57cec5SDimitry Andric
22100b57cec5SDimitry Andric default:
22110b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
22120b57cec5SDimitry Andric consumeToken();
22130b57cec5SDimitry Andric break;
22140b57cec5SDimitry Andric }
22150b57cec5SDimitry Andric } while (!Done);
22160b57cec5SDimitry Andric
22170b57cec5SDimitry Andric if (Tok.is(MMToken::RBrace))
22180b57cec5SDimitry Andric consumeToken();
22190b57cec5SDimitry Andric else {
22200b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
22210b57cec5SDimitry Andric Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
22220b57cec5SDimitry Andric HadError = true;
22230b57cec5SDimitry Andric }
22240b57cec5SDimitry Andric
22250b57cec5SDimitry Andric // If the active module is a top-level framework, and there are no link
22260b57cec5SDimitry Andric // libraries, automatically link against the framework.
22270b57cec5SDimitry Andric if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
2228fe013be4SDimitry Andric ActiveModule->LinkLibraries.empty())
2229fe013be4SDimitry Andric inferFrameworkLink(ActiveModule);
22300b57cec5SDimitry Andric
22310b57cec5SDimitry Andric // If the module meets all requirements but is still unavailable, mark the
22320b57cec5SDimitry Andric // whole tree as unavailable to prevent it from building.
22335ffd83dbSDimitry Andric if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
22340b57cec5SDimitry Andric ActiveModule->Parent) {
22355ffd83dbSDimitry Andric ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false);
22360b57cec5SDimitry Andric ActiveModule->getTopLevelModule()->MissingHeaders.append(
22370b57cec5SDimitry Andric ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
22380b57cec5SDimitry Andric }
22390b57cec5SDimitry Andric
22400b57cec5SDimitry Andric // We're done parsing this module. Pop back to the previous module.
22410b57cec5SDimitry Andric ActiveModule = PreviousActiveModule;
22420b57cec5SDimitry Andric }
22430b57cec5SDimitry Andric
22440b57cec5SDimitry Andric /// Parse an extern module declaration.
22450b57cec5SDimitry Andric ///
22460b57cec5SDimitry Andric /// extern module-declaration:
22470b57cec5SDimitry Andric /// 'extern' 'module' module-id string-literal
parseExternModuleDecl()22480b57cec5SDimitry Andric void ModuleMapParser::parseExternModuleDecl() {
22490b57cec5SDimitry Andric assert(Tok.is(MMToken::ExternKeyword));
22500b57cec5SDimitry Andric SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
22510b57cec5SDimitry Andric
22520b57cec5SDimitry Andric // Parse 'module' keyword.
22530b57cec5SDimitry Andric if (!Tok.is(MMToken::ModuleKeyword)) {
22540b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
22550b57cec5SDimitry Andric consumeToken();
22560b57cec5SDimitry Andric HadError = true;
22570b57cec5SDimitry Andric return;
22580b57cec5SDimitry Andric }
22590b57cec5SDimitry Andric consumeToken(); // 'module' keyword
22600b57cec5SDimitry Andric
22610b57cec5SDimitry Andric // Parse the module name.
22620b57cec5SDimitry Andric ModuleId Id;
22630b57cec5SDimitry Andric if (parseModuleId(Id)) {
22640b57cec5SDimitry Andric HadError = true;
22650b57cec5SDimitry Andric return;
22660b57cec5SDimitry Andric }
22670b57cec5SDimitry Andric
22680b57cec5SDimitry Andric // Parse the referenced module map file name.
22690b57cec5SDimitry Andric if (!Tok.is(MMToken::StringLiteral)) {
22700b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
22710b57cec5SDimitry Andric HadError = true;
22720b57cec5SDimitry Andric return;
22730b57cec5SDimitry Andric }
22745ffd83dbSDimitry Andric std::string FileName = std::string(Tok.getString());
22750b57cec5SDimitry Andric consumeToken(); // filename
22760b57cec5SDimitry Andric
22770b57cec5SDimitry Andric StringRef FileNameRef = FileName;
22780b57cec5SDimitry Andric SmallString<128> ModuleMapFileName;
22790b57cec5SDimitry Andric if (llvm::sys::path::is_relative(FileNameRef)) {
2280fe013be4SDimitry Andric ModuleMapFileName += Directory.getName();
22810b57cec5SDimitry Andric llvm::sys::path::append(ModuleMapFileName, FileName);
22820b57cec5SDimitry Andric FileNameRef = ModuleMapFileName;
22830b57cec5SDimitry Andric }
2284fe013be4SDimitry Andric if (auto File = SourceMgr.getFileManager().getOptionalFileRef(FileNameRef))
22850b57cec5SDimitry Andric Map.parseModuleMapFile(
2286349cc55cSDimitry Andric *File, IsSystem,
22870b57cec5SDimitry Andric Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
22880b57cec5SDimitry Andric ? Directory
2289fe013be4SDimitry Andric : File->getDir(),
22900b57cec5SDimitry Andric FileID(), nullptr, ExternLoc);
22910b57cec5SDimitry Andric }
22920b57cec5SDimitry Andric
22930b57cec5SDimitry Andric /// Whether to add the requirement \p Feature to the module \p M.
22940b57cec5SDimitry Andric ///
22950b57cec5SDimitry Andric /// This preserves backwards compatibility for two hacks in the Darwin system
22960b57cec5SDimitry Andric /// module map files:
22970b57cec5SDimitry Andric ///
22980b57cec5SDimitry Andric /// 1. The use of 'requires excluded' to make headers non-modular, which
22990b57cec5SDimitry Andric /// should really be mapped to 'textual' now that we have this feature. We
23000b57cec5SDimitry Andric /// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
23010b57cec5SDimitry Andric /// true. Later, this bit will be used to map all the headers inside this
23020b57cec5SDimitry Andric /// module to 'textual'.
23030b57cec5SDimitry Andric ///
23040b57cec5SDimitry Andric /// This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
23050b57cec5SDimitry Andric ///
23060b57cec5SDimitry Andric /// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement
23070b57cec5SDimitry Andric /// was never correct and causes issues now that we check it, so drop it.
shouldAddRequirement(Module * M,StringRef Feature,bool & IsRequiresExcludedHack)23080b57cec5SDimitry Andric static bool shouldAddRequirement(Module *M, StringRef Feature,
23090b57cec5SDimitry Andric bool &IsRequiresExcludedHack) {
23100b57cec5SDimitry Andric if (Feature == "excluded" &&
23110b57cec5SDimitry Andric (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
23120b57cec5SDimitry Andric M->fullModuleNameIs({"Tcl", "Private"}))) {
23130b57cec5SDimitry Andric IsRequiresExcludedHack = true;
23140b57cec5SDimitry Andric return false;
23150b57cec5SDimitry Andric } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
23160b57cec5SDimitry Andric return false;
23170b57cec5SDimitry Andric }
23180b57cec5SDimitry Andric
23190b57cec5SDimitry Andric return true;
23200b57cec5SDimitry Andric }
23210b57cec5SDimitry Andric
23220b57cec5SDimitry Andric /// Parse a requires declaration.
23230b57cec5SDimitry Andric ///
23240b57cec5SDimitry Andric /// requires-declaration:
23250b57cec5SDimitry Andric /// 'requires' feature-list
23260b57cec5SDimitry Andric ///
23270b57cec5SDimitry Andric /// feature-list:
23280b57cec5SDimitry Andric /// feature ',' feature-list
23290b57cec5SDimitry Andric /// feature
23300b57cec5SDimitry Andric ///
23310b57cec5SDimitry Andric /// feature:
23320b57cec5SDimitry Andric /// '!'[opt] identifier
parseRequiresDecl()23330b57cec5SDimitry Andric void ModuleMapParser::parseRequiresDecl() {
23340b57cec5SDimitry Andric assert(Tok.is(MMToken::RequiresKeyword));
23350b57cec5SDimitry Andric
23360b57cec5SDimitry Andric // Parse 'requires' keyword.
23370b57cec5SDimitry Andric consumeToken();
23380b57cec5SDimitry Andric
23390b57cec5SDimitry Andric // Parse the feature-list.
23400b57cec5SDimitry Andric do {
23410b57cec5SDimitry Andric bool RequiredState = true;
23420b57cec5SDimitry Andric if (Tok.is(MMToken::Exclaim)) {
23430b57cec5SDimitry Andric RequiredState = false;
23440b57cec5SDimitry Andric consumeToken();
23450b57cec5SDimitry Andric }
23460b57cec5SDimitry Andric
23470b57cec5SDimitry Andric if (!Tok.is(MMToken::Identifier)) {
23480b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
23490b57cec5SDimitry Andric HadError = true;
23500b57cec5SDimitry Andric return;
23510b57cec5SDimitry Andric }
23520b57cec5SDimitry Andric
23530b57cec5SDimitry Andric // Consume the feature name.
23545ffd83dbSDimitry Andric std::string Feature = std::string(Tok.getString());
23550b57cec5SDimitry Andric consumeToken();
23560b57cec5SDimitry Andric
23570b57cec5SDimitry Andric bool IsRequiresExcludedHack = false;
23580b57cec5SDimitry Andric bool ShouldAddRequirement =
23590b57cec5SDimitry Andric shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
23600b57cec5SDimitry Andric
23610b57cec5SDimitry Andric if (IsRequiresExcludedHack)
23620b57cec5SDimitry Andric UsesRequiresExcludedHack.insert(ActiveModule);
23630b57cec5SDimitry Andric
23640b57cec5SDimitry Andric if (ShouldAddRequirement) {
23650b57cec5SDimitry Andric // Add this feature.
23660b57cec5SDimitry Andric ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
23670b57cec5SDimitry Andric *Map.Target);
23680b57cec5SDimitry Andric }
23690b57cec5SDimitry Andric
23700b57cec5SDimitry Andric if (!Tok.is(MMToken::Comma))
23710b57cec5SDimitry Andric break;
23720b57cec5SDimitry Andric
23730b57cec5SDimitry Andric // Consume the comma.
23740b57cec5SDimitry Andric consumeToken();
23750b57cec5SDimitry Andric } while (true);
23760b57cec5SDimitry Andric }
23770b57cec5SDimitry Andric
23780b57cec5SDimitry Andric /// Parse a header declaration.
23790b57cec5SDimitry Andric ///
23800b57cec5SDimitry Andric /// header-declaration:
23810b57cec5SDimitry Andric /// 'textual'[opt] 'header' string-literal
23820b57cec5SDimitry Andric /// 'private' 'textual'[opt] 'header' string-literal
23830b57cec5SDimitry Andric /// 'exclude' 'header' string-literal
23840b57cec5SDimitry Andric /// 'umbrella' 'header' string-literal
23850b57cec5SDimitry Andric ///
23860b57cec5SDimitry Andric /// FIXME: Support 'private textual header'.
parseHeaderDecl(MMToken::TokenKind LeadingToken,SourceLocation LeadingLoc)23870b57cec5SDimitry Andric void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
23880b57cec5SDimitry Andric SourceLocation LeadingLoc) {
23890b57cec5SDimitry Andric // We've already consumed the first token.
23900b57cec5SDimitry Andric ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
2391bdd1243dSDimitry Andric
23920b57cec5SDimitry Andric if (LeadingToken == MMToken::PrivateKeyword) {
23930b57cec5SDimitry Andric Role = ModuleMap::PrivateHeader;
23940b57cec5SDimitry Andric // 'private' may optionally be followed by 'textual'.
23950b57cec5SDimitry Andric if (Tok.is(MMToken::TextualKeyword)) {
23960b57cec5SDimitry Andric LeadingToken = Tok.Kind;
23970b57cec5SDimitry Andric consumeToken();
23980b57cec5SDimitry Andric }
2399bdd1243dSDimitry Andric } else if (LeadingToken == MMToken::ExcludeKeyword) {
2400bdd1243dSDimitry Andric Role = ModuleMap::ExcludedHeader;
24010b57cec5SDimitry Andric }
24020b57cec5SDimitry Andric
24030b57cec5SDimitry Andric if (LeadingToken == MMToken::TextualKeyword)
24040b57cec5SDimitry Andric Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
24050b57cec5SDimitry Andric
24060b57cec5SDimitry Andric if (UsesRequiresExcludedHack.count(ActiveModule)) {
24070b57cec5SDimitry Andric // Mark this header 'textual' (see doc comment for
24080b57cec5SDimitry Andric // Module::UsesRequiresExcludedHack).
24090b57cec5SDimitry Andric Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
24100b57cec5SDimitry Andric }
24110b57cec5SDimitry Andric
24120b57cec5SDimitry Andric if (LeadingToken != MMToken::HeaderKeyword) {
24130b57cec5SDimitry Andric if (!Tok.is(MMToken::HeaderKeyword)) {
24140b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
24150b57cec5SDimitry Andric << (LeadingToken == MMToken::PrivateKeyword ? "private" :
24160b57cec5SDimitry Andric LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
24170b57cec5SDimitry Andric LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
24180b57cec5SDimitry Andric return;
24190b57cec5SDimitry Andric }
24200b57cec5SDimitry Andric consumeToken();
24210b57cec5SDimitry Andric }
24220b57cec5SDimitry Andric
24230b57cec5SDimitry Andric // Parse the header name.
24240b57cec5SDimitry Andric if (!Tok.is(MMToken::StringLiteral)) {
24250b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
24260b57cec5SDimitry Andric << "header";
24270b57cec5SDimitry Andric HadError = true;
24280b57cec5SDimitry Andric return;
24290b57cec5SDimitry Andric }
24300b57cec5SDimitry Andric Module::UnresolvedHeaderDirective Header;
24315ffd83dbSDimitry Andric Header.FileName = std::string(Tok.getString());
24320b57cec5SDimitry Andric Header.FileNameLoc = consumeToken();
24330b57cec5SDimitry Andric Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
2434bdd1243dSDimitry Andric Header.Kind = Map.headerRoleToKind(Role);
24350b57cec5SDimitry Andric
24360b57cec5SDimitry Andric // Check whether we already have an umbrella.
2437c9157d92SDimitry Andric if (Header.IsUmbrella &&
2438c9157d92SDimitry Andric !std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
24390b57cec5SDimitry Andric Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
24400b57cec5SDimitry Andric << ActiveModule->getFullModuleName();
24410b57cec5SDimitry Andric HadError = true;
24420b57cec5SDimitry Andric return;
24430b57cec5SDimitry Andric }
24440b57cec5SDimitry Andric
24450b57cec5SDimitry Andric // If we were given stat information, parse it so we can skip looking for
24460b57cec5SDimitry Andric // the file.
24470b57cec5SDimitry Andric if (Tok.is(MMToken::LBrace)) {
24480b57cec5SDimitry Andric SourceLocation LBraceLoc = consumeToken();
24490b57cec5SDimitry Andric
24500b57cec5SDimitry Andric while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
24510b57cec5SDimitry Andric enum Attribute { Size, ModTime, Unknown };
24520b57cec5SDimitry Andric StringRef Str = Tok.getString();
24530b57cec5SDimitry Andric SourceLocation Loc = consumeToken();
24540b57cec5SDimitry Andric switch (llvm::StringSwitch<Attribute>(Str)
24550b57cec5SDimitry Andric .Case("size", Size)
24560b57cec5SDimitry Andric .Case("mtime", ModTime)
24570b57cec5SDimitry Andric .Default(Unknown)) {
24580b57cec5SDimitry Andric case Size:
24590b57cec5SDimitry Andric if (Header.Size)
24600b57cec5SDimitry Andric Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
24610b57cec5SDimitry Andric if (!Tok.is(MMToken::IntegerLiteral)) {
24620b57cec5SDimitry Andric Diags.Report(Tok.getLocation(),
24630b57cec5SDimitry Andric diag::err_mmap_invalid_header_attribute_value) << Str;
24640b57cec5SDimitry Andric skipUntil(MMToken::RBrace);
24650b57cec5SDimitry Andric break;
24660b57cec5SDimitry Andric }
24670b57cec5SDimitry Andric Header.Size = Tok.getInteger();
24680b57cec5SDimitry Andric consumeToken();
24690b57cec5SDimitry Andric break;
24700b57cec5SDimitry Andric
24710b57cec5SDimitry Andric case ModTime:
24720b57cec5SDimitry Andric if (Header.ModTime)
24730b57cec5SDimitry Andric Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
24740b57cec5SDimitry Andric if (!Tok.is(MMToken::IntegerLiteral)) {
24750b57cec5SDimitry Andric Diags.Report(Tok.getLocation(),
24760b57cec5SDimitry Andric diag::err_mmap_invalid_header_attribute_value) << Str;
24770b57cec5SDimitry Andric skipUntil(MMToken::RBrace);
24780b57cec5SDimitry Andric break;
24790b57cec5SDimitry Andric }
24800b57cec5SDimitry Andric Header.ModTime = Tok.getInteger();
24810b57cec5SDimitry Andric consumeToken();
24820b57cec5SDimitry Andric break;
24830b57cec5SDimitry Andric
24840b57cec5SDimitry Andric case Unknown:
24850b57cec5SDimitry Andric Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
24860b57cec5SDimitry Andric skipUntil(MMToken::RBrace);
24870b57cec5SDimitry Andric break;
24880b57cec5SDimitry Andric }
24890b57cec5SDimitry Andric }
24900b57cec5SDimitry Andric
24910b57cec5SDimitry Andric if (Tok.is(MMToken::RBrace))
24920b57cec5SDimitry Andric consumeToken();
24930b57cec5SDimitry Andric else {
24940b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
24950b57cec5SDimitry Andric Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
24960b57cec5SDimitry Andric HadError = true;
24970b57cec5SDimitry Andric }
24980b57cec5SDimitry Andric }
24990b57cec5SDimitry Andric
25000b57cec5SDimitry Andric bool NeedsFramework = false;
2501*c9eafe97SDimitry Andric // Don't add headers to the builtin modules if the builtin headers belong to
2502*c9eafe97SDimitry Andric // the system modules, with the exception of __stddef_max_align_t.h which
2503*c9eafe97SDimitry Andric // always had its own module.
2504*c9eafe97SDimitry Andric if (!Map.LangOpts.BuiltinHeadersInSystemModules ||
2505*c9eafe97SDimitry Andric !isBuiltInModuleName(ActiveModule->getTopLevelModuleName()) ||
2506*c9eafe97SDimitry Andric ActiveModule->fullModuleNameIs({"_Builtin_stddef", "max_align_t"}))
25070b57cec5SDimitry Andric Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
25080b57cec5SDimitry Andric
2509fe013be4SDimitry Andric if (NeedsFramework)
25100b57cec5SDimitry Andric Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
25110b57cec5SDimitry Andric << ActiveModule->getFullModuleName()
25120b57cec5SDimitry Andric << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
25130b57cec5SDimitry Andric }
25140b57cec5SDimitry Andric
compareModuleHeaders(const Module::Header & A,const Module::Header & B)25154aee07d5SDimitry Andric static bool compareModuleHeaders(const Module::Header &A,
25164aee07d5SDimitry Andric const Module::Header &B) {
25174aee07d5SDimitry Andric return A.NameAsWritten < B.NameAsWritten;
25180b57cec5SDimitry Andric }
25190b57cec5SDimitry Andric
25200b57cec5SDimitry Andric /// Parse an umbrella directory declaration.
25210b57cec5SDimitry Andric ///
25220b57cec5SDimitry Andric /// umbrella-dir-declaration:
25230b57cec5SDimitry Andric /// umbrella string-literal
parseUmbrellaDirDecl(SourceLocation UmbrellaLoc)25240b57cec5SDimitry Andric void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
25250b57cec5SDimitry Andric // Parse the directory name.
25260b57cec5SDimitry Andric if (!Tok.is(MMToken::StringLiteral)) {
25270b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
25280b57cec5SDimitry Andric << "umbrella";
25290b57cec5SDimitry Andric HadError = true;
25300b57cec5SDimitry Andric return;
25310b57cec5SDimitry Andric }
25320b57cec5SDimitry Andric
25335ffd83dbSDimitry Andric std::string DirName = std::string(Tok.getString());
2534fe6060f1SDimitry Andric std::string DirNameAsWritten = DirName;
25350b57cec5SDimitry Andric SourceLocation DirNameLoc = consumeToken();
25360b57cec5SDimitry Andric
25370b57cec5SDimitry Andric // Check whether we already have an umbrella.
2538c9157d92SDimitry Andric if (!std::holds_alternative<std::monostate>(ActiveModule->Umbrella)) {
25390b57cec5SDimitry Andric Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
25400b57cec5SDimitry Andric << ActiveModule->getFullModuleName();
25410b57cec5SDimitry Andric HadError = true;
25420b57cec5SDimitry Andric return;
25430b57cec5SDimitry Andric }
25440b57cec5SDimitry Andric
25450b57cec5SDimitry Andric // Look for this file.
2546fe013be4SDimitry Andric OptionalDirectoryEntryRef Dir;
2547a7dea167SDimitry Andric if (llvm::sys::path::is_absolute(DirName)) {
2548fe013be4SDimitry Andric Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(DirName);
2549a7dea167SDimitry Andric } else {
25500b57cec5SDimitry Andric SmallString<128> PathName;
2551fe013be4SDimitry Andric PathName = Directory.getName();
25520b57cec5SDimitry Andric llvm::sys::path::append(PathName, DirName);
2553fe013be4SDimitry Andric Dir = SourceMgr.getFileManager().getOptionalDirectoryRef(PathName);
25540b57cec5SDimitry Andric }
25550b57cec5SDimitry Andric
25560b57cec5SDimitry Andric if (!Dir) {
25570b57cec5SDimitry Andric Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
25580b57cec5SDimitry Andric << DirName;
25590b57cec5SDimitry Andric return;
25600b57cec5SDimitry Andric }
25610b57cec5SDimitry Andric
25620b57cec5SDimitry Andric if (UsesRequiresExcludedHack.count(ActiveModule)) {
25630b57cec5SDimitry Andric // Mark this header 'textual' (see doc comment for
25640b57cec5SDimitry Andric // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
25650b57cec5SDimitry Andric // directory is relatively expensive, in practice this only applies to the
25660b57cec5SDimitry Andric // uncommonly used Tcl module on Darwin platforms.
25670b57cec5SDimitry Andric std::error_code EC;
25680b57cec5SDimitry Andric SmallVector<Module::Header, 6> Headers;
25690b57cec5SDimitry Andric llvm::vfs::FileSystem &FS =
25700b57cec5SDimitry Andric SourceMgr.getFileManager().getVirtualFileSystem();
25710b57cec5SDimitry Andric for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
25720b57cec5SDimitry Andric I != E && !EC; I.increment(EC)) {
2573bdd1243dSDimitry Andric if (auto FE = SourceMgr.getFileManager().getOptionalFileRef(I->path())) {
2574fe013be4SDimitry Andric Module::Header Header = {"", std::string(I->path()), *FE};
25750b57cec5SDimitry Andric Headers.push_back(std::move(Header));
25760b57cec5SDimitry Andric }
25770b57cec5SDimitry Andric }
25780b57cec5SDimitry Andric
25790b57cec5SDimitry Andric // Sort header paths so that the pcm doesn't depend on iteration order.
25804aee07d5SDimitry Andric std::stable_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
25810b57cec5SDimitry Andric
25820b57cec5SDimitry Andric for (auto &Header : Headers)
25830b57cec5SDimitry Andric Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
25840b57cec5SDimitry Andric return;
25850b57cec5SDimitry Andric }
25860b57cec5SDimitry Andric
2587fe013be4SDimitry Andric if (Module *OwningModule = Map.UmbrellaDirs[*Dir]) {
25880b57cec5SDimitry Andric Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
25890b57cec5SDimitry Andric << OwningModule->getFullModuleName();
25900b57cec5SDimitry Andric HadError = true;
25910b57cec5SDimitry Andric return;
25920b57cec5SDimitry Andric }
25930b57cec5SDimitry Andric
25940b57cec5SDimitry Andric // Record this umbrella directory.
2595fe013be4SDimitry Andric Map.setUmbrellaDirAsWritten(ActiveModule, *Dir, DirNameAsWritten, DirName);
25960b57cec5SDimitry Andric }
25970b57cec5SDimitry Andric
25980b57cec5SDimitry Andric /// Parse a module export declaration.
25990b57cec5SDimitry Andric ///
26000b57cec5SDimitry Andric /// export-declaration:
26010b57cec5SDimitry Andric /// 'export' wildcard-module-id
26020b57cec5SDimitry Andric ///
26030b57cec5SDimitry Andric /// wildcard-module-id:
26040b57cec5SDimitry Andric /// identifier
26050b57cec5SDimitry Andric /// '*'
26060b57cec5SDimitry Andric /// identifier '.' wildcard-module-id
parseExportDecl()26070b57cec5SDimitry Andric void ModuleMapParser::parseExportDecl() {
26080b57cec5SDimitry Andric assert(Tok.is(MMToken::ExportKeyword));
26090b57cec5SDimitry Andric SourceLocation ExportLoc = consumeToken();
26100b57cec5SDimitry Andric
26110b57cec5SDimitry Andric // Parse the module-id with an optional wildcard at the end.
26120b57cec5SDimitry Andric ModuleId ParsedModuleId;
26130b57cec5SDimitry Andric bool Wildcard = false;
26140b57cec5SDimitry Andric do {
26150b57cec5SDimitry Andric // FIXME: Support string-literal module names here.
26160b57cec5SDimitry Andric if (Tok.is(MMToken::Identifier)) {
26175ffd83dbSDimitry Andric ParsedModuleId.push_back(
26185ffd83dbSDimitry Andric std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
26190b57cec5SDimitry Andric consumeToken();
26200b57cec5SDimitry Andric
26210b57cec5SDimitry Andric if (Tok.is(MMToken::Period)) {
26220b57cec5SDimitry Andric consumeToken();
26230b57cec5SDimitry Andric continue;
26240b57cec5SDimitry Andric }
26250b57cec5SDimitry Andric
26260b57cec5SDimitry Andric break;
26270b57cec5SDimitry Andric }
26280b57cec5SDimitry Andric
26290b57cec5SDimitry Andric if(Tok.is(MMToken::Star)) {
26300b57cec5SDimitry Andric Wildcard = true;
26310b57cec5SDimitry Andric consumeToken();
26320b57cec5SDimitry Andric break;
26330b57cec5SDimitry Andric }
26340b57cec5SDimitry Andric
26350b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
26360b57cec5SDimitry Andric HadError = true;
26370b57cec5SDimitry Andric return;
26380b57cec5SDimitry Andric } while (true);
26390b57cec5SDimitry Andric
26400b57cec5SDimitry Andric Module::UnresolvedExportDecl Unresolved = {
26410b57cec5SDimitry Andric ExportLoc, ParsedModuleId, Wildcard
26420b57cec5SDimitry Andric };
26430b57cec5SDimitry Andric ActiveModule->UnresolvedExports.push_back(Unresolved);
26440b57cec5SDimitry Andric }
26450b57cec5SDimitry Andric
26460b57cec5SDimitry Andric /// Parse a module export_as declaration.
26470b57cec5SDimitry Andric ///
26480b57cec5SDimitry Andric /// export-as-declaration:
26490b57cec5SDimitry Andric /// 'export_as' identifier
parseExportAsDecl()26500b57cec5SDimitry Andric void ModuleMapParser::parseExportAsDecl() {
26510b57cec5SDimitry Andric assert(Tok.is(MMToken::ExportAsKeyword));
26520b57cec5SDimitry Andric consumeToken();
26530b57cec5SDimitry Andric
26540b57cec5SDimitry Andric if (!Tok.is(MMToken::Identifier)) {
26550b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
26560b57cec5SDimitry Andric HadError = true;
26570b57cec5SDimitry Andric return;
26580b57cec5SDimitry Andric }
26590b57cec5SDimitry Andric
26600b57cec5SDimitry Andric if (ActiveModule->Parent) {
26610b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
26620b57cec5SDimitry Andric consumeToken();
26630b57cec5SDimitry Andric return;
26640b57cec5SDimitry Andric }
26650b57cec5SDimitry Andric
26660b57cec5SDimitry Andric if (!ActiveModule->ExportAsModule.empty()) {
26670b57cec5SDimitry Andric if (ActiveModule->ExportAsModule == Tok.getString()) {
26680b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
26690b57cec5SDimitry Andric << ActiveModule->Name << Tok.getString();
26700b57cec5SDimitry Andric } else {
26710b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
26720b57cec5SDimitry Andric << ActiveModule->Name << ActiveModule->ExportAsModule
26730b57cec5SDimitry Andric << Tok.getString();
26740b57cec5SDimitry Andric }
26750b57cec5SDimitry Andric }
26760b57cec5SDimitry Andric
26775ffd83dbSDimitry Andric ActiveModule->ExportAsModule = std::string(Tok.getString());
26780b57cec5SDimitry Andric Map.addLinkAsDependency(ActiveModule);
26790b57cec5SDimitry Andric
26800b57cec5SDimitry Andric consumeToken();
26810b57cec5SDimitry Andric }
26820b57cec5SDimitry Andric
26830b57cec5SDimitry Andric /// Parse a module use declaration.
26840b57cec5SDimitry Andric ///
26850b57cec5SDimitry Andric /// use-declaration:
26860b57cec5SDimitry Andric /// 'use' wildcard-module-id
parseUseDecl()26870b57cec5SDimitry Andric void ModuleMapParser::parseUseDecl() {
26880b57cec5SDimitry Andric assert(Tok.is(MMToken::UseKeyword));
26890b57cec5SDimitry Andric auto KWLoc = consumeToken();
26900b57cec5SDimitry Andric // Parse the module-id.
26910b57cec5SDimitry Andric ModuleId ParsedModuleId;
26920b57cec5SDimitry Andric parseModuleId(ParsedModuleId);
26930b57cec5SDimitry Andric
26940b57cec5SDimitry Andric if (ActiveModule->Parent)
26950b57cec5SDimitry Andric Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
26960b57cec5SDimitry Andric else
26970b57cec5SDimitry Andric ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
26980b57cec5SDimitry Andric }
26990b57cec5SDimitry Andric
27000b57cec5SDimitry Andric /// Parse a link declaration.
27010b57cec5SDimitry Andric ///
27020b57cec5SDimitry Andric /// module-declaration:
27030b57cec5SDimitry Andric /// 'link' 'framework'[opt] string-literal
parseLinkDecl()27040b57cec5SDimitry Andric void ModuleMapParser::parseLinkDecl() {
27050b57cec5SDimitry Andric assert(Tok.is(MMToken::LinkKeyword));
27060b57cec5SDimitry Andric SourceLocation LinkLoc = consumeToken();
27070b57cec5SDimitry Andric
27080b57cec5SDimitry Andric // Parse the optional 'framework' keyword.
27090b57cec5SDimitry Andric bool IsFramework = false;
27100b57cec5SDimitry Andric if (Tok.is(MMToken::FrameworkKeyword)) {
27110b57cec5SDimitry Andric consumeToken();
27120b57cec5SDimitry Andric IsFramework = true;
27130b57cec5SDimitry Andric }
27140b57cec5SDimitry Andric
27150b57cec5SDimitry Andric // Parse the library name
27160b57cec5SDimitry Andric if (!Tok.is(MMToken::StringLiteral)) {
27170b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
27180b57cec5SDimitry Andric << IsFramework << SourceRange(LinkLoc);
27190b57cec5SDimitry Andric HadError = true;
27200b57cec5SDimitry Andric return;
27210b57cec5SDimitry Andric }
27220b57cec5SDimitry Andric
27235ffd83dbSDimitry Andric std::string LibraryName = std::string(Tok.getString());
27240b57cec5SDimitry Andric consumeToken();
27250b57cec5SDimitry Andric ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
27260b57cec5SDimitry Andric IsFramework));
27270b57cec5SDimitry Andric }
27280b57cec5SDimitry Andric
27290b57cec5SDimitry Andric /// Parse a configuration macro declaration.
27300b57cec5SDimitry Andric ///
27310b57cec5SDimitry Andric /// module-declaration:
27320b57cec5SDimitry Andric /// 'config_macros' attributes[opt] config-macro-list?
27330b57cec5SDimitry Andric ///
27340b57cec5SDimitry Andric /// config-macro-list:
27350b57cec5SDimitry Andric /// identifier (',' identifier)?
parseConfigMacros()27360b57cec5SDimitry Andric void ModuleMapParser::parseConfigMacros() {
27370b57cec5SDimitry Andric assert(Tok.is(MMToken::ConfigMacros));
27380b57cec5SDimitry Andric SourceLocation ConfigMacrosLoc = consumeToken();
27390b57cec5SDimitry Andric
27400b57cec5SDimitry Andric // Only top-level modules can have configuration macros.
27410b57cec5SDimitry Andric if (ActiveModule->Parent) {
27420b57cec5SDimitry Andric Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
27430b57cec5SDimitry Andric }
27440b57cec5SDimitry Andric
27450b57cec5SDimitry Andric // Parse the optional attributes.
27460b57cec5SDimitry Andric Attributes Attrs;
27470b57cec5SDimitry Andric if (parseOptionalAttributes(Attrs))
27480b57cec5SDimitry Andric return;
27490b57cec5SDimitry Andric
27500b57cec5SDimitry Andric if (Attrs.IsExhaustive && !ActiveModule->Parent) {
27510b57cec5SDimitry Andric ActiveModule->ConfigMacrosExhaustive = true;
27520b57cec5SDimitry Andric }
27530b57cec5SDimitry Andric
27540b57cec5SDimitry Andric // If we don't have an identifier, we're done.
27550b57cec5SDimitry Andric // FIXME: Support macros with the same name as a keyword here.
27560b57cec5SDimitry Andric if (!Tok.is(MMToken::Identifier))
27570b57cec5SDimitry Andric return;
27580b57cec5SDimitry Andric
27590b57cec5SDimitry Andric // Consume the first identifier.
27600b57cec5SDimitry Andric if (!ActiveModule->Parent) {
27610b57cec5SDimitry Andric ActiveModule->ConfigMacros.push_back(Tok.getString().str());
27620b57cec5SDimitry Andric }
27630b57cec5SDimitry Andric consumeToken();
27640b57cec5SDimitry Andric
27650b57cec5SDimitry Andric do {
27660b57cec5SDimitry Andric // If there's a comma, consume it.
27670b57cec5SDimitry Andric if (!Tok.is(MMToken::Comma))
27680b57cec5SDimitry Andric break;
27690b57cec5SDimitry Andric consumeToken();
27700b57cec5SDimitry Andric
27710b57cec5SDimitry Andric // We expect to see a macro name here.
27720b57cec5SDimitry Andric // FIXME: Support macros with the same name as a keyword here.
27730b57cec5SDimitry Andric if (!Tok.is(MMToken::Identifier)) {
27740b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
27750b57cec5SDimitry Andric break;
27760b57cec5SDimitry Andric }
27770b57cec5SDimitry Andric
27780b57cec5SDimitry Andric // Consume the macro name.
27790b57cec5SDimitry Andric if (!ActiveModule->Parent) {
27800b57cec5SDimitry Andric ActiveModule->ConfigMacros.push_back(Tok.getString().str());
27810b57cec5SDimitry Andric }
27820b57cec5SDimitry Andric consumeToken();
27830b57cec5SDimitry Andric } while (true);
27840b57cec5SDimitry Andric }
27850b57cec5SDimitry Andric
27860b57cec5SDimitry Andric /// Format a module-id into a string.
formatModuleId(const ModuleId & Id)27870b57cec5SDimitry Andric static std::string formatModuleId(const ModuleId &Id) {
27880b57cec5SDimitry Andric std::string result;
27890b57cec5SDimitry Andric {
27900b57cec5SDimitry Andric llvm::raw_string_ostream OS(result);
27910b57cec5SDimitry Andric
27920b57cec5SDimitry Andric for (unsigned I = 0, N = Id.size(); I != N; ++I) {
27930b57cec5SDimitry Andric if (I)
27940b57cec5SDimitry Andric OS << ".";
27950b57cec5SDimitry Andric OS << Id[I].first;
27960b57cec5SDimitry Andric }
27970b57cec5SDimitry Andric }
27980b57cec5SDimitry Andric
27990b57cec5SDimitry Andric return result;
28000b57cec5SDimitry Andric }
28010b57cec5SDimitry Andric
28020b57cec5SDimitry Andric /// Parse a conflict declaration.
28030b57cec5SDimitry Andric ///
28040b57cec5SDimitry Andric /// module-declaration:
28050b57cec5SDimitry Andric /// 'conflict' module-id ',' string-literal
parseConflict()28060b57cec5SDimitry Andric void ModuleMapParser::parseConflict() {
28070b57cec5SDimitry Andric assert(Tok.is(MMToken::Conflict));
28080b57cec5SDimitry Andric SourceLocation ConflictLoc = consumeToken();
28090b57cec5SDimitry Andric Module::UnresolvedConflict Conflict;
28100b57cec5SDimitry Andric
28110b57cec5SDimitry Andric // Parse the module-id.
28120b57cec5SDimitry Andric if (parseModuleId(Conflict.Id))
28130b57cec5SDimitry Andric return;
28140b57cec5SDimitry Andric
28150b57cec5SDimitry Andric // Parse the ','.
28160b57cec5SDimitry Andric if (!Tok.is(MMToken::Comma)) {
28170b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
28180b57cec5SDimitry Andric << SourceRange(ConflictLoc);
28190b57cec5SDimitry Andric return;
28200b57cec5SDimitry Andric }
28210b57cec5SDimitry Andric consumeToken();
28220b57cec5SDimitry Andric
28230b57cec5SDimitry Andric // Parse the message.
28240b57cec5SDimitry Andric if (!Tok.is(MMToken::StringLiteral)) {
28250b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
28260b57cec5SDimitry Andric << formatModuleId(Conflict.Id);
28270b57cec5SDimitry Andric return;
28280b57cec5SDimitry Andric }
28290b57cec5SDimitry Andric Conflict.Message = Tok.getString().str();
28300b57cec5SDimitry Andric consumeToken();
28310b57cec5SDimitry Andric
28320b57cec5SDimitry Andric // Add this unresolved conflict.
28330b57cec5SDimitry Andric ActiveModule->UnresolvedConflicts.push_back(Conflict);
28340b57cec5SDimitry Andric }
28350b57cec5SDimitry Andric
28360b57cec5SDimitry Andric /// Parse an inferred module declaration (wildcard modules).
28370b57cec5SDimitry Andric ///
28380b57cec5SDimitry Andric /// module-declaration:
28390b57cec5SDimitry Andric /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
28400b57cec5SDimitry Andric /// { inferred-module-member* }
28410b57cec5SDimitry Andric ///
28420b57cec5SDimitry Andric /// inferred-module-member:
28430b57cec5SDimitry Andric /// 'export' '*'
28440b57cec5SDimitry Andric /// 'exclude' identifier
parseInferredModuleDecl(bool Framework,bool Explicit)28450b57cec5SDimitry Andric void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
28460b57cec5SDimitry Andric assert(Tok.is(MMToken::Star));
28470b57cec5SDimitry Andric SourceLocation StarLoc = consumeToken();
28480b57cec5SDimitry Andric bool Failed = false;
28490b57cec5SDimitry Andric
28500b57cec5SDimitry Andric // Inferred modules must be submodules.
28510b57cec5SDimitry Andric if (!ActiveModule && !Framework) {
28520b57cec5SDimitry Andric Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
28530b57cec5SDimitry Andric Failed = true;
28540b57cec5SDimitry Andric }
28550b57cec5SDimitry Andric
28560b57cec5SDimitry Andric if (ActiveModule) {
28570b57cec5SDimitry Andric // Inferred modules must have umbrella directories.
28580b57cec5SDimitry Andric if (!Failed && ActiveModule->IsAvailable &&
2859fe013be4SDimitry Andric !ActiveModule->getEffectiveUmbrellaDir()) {
28600b57cec5SDimitry Andric Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
28610b57cec5SDimitry Andric Failed = true;
28620b57cec5SDimitry Andric }
28630b57cec5SDimitry Andric
28640b57cec5SDimitry Andric // Check for redefinition of an inferred module.
28650b57cec5SDimitry Andric if (!Failed && ActiveModule->InferSubmodules) {
28660b57cec5SDimitry Andric Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
28670b57cec5SDimitry Andric if (ActiveModule->InferredSubmoduleLoc.isValid())
28680b57cec5SDimitry Andric Diags.Report(ActiveModule->InferredSubmoduleLoc,
28690b57cec5SDimitry Andric diag::note_mmap_prev_definition);
28700b57cec5SDimitry Andric Failed = true;
28710b57cec5SDimitry Andric }
28720b57cec5SDimitry Andric
28730b57cec5SDimitry Andric // Check for the 'framework' keyword, which is not permitted here.
28740b57cec5SDimitry Andric if (Framework) {
28750b57cec5SDimitry Andric Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
28760b57cec5SDimitry Andric Framework = false;
28770b57cec5SDimitry Andric }
28780b57cec5SDimitry Andric } else if (Explicit) {
28790b57cec5SDimitry Andric Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
28800b57cec5SDimitry Andric Explicit = false;
28810b57cec5SDimitry Andric }
28820b57cec5SDimitry Andric
28830b57cec5SDimitry Andric // If there were any problems with this inferred submodule, skip its body.
28840b57cec5SDimitry Andric if (Failed) {
28850b57cec5SDimitry Andric if (Tok.is(MMToken::LBrace)) {
28860b57cec5SDimitry Andric consumeToken();
28870b57cec5SDimitry Andric skipUntil(MMToken::RBrace);
28880b57cec5SDimitry Andric if (Tok.is(MMToken::RBrace))
28890b57cec5SDimitry Andric consumeToken();
28900b57cec5SDimitry Andric }
28910b57cec5SDimitry Andric HadError = true;
28920b57cec5SDimitry Andric return;
28930b57cec5SDimitry Andric }
28940b57cec5SDimitry Andric
28950b57cec5SDimitry Andric // Parse optional attributes.
28960b57cec5SDimitry Andric Attributes Attrs;
28970b57cec5SDimitry Andric if (parseOptionalAttributes(Attrs))
28980b57cec5SDimitry Andric return;
28990b57cec5SDimitry Andric
29000b57cec5SDimitry Andric if (ActiveModule) {
29010b57cec5SDimitry Andric // Note that we have an inferred submodule.
29020b57cec5SDimitry Andric ActiveModule->InferSubmodules = true;
29030b57cec5SDimitry Andric ActiveModule->InferredSubmoduleLoc = StarLoc;
29040b57cec5SDimitry Andric ActiveModule->InferExplicitSubmodules = Explicit;
29050b57cec5SDimitry Andric } else {
29060b57cec5SDimitry Andric // We'll be inferring framework modules for this directory.
29070b57cec5SDimitry Andric Map.InferredDirectories[Directory].InferModules = true;
29080b57cec5SDimitry Andric Map.InferredDirectories[Directory].Attrs = Attrs;
29090b57cec5SDimitry Andric Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
29100b57cec5SDimitry Andric // FIXME: Handle the 'framework' keyword.
29110b57cec5SDimitry Andric }
29120b57cec5SDimitry Andric
29130b57cec5SDimitry Andric // Parse the opening brace.
29140b57cec5SDimitry Andric if (!Tok.is(MMToken::LBrace)) {
29150b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
29160b57cec5SDimitry Andric HadError = true;
29170b57cec5SDimitry Andric return;
29180b57cec5SDimitry Andric }
29190b57cec5SDimitry Andric SourceLocation LBraceLoc = consumeToken();
29200b57cec5SDimitry Andric
29210b57cec5SDimitry Andric // Parse the body of the inferred submodule.
29220b57cec5SDimitry Andric bool Done = false;
29230b57cec5SDimitry Andric do {
29240b57cec5SDimitry Andric switch (Tok.Kind) {
29250b57cec5SDimitry Andric case MMToken::EndOfFile:
29260b57cec5SDimitry Andric case MMToken::RBrace:
29270b57cec5SDimitry Andric Done = true;
29280b57cec5SDimitry Andric break;
29290b57cec5SDimitry Andric
29300b57cec5SDimitry Andric case MMToken::ExcludeKeyword:
29310b57cec5SDimitry Andric if (ActiveModule) {
29320b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
29330b57cec5SDimitry Andric << (ActiveModule != nullptr);
29340b57cec5SDimitry Andric consumeToken();
29350b57cec5SDimitry Andric break;
29360b57cec5SDimitry Andric }
29370b57cec5SDimitry Andric
29380b57cec5SDimitry Andric consumeToken();
29390b57cec5SDimitry Andric // FIXME: Support string-literal module names here.
29400b57cec5SDimitry Andric if (!Tok.is(MMToken::Identifier)) {
29410b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
29420b57cec5SDimitry Andric break;
29430b57cec5SDimitry Andric }
29440b57cec5SDimitry Andric
29455ffd83dbSDimitry Andric Map.InferredDirectories[Directory].ExcludedModules.push_back(
29465ffd83dbSDimitry Andric std::string(Tok.getString()));
29470b57cec5SDimitry Andric consumeToken();
29480b57cec5SDimitry Andric break;
29490b57cec5SDimitry Andric
29500b57cec5SDimitry Andric case MMToken::ExportKeyword:
29510b57cec5SDimitry Andric if (!ActiveModule) {
29520b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
29530b57cec5SDimitry Andric << (ActiveModule != nullptr);
29540b57cec5SDimitry Andric consumeToken();
29550b57cec5SDimitry Andric break;
29560b57cec5SDimitry Andric }
29570b57cec5SDimitry Andric
29580b57cec5SDimitry Andric consumeToken();
29590b57cec5SDimitry Andric if (Tok.is(MMToken::Star))
29600b57cec5SDimitry Andric ActiveModule->InferExportWildcard = true;
29610b57cec5SDimitry Andric else
29620b57cec5SDimitry Andric Diags.Report(Tok.getLocation(),
29630b57cec5SDimitry Andric diag::err_mmap_expected_export_wildcard);
29640b57cec5SDimitry Andric consumeToken();
29650b57cec5SDimitry Andric break;
29660b57cec5SDimitry Andric
29670b57cec5SDimitry Andric case MMToken::ExplicitKeyword:
29680b57cec5SDimitry Andric case MMToken::ModuleKeyword:
29690b57cec5SDimitry Andric case MMToken::HeaderKeyword:
29700b57cec5SDimitry Andric case MMToken::PrivateKeyword:
29710b57cec5SDimitry Andric case MMToken::UmbrellaKeyword:
29720b57cec5SDimitry Andric default:
29730b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
29740b57cec5SDimitry Andric << (ActiveModule != nullptr);
29750b57cec5SDimitry Andric consumeToken();
29760b57cec5SDimitry Andric break;
29770b57cec5SDimitry Andric }
29780b57cec5SDimitry Andric } while (!Done);
29790b57cec5SDimitry Andric
29800b57cec5SDimitry Andric if (Tok.is(MMToken::RBrace))
29810b57cec5SDimitry Andric consumeToken();
29820b57cec5SDimitry Andric else {
29830b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
29840b57cec5SDimitry Andric Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
29850b57cec5SDimitry Andric HadError = true;
29860b57cec5SDimitry Andric }
29870b57cec5SDimitry Andric }
29880b57cec5SDimitry Andric
29890b57cec5SDimitry Andric /// Parse optional attributes.
29900b57cec5SDimitry Andric ///
29910b57cec5SDimitry Andric /// attributes:
29920b57cec5SDimitry Andric /// attribute attributes
29930b57cec5SDimitry Andric /// attribute
29940b57cec5SDimitry Andric ///
29950b57cec5SDimitry Andric /// attribute:
29960b57cec5SDimitry Andric /// [ identifier ]
29970b57cec5SDimitry Andric ///
29980b57cec5SDimitry Andric /// \param Attrs Will be filled in with the parsed attributes.
29990b57cec5SDimitry Andric ///
30000b57cec5SDimitry Andric /// \returns true if an error occurred, false otherwise.
parseOptionalAttributes(Attributes & Attrs)30010b57cec5SDimitry Andric bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
30020b57cec5SDimitry Andric bool HadError = false;
30030b57cec5SDimitry Andric
30040b57cec5SDimitry Andric while (Tok.is(MMToken::LSquare)) {
30050b57cec5SDimitry Andric // Consume the '['.
30060b57cec5SDimitry Andric SourceLocation LSquareLoc = consumeToken();
30070b57cec5SDimitry Andric
30080b57cec5SDimitry Andric // Check whether we have an attribute name here.
30090b57cec5SDimitry Andric if (!Tok.is(MMToken::Identifier)) {
30100b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
30110b57cec5SDimitry Andric skipUntil(MMToken::RSquare);
30120b57cec5SDimitry Andric if (Tok.is(MMToken::RSquare))
30130b57cec5SDimitry Andric consumeToken();
30140b57cec5SDimitry Andric HadError = true;
30150b57cec5SDimitry Andric }
30160b57cec5SDimitry Andric
30170b57cec5SDimitry Andric // Decode the attribute name.
30180b57cec5SDimitry Andric AttributeKind Attribute
30190b57cec5SDimitry Andric = llvm::StringSwitch<AttributeKind>(Tok.getString())
30200b57cec5SDimitry Andric .Case("exhaustive", AT_exhaustive)
30210b57cec5SDimitry Andric .Case("extern_c", AT_extern_c)
30220b57cec5SDimitry Andric .Case("no_undeclared_includes", AT_no_undeclared_includes)
30230b57cec5SDimitry Andric .Case("system", AT_system)
30240b57cec5SDimitry Andric .Default(AT_unknown);
30250b57cec5SDimitry Andric switch (Attribute) {
30260b57cec5SDimitry Andric case AT_unknown:
30270b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
30280b57cec5SDimitry Andric << Tok.getString();
30290b57cec5SDimitry Andric break;
30300b57cec5SDimitry Andric
30310b57cec5SDimitry Andric case AT_system:
30320b57cec5SDimitry Andric Attrs.IsSystem = true;
30330b57cec5SDimitry Andric break;
30340b57cec5SDimitry Andric
30350b57cec5SDimitry Andric case AT_extern_c:
30360b57cec5SDimitry Andric Attrs.IsExternC = true;
30370b57cec5SDimitry Andric break;
30380b57cec5SDimitry Andric
30390b57cec5SDimitry Andric case AT_exhaustive:
30400b57cec5SDimitry Andric Attrs.IsExhaustive = true;
30410b57cec5SDimitry Andric break;
30420b57cec5SDimitry Andric
30430b57cec5SDimitry Andric case AT_no_undeclared_includes:
30440b57cec5SDimitry Andric Attrs.NoUndeclaredIncludes = true;
30450b57cec5SDimitry Andric break;
30460b57cec5SDimitry Andric }
30470b57cec5SDimitry Andric consumeToken();
30480b57cec5SDimitry Andric
30490b57cec5SDimitry Andric // Consume the ']'.
30500b57cec5SDimitry Andric if (!Tok.is(MMToken::RSquare)) {
30510b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
30520b57cec5SDimitry Andric Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
30530b57cec5SDimitry Andric skipUntil(MMToken::RSquare);
30540b57cec5SDimitry Andric HadError = true;
30550b57cec5SDimitry Andric }
30560b57cec5SDimitry Andric
30570b57cec5SDimitry Andric if (Tok.is(MMToken::RSquare))
30580b57cec5SDimitry Andric consumeToken();
30590b57cec5SDimitry Andric }
30600b57cec5SDimitry Andric
30610b57cec5SDimitry Andric return HadError;
30620b57cec5SDimitry Andric }
30630b57cec5SDimitry Andric
30640b57cec5SDimitry Andric /// Parse a module map file.
30650b57cec5SDimitry Andric ///
30660b57cec5SDimitry Andric /// module-map-file:
30670b57cec5SDimitry Andric /// module-declaration*
parseModuleMapFile()30680b57cec5SDimitry Andric bool ModuleMapParser::parseModuleMapFile() {
30690b57cec5SDimitry Andric do {
30700b57cec5SDimitry Andric switch (Tok.Kind) {
30710b57cec5SDimitry Andric case MMToken::EndOfFile:
30720b57cec5SDimitry Andric return HadError;
30730b57cec5SDimitry Andric
30740b57cec5SDimitry Andric case MMToken::ExplicitKeyword:
30750b57cec5SDimitry Andric case MMToken::ExternKeyword:
30760b57cec5SDimitry Andric case MMToken::ModuleKeyword:
30770b57cec5SDimitry Andric case MMToken::FrameworkKeyword:
30780b57cec5SDimitry Andric parseModuleDecl();
30790b57cec5SDimitry Andric break;
30800b57cec5SDimitry Andric
30810b57cec5SDimitry Andric case MMToken::Comma:
30820b57cec5SDimitry Andric case MMToken::ConfigMacros:
30830b57cec5SDimitry Andric case MMToken::Conflict:
30840b57cec5SDimitry Andric case MMToken::Exclaim:
30850b57cec5SDimitry Andric case MMToken::ExcludeKeyword:
30860b57cec5SDimitry Andric case MMToken::ExportKeyword:
30870b57cec5SDimitry Andric case MMToken::ExportAsKeyword:
30880b57cec5SDimitry Andric case MMToken::HeaderKeyword:
30890b57cec5SDimitry Andric case MMToken::Identifier:
30900b57cec5SDimitry Andric case MMToken::LBrace:
30910b57cec5SDimitry Andric case MMToken::LinkKeyword:
30920b57cec5SDimitry Andric case MMToken::LSquare:
30930b57cec5SDimitry Andric case MMToken::Period:
30940b57cec5SDimitry Andric case MMToken::PrivateKeyword:
30950b57cec5SDimitry Andric case MMToken::RBrace:
30960b57cec5SDimitry Andric case MMToken::RSquare:
30970b57cec5SDimitry Andric case MMToken::RequiresKeyword:
30980b57cec5SDimitry Andric case MMToken::Star:
30990b57cec5SDimitry Andric case MMToken::StringLiteral:
31000b57cec5SDimitry Andric case MMToken::IntegerLiteral:
31010b57cec5SDimitry Andric case MMToken::TextualKeyword:
31020b57cec5SDimitry Andric case MMToken::UmbrellaKeyword:
31030b57cec5SDimitry Andric case MMToken::UseKeyword:
31040b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
31050b57cec5SDimitry Andric HadError = true;
31060b57cec5SDimitry Andric consumeToken();
31070b57cec5SDimitry Andric break;
31080b57cec5SDimitry Andric }
31090b57cec5SDimitry Andric } while (true);
31100b57cec5SDimitry Andric }
31110b57cec5SDimitry Andric
parseModuleMapFile(FileEntryRef File,bool IsSystem,DirectoryEntryRef Dir,FileID ID,unsigned * Offset,SourceLocation ExternModuleLoc)3112c9157d92SDimitry Andric bool ModuleMap::parseModuleMapFile(FileEntryRef File, bool IsSystem,
3113fe013be4SDimitry Andric DirectoryEntryRef Dir, FileID ID,
31140b57cec5SDimitry Andric unsigned *Offset,
31150b57cec5SDimitry Andric SourceLocation ExternModuleLoc) {
31160b57cec5SDimitry Andric assert(Target && "Missing target information");
31170b57cec5SDimitry Andric llvm::DenseMap<const FileEntry *, bool>::iterator Known
31180b57cec5SDimitry Andric = ParsedModuleMap.find(File);
31190b57cec5SDimitry Andric if (Known != ParsedModuleMap.end())
31200b57cec5SDimitry Andric return Known->second;
31210b57cec5SDimitry Andric
31220b57cec5SDimitry Andric // If the module map file wasn't already entered, do so now.
31230b57cec5SDimitry Andric if (ID.isInvalid()) {
31240b57cec5SDimitry Andric auto FileCharacter =
31250b57cec5SDimitry Andric IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
31260b57cec5SDimitry Andric ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
31270b57cec5SDimitry Andric }
31280b57cec5SDimitry Andric
31290b57cec5SDimitry Andric assert(Target && "Missing target information");
3130bdd1243dSDimitry Andric std::optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
31310b57cec5SDimitry Andric if (!Buffer)
31320b57cec5SDimitry Andric return ParsedModuleMap[File] = true;
31330b57cec5SDimitry Andric assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
31340b57cec5SDimitry Andric "invalid buffer offset");
31350b57cec5SDimitry Andric
31360b57cec5SDimitry Andric // Parse this module map file.
31370b57cec5SDimitry Andric Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
31380b57cec5SDimitry Andric Buffer->getBufferStart(),
31390b57cec5SDimitry Andric Buffer->getBufferStart() + (Offset ? *Offset : 0),
31400b57cec5SDimitry Andric Buffer->getBufferEnd());
31410b57cec5SDimitry Andric SourceLocation Start = L.getSourceLocation();
31420b57cec5SDimitry Andric ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
31430b57cec5SDimitry Andric IsSystem);
31440b57cec5SDimitry Andric bool Result = Parser.parseModuleMapFile();
31450b57cec5SDimitry Andric ParsedModuleMap[File] = Result;
31460b57cec5SDimitry Andric
31470b57cec5SDimitry Andric if (Offset) {
31480b57cec5SDimitry Andric auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
31490b57cec5SDimitry Andric assert(Loc.first == ID && "stopped in a different file?");
31500b57cec5SDimitry Andric *Offset = Loc.second;
31510b57cec5SDimitry Andric }
31520b57cec5SDimitry Andric
31530b57cec5SDimitry Andric // Notify callbacks that we parsed it.
31540b57cec5SDimitry Andric for (const auto &Cb : Callbacks)
3155c9157d92SDimitry Andric Cb->moduleMapFileRead(Start, File, IsSystem);
31560b57cec5SDimitry Andric
31570b57cec5SDimitry Andric return Result;
31580b57cec5SDimitry Andric }
3159