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/None.h"
320b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
330b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
340b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
350b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
360b57cec5SDimitry Andric #include "llvm/ADT/StringMap.h"
370b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
380b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
390b57cec5SDimitry Andric #include "llvm/Support/Allocator.h"
400b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
410b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
420b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
430b57cec5SDimitry Andric #include "llvm/Support/Path.h"
440b57cec5SDimitry Andric #include "llvm/Support/VirtualFileSystem.h"
450b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
460b57cec5SDimitry Andric #include <algorithm>
470b57cec5SDimitry Andric #include <cassert>
480b57cec5SDimitry Andric #include <cstdint>
490b57cec5SDimitry Andric #include <cstring>
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 default: llvm_unreachable("unknown header role");
790b57cec5SDimitry Andric case NormalHeader:
800b57cec5SDimitry Andric return Module::HK_Normal;
810b57cec5SDimitry Andric case PrivateHeader:
820b57cec5SDimitry Andric return Module::HK_Private;
830b57cec5SDimitry Andric case TextualHeader:
840b57cec5SDimitry Andric return Module::HK_Textual;
850b57cec5SDimitry Andric case PrivateHeader | TextualHeader:
860b57cec5SDimitry Andric return Module::HK_PrivateTextual;
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric
900b57cec5SDimitry Andric ModuleMap::ModuleHeaderRole
headerKindToRole(Module::HeaderKind Kind)910b57cec5SDimitry Andric ModuleMap::headerKindToRole(Module::HeaderKind Kind) {
920b57cec5SDimitry Andric switch ((int)Kind) {
930b57cec5SDimitry Andric case Module::HK_Normal:
940b57cec5SDimitry Andric return NormalHeader;
950b57cec5SDimitry Andric case Module::HK_Private:
960b57cec5SDimitry Andric return PrivateHeader;
970b57cec5SDimitry Andric case Module::HK_Textual:
980b57cec5SDimitry Andric return TextualHeader;
990b57cec5SDimitry Andric case Module::HK_PrivateTextual:
1000b57cec5SDimitry Andric return ModuleHeaderRole(PrivateHeader | TextualHeader);
1010b57cec5SDimitry Andric case Module::HK_Excluded:
1020b57cec5SDimitry Andric llvm_unreachable("unexpected header kind");
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric llvm_unreachable("unknown header kind");
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric
1070b57cec5SDimitry Andric Module::ExportDecl
resolveExport(Module * Mod,const Module::UnresolvedExportDecl & Unresolved,bool Complain) const1080b57cec5SDimitry Andric ModuleMap::resolveExport(Module *Mod,
1090b57cec5SDimitry Andric const Module::UnresolvedExportDecl &Unresolved,
1100b57cec5SDimitry Andric bool Complain) const {
1110b57cec5SDimitry Andric // We may have just a wildcard.
1120b57cec5SDimitry Andric if (Unresolved.Id.empty()) {
1130b57cec5SDimitry Andric assert(Unresolved.Wildcard && "Invalid unresolved export");
1140b57cec5SDimitry Andric return Module::ExportDecl(nullptr, true);
1150b57cec5SDimitry Andric }
1160b57cec5SDimitry Andric
1170b57cec5SDimitry Andric // Resolve the module-id.
1180b57cec5SDimitry Andric Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain);
1190b57cec5SDimitry Andric if (!Context)
1200b57cec5SDimitry Andric return {};
1210b57cec5SDimitry Andric
1220b57cec5SDimitry Andric return Module::ExportDecl(Context, Unresolved.Wildcard);
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric
resolveModuleId(const ModuleId & Id,Module * Mod,bool Complain) const1250b57cec5SDimitry Andric Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod,
1260b57cec5SDimitry Andric bool Complain) const {
1270b57cec5SDimitry Andric // Find the starting module.
1280b57cec5SDimitry Andric Module *Context = lookupModuleUnqualified(Id[0].first, Mod);
1290b57cec5SDimitry Andric if (!Context) {
1300b57cec5SDimitry Andric if (Complain)
1310b57cec5SDimitry Andric Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified)
1320b57cec5SDimitry Andric << Id[0].first << Mod->getFullModuleName();
1330b57cec5SDimitry Andric
1340b57cec5SDimitry Andric return nullptr;
1350b57cec5SDimitry Andric }
1360b57cec5SDimitry Andric
1370b57cec5SDimitry Andric // Dig into the module path.
1380b57cec5SDimitry Andric for (unsigned I = 1, N = Id.size(); I != N; ++I) {
1390b57cec5SDimitry Andric Module *Sub = lookupModuleQualified(Id[I].first, Context);
1400b57cec5SDimitry Andric if (!Sub) {
1410b57cec5SDimitry Andric if (Complain)
1420b57cec5SDimitry Andric Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified)
1430b57cec5SDimitry Andric << Id[I].first << Context->getFullModuleName()
1440b57cec5SDimitry Andric << SourceRange(Id[0].second, Id[I-1].second);
1450b57cec5SDimitry Andric
1460b57cec5SDimitry Andric return nullptr;
1470b57cec5SDimitry Andric }
1480b57cec5SDimitry Andric
1490b57cec5SDimitry Andric Context = Sub;
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric
1520b57cec5SDimitry Andric return Context;
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric
1550b57cec5SDimitry Andric /// Append to \p Paths the set of paths needed to get to the
1560b57cec5SDimitry Andric /// subframework in which the given module lives.
appendSubframeworkPaths(Module * Mod,SmallVectorImpl<char> & Path)1570b57cec5SDimitry Andric static void appendSubframeworkPaths(Module *Mod,
1580b57cec5SDimitry Andric SmallVectorImpl<char> &Path) {
1590b57cec5SDimitry Andric // Collect the framework names from the given module to the top-level module.
1600b57cec5SDimitry Andric SmallVector<StringRef, 2> Paths;
1610b57cec5SDimitry Andric for (; Mod; Mod = Mod->Parent) {
1620b57cec5SDimitry Andric if (Mod->IsFramework)
1630b57cec5SDimitry Andric Paths.push_back(Mod->Name);
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric
1660b57cec5SDimitry Andric if (Paths.empty())
1670b57cec5SDimitry Andric return;
1680b57cec5SDimitry Andric
1690b57cec5SDimitry Andric // Add Frameworks/Name.framework for each subframework.
1700b57cec5SDimitry Andric for (unsigned I = Paths.size() - 1; I != 0; --I)
1710b57cec5SDimitry Andric llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework");
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric
findHeader(Module * M,const Module::UnresolvedHeaderDirective & Header,SmallVectorImpl<char> & RelativePathName,bool & NeedsFramework)174af732203SDimitry Andric Optional<FileEntryRef> ModuleMap::findHeader(
1750b57cec5SDimitry Andric Module *M, const Module::UnresolvedHeaderDirective &Header,
1760b57cec5SDimitry Andric SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) {
1770b57cec5SDimitry Andric // Search for the header file within the module's home directory.
1780b57cec5SDimitry Andric auto *Directory = M->Directory;
1790b57cec5SDimitry Andric SmallString<128> FullPathName(Directory->getName());
1800b57cec5SDimitry Andric
181af732203SDimitry Andric auto GetFile = [&](StringRef Filename) -> Optional<FileEntryRef> {
182af732203SDimitry Andric auto File =
183af732203SDimitry Andric expectedToOptional(SourceMgr.getFileManager().getFileRef(Filename));
184af732203SDimitry Andric if (!File || (Header.Size && File->getSize() != *Header.Size) ||
185af732203SDimitry Andric (Header.ModTime && File->getModificationTime() != *Header.ModTime))
186af732203SDimitry Andric return None;
187a7dea167SDimitry Andric return *File;
1880b57cec5SDimitry Andric };
1890b57cec5SDimitry Andric
190af732203SDimitry Andric auto GetFrameworkFile = [&]() -> Optional<FileEntryRef> {
1910b57cec5SDimitry Andric unsigned FullPathLength = FullPathName.size();
1920b57cec5SDimitry Andric appendSubframeworkPaths(M, RelativePathName);
1930b57cec5SDimitry Andric unsigned RelativePathLength = RelativePathName.size();
1940b57cec5SDimitry Andric
1950b57cec5SDimitry Andric // Check whether this file is in the public headers.
1960b57cec5SDimitry Andric llvm::sys::path::append(RelativePathName, "Headers", Header.FileName);
1970b57cec5SDimitry Andric llvm::sys::path::append(FullPathName, RelativePathName);
198af732203SDimitry Andric if (auto File = GetFile(FullPathName))
1990b57cec5SDimitry Andric return File;
2000b57cec5SDimitry Andric
2010b57cec5SDimitry Andric // Check whether this file is in the private headers.
2020b57cec5SDimitry Andric // Ideally, private modules in the form 'FrameworkName.Private' should
2030b57cec5SDimitry Andric // be defined as 'module FrameworkName.Private', and not as
2040b57cec5SDimitry Andric // 'framework module FrameworkName.Private', since a 'Private.Framework'
2050b57cec5SDimitry Andric // does not usually exist. However, since both are currently widely used
2060b57cec5SDimitry Andric // for private modules, make sure we find the right path in both cases.
2070b57cec5SDimitry Andric if (M->IsFramework && M->Name == "Private")
2080b57cec5SDimitry Andric RelativePathName.clear();
2090b57cec5SDimitry Andric else
2100b57cec5SDimitry Andric RelativePathName.resize(RelativePathLength);
2110b57cec5SDimitry Andric FullPathName.resize(FullPathLength);
2120b57cec5SDimitry Andric llvm::sys::path::append(RelativePathName, "PrivateHeaders",
2130b57cec5SDimitry Andric Header.FileName);
2140b57cec5SDimitry Andric llvm::sys::path::append(FullPathName, RelativePathName);
2150b57cec5SDimitry Andric return GetFile(FullPathName);
2160b57cec5SDimitry Andric };
2170b57cec5SDimitry Andric
2180b57cec5SDimitry Andric if (llvm::sys::path::is_absolute(Header.FileName)) {
2190b57cec5SDimitry Andric RelativePathName.clear();
2200b57cec5SDimitry Andric RelativePathName.append(Header.FileName.begin(), Header.FileName.end());
2210b57cec5SDimitry Andric return GetFile(Header.FileName);
2220b57cec5SDimitry Andric }
2230b57cec5SDimitry Andric
2240b57cec5SDimitry Andric if (M->isPartOfFramework())
2250b57cec5SDimitry Andric return GetFrameworkFile();
2260b57cec5SDimitry Andric
2270b57cec5SDimitry Andric // Lookup for normal headers.
2280b57cec5SDimitry Andric llvm::sys::path::append(RelativePathName, Header.FileName);
2290b57cec5SDimitry Andric llvm::sys::path::append(FullPathName, RelativePathName);
230af732203SDimitry Andric auto NormalHdrFile = GetFile(FullPathName);
2310b57cec5SDimitry Andric
232480093f4SDimitry Andric if (!NormalHdrFile && Directory->getName().endswith(".framework")) {
2330b57cec5SDimitry Andric // The lack of 'framework' keyword in a module declaration it's a simple
2340b57cec5SDimitry Andric // mistake we can diagnose when the header exists within the proper
2350b57cec5SDimitry Andric // framework style path.
2360b57cec5SDimitry Andric FullPathName.assign(Directory->getName());
2370b57cec5SDimitry Andric RelativePathName.clear();
2380b57cec5SDimitry Andric if (GetFrameworkFile()) {
2390b57cec5SDimitry Andric Diags.Report(Header.FileNameLoc,
2400b57cec5SDimitry Andric diag::warn_mmap_incomplete_framework_module_declaration)
2410b57cec5SDimitry Andric << Header.FileName << M->getFullModuleName();
2420b57cec5SDimitry Andric NeedsFramework = true;
2430b57cec5SDimitry Andric }
244af732203SDimitry Andric return None;
2450b57cec5SDimitry Andric }
2460b57cec5SDimitry Andric
2470b57cec5SDimitry Andric return NormalHdrFile;
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric
resolveHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header,bool & NeedsFramework)2500b57cec5SDimitry Andric void ModuleMap::resolveHeader(Module *Mod,
2510b57cec5SDimitry Andric const Module::UnresolvedHeaderDirective &Header,
2520b57cec5SDimitry Andric bool &NeedsFramework) {
2530b57cec5SDimitry Andric SmallString<128> RelativePathName;
254af732203SDimitry Andric if (Optional<FileEntryRef> File =
2550b57cec5SDimitry Andric findHeader(Mod, Header, RelativePathName, NeedsFramework)) {
2560b57cec5SDimitry Andric if (Header.IsUmbrella) {
257af732203SDimitry Andric const DirectoryEntry *UmbrellaDir = &File->getDir().getDirEntry();
2580b57cec5SDimitry Andric if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir])
2590b57cec5SDimitry Andric Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
2600b57cec5SDimitry Andric << UmbrellaMod->getFullModuleName();
2610b57cec5SDimitry Andric else
2620b57cec5SDimitry Andric // Record this umbrella header.
263*5f7ddb14SDimitry Andric setUmbrellaHeader(Mod, *File, Header.FileName, RelativePathName.str());
2640b57cec5SDimitry Andric } else {
265*5f7ddb14SDimitry Andric Module::Header H = {Header.FileName, std::string(RelativePathName.str()),
266*5f7ddb14SDimitry Andric *File};
2670b57cec5SDimitry Andric if (Header.Kind == Module::HK_Excluded)
2680b57cec5SDimitry Andric excludeHeader(Mod, H);
2690b57cec5SDimitry Andric else
2700b57cec5SDimitry Andric addHeader(Mod, H, headerKindToRole(Header.Kind));
2710b57cec5SDimitry Andric }
2720b57cec5SDimitry Andric } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) {
2730b57cec5SDimitry Andric // There's a builtin header but no corresponding on-disk header. Assume
2740b57cec5SDimitry Andric // this was supposed to modularize the builtin header alone.
2750b57cec5SDimitry Andric } else if (Header.Kind == Module::HK_Excluded) {
2760b57cec5SDimitry Andric // Ignore missing excluded header files. They're optional anyway.
2770b57cec5SDimitry Andric } else {
2780b57cec5SDimitry Andric // If we find a module that has a missing header, we mark this module as
2790b57cec5SDimitry Andric // unavailable and store the header directive for displaying diagnostics.
2800b57cec5SDimitry Andric Mod->MissingHeaders.push_back(Header);
2810b57cec5SDimitry Andric // A missing header with stat information doesn't make the module
2820b57cec5SDimitry Andric // unavailable; this keeps our behavior consistent as headers are lazily
2830b57cec5SDimitry Andric // resolved. (Such a module still can't be built though, except from
2840b57cec5SDimitry Andric // preprocessed source.)
2850b57cec5SDimitry Andric if (!Header.Size && !Header.ModTime)
2865ffd83dbSDimitry Andric Mod->markUnavailable(/*Unimportable=*/false);
2870b57cec5SDimitry Andric }
2880b57cec5SDimitry Andric }
2890b57cec5SDimitry Andric
resolveAsBuiltinHeader(Module * Mod,const Module::UnresolvedHeaderDirective & Header)2900b57cec5SDimitry Andric bool ModuleMap::resolveAsBuiltinHeader(
2910b57cec5SDimitry Andric Module *Mod, const Module::UnresolvedHeaderDirective &Header) {
2920b57cec5SDimitry Andric if (Header.Kind == Module::HK_Excluded ||
2930b57cec5SDimitry Andric llvm::sys::path::is_absolute(Header.FileName) ||
2940b57cec5SDimitry Andric Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella ||
2950b57cec5SDimitry Andric !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory ||
2960b57cec5SDimitry Andric !isBuiltinHeader(Header.FileName))
2970b57cec5SDimitry Andric return false;
2980b57cec5SDimitry Andric
2990b57cec5SDimitry Andric // This is a system module with a top-level header. This header
3000b57cec5SDimitry Andric // may have a counterpart (or replacement) in the set of headers
3010b57cec5SDimitry Andric // supplied by Clang. Find that builtin header.
3020b57cec5SDimitry Andric SmallString<128> Path;
3030b57cec5SDimitry Andric llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName);
304*5f7ddb14SDimitry Andric auto File = SourceMgr.getFileManager().getFile(Path);
3050b57cec5SDimitry Andric if (!File)
3060b57cec5SDimitry Andric return false;
3070b57cec5SDimitry Andric
3080b57cec5SDimitry Andric auto Role = headerKindToRole(Header.Kind);
309*5f7ddb14SDimitry Andric Module::Header H = {Header.FileName, std::string(Path.str()), *File};
3100b57cec5SDimitry Andric addHeader(Mod, H, Role);
3110b57cec5SDimitry Andric return true;
3120b57cec5SDimitry Andric }
3130b57cec5SDimitry Andric
ModuleMap(SourceManager & SourceMgr,DiagnosticsEngine & Diags,const LangOptions & LangOpts,const TargetInfo * Target,HeaderSearch & HeaderInfo)3140b57cec5SDimitry Andric ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
3150b57cec5SDimitry Andric const LangOptions &LangOpts, const TargetInfo *Target,
3160b57cec5SDimitry Andric HeaderSearch &HeaderInfo)
3170b57cec5SDimitry Andric : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
3180b57cec5SDimitry Andric HeaderInfo(HeaderInfo) {
3190b57cec5SDimitry Andric MMapLangOpts.LineComment = true;
3200b57cec5SDimitry Andric }
3210b57cec5SDimitry Andric
~ModuleMap()3220b57cec5SDimitry Andric ModuleMap::~ModuleMap() {
3230b57cec5SDimitry Andric for (auto &M : Modules)
3240b57cec5SDimitry Andric delete M.getValue();
3250b57cec5SDimitry Andric for (auto *M : ShadowModules)
3260b57cec5SDimitry Andric delete M;
3270b57cec5SDimitry Andric }
3280b57cec5SDimitry Andric
setTarget(const TargetInfo & Target)3290b57cec5SDimitry Andric void ModuleMap::setTarget(const TargetInfo &Target) {
3300b57cec5SDimitry Andric assert((!this->Target || this->Target == &Target) &&
3310b57cec5SDimitry Andric "Improper target override");
3320b57cec5SDimitry Andric this->Target = &Target;
3330b57cec5SDimitry Andric }
3340b57cec5SDimitry Andric
3350b57cec5SDimitry Andric /// "Sanitize" a filename so that it can be used as an identifier.
sanitizeFilenameAsIdentifier(StringRef Name,SmallVectorImpl<char> & Buffer)3360b57cec5SDimitry Andric static StringRef sanitizeFilenameAsIdentifier(StringRef Name,
3370b57cec5SDimitry Andric SmallVectorImpl<char> &Buffer) {
3380b57cec5SDimitry Andric if (Name.empty())
3390b57cec5SDimitry Andric return Name;
3400b57cec5SDimitry Andric
3410b57cec5SDimitry Andric if (!isValidIdentifier(Name)) {
3420b57cec5SDimitry Andric // If we don't already have something with the form of an identifier,
3430b57cec5SDimitry Andric // create a buffer with the sanitized name.
3440b57cec5SDimitry Andric Buffer.clear();
3450b57cec5SDimitry Andric if (isDigit(Name[0]))
3460b57cec5SDimitry Andric Buffer.push_back('_');
3470b57cec5SDimitry Andric Buffer.reserve(Buffer.size() + Name.size());
3480b57cec5SDimitry Andric for (unsigned I = 0, N = Name.size(); I != N; ++I) {
3490b57cec5SDimitry Andric if (isIdentifierBody(Name[I]))
3500b57cec5SDimitry Andric Buffer.push_back(Name[I]);
3510b57cec5SDimitry Andric else
3520b57cec5SDimitry Andric Buffer.push_back('_');
3530b57cec5SDimitry Andric }
3540b57cec5SDimitry Andric
3550b57cec5SDimitry Andric Name = StringRef(Buffer.data(), Buffer.size());
3560b57cec5SDimitry Andric }
3570b57cec5SDimitry Andric
3580b57cec5SDimitry Andric while (llvm::StringSwitch<bool>(Name)
3590b57cec5SDimitry Andric #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true)
3600b57cec5SDimitry Andric #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true)
3610b57cec5SDimitry Andric #include "clang/Basic/TokenKinds.def"
3620b57cec5SDimitry Andric .Default(false)) {
3630b57cec5SDimitry Andric if (Name.data() != Buffer.data())
3640b57cec5SDimitry Andric Buffer.append(Name.begin(), Name.end());
3650b57cec5SDimitry Andric Buffer.push_back('_');
3660b57cec5SDimitry Andric Name = StringRef(Buffer.data(), Buffer.size());
3670b57cec5SDimitry Andric }
3680b57cec5SDimitry Andric
3690b57cec5SDimitry Andric return Name;
3700b57cec5SDimitry Andric }
3710b57cec5SDimitry Andric
3720b57cec5SDimitry Andric /// Determine whether the given file name is the name of a builtin
3730b57cec5SDimitry Andric /// header, supplied by Clang to replace, override, or augment existing system
3740b57cec5SDimitry Andric /// headers.
isBuiltinHeader(StringRef FileName)3750b57cec5SDimitry Andric bool ModuleMap::isBuiltinHeader(StringRef FileName) {
3760b57cec5SDimitry Andric return llvm::StringSwitch<bool>(FileName)
3770b57cec5SDimitry Andric .Case("float.h", true)
3780b57cec5SDimitry Andric .Case("iso646.h", true)
3790b57cec5SDimitry Andric .Case("limits.h", true)
3800b57cec5SDimitry Andric .Case("stdalign.h", true)
3810b57cec5SDimitry Andric .Case("stdarg.h", true)
3820b57cec5SDimitry Andric .Case("stdatomic.h", true)
3830b57cec5SDimitry Andric .Case("stdbool.h", true)
3840b57cec5SDimitry Andric .Case("stddef.h", true)
3850b57cec5SDimitry Andric .Case("stdint.h", true)
3860b57cec5SDimitry Andric .Case("tgmath.h", true)
3870b57cec5SDimitry Andric .Case("unwind.h", true)
3880b57cec5SDimitry Andric .Default(false);
3890b57cec5SDimitry Andric }
3900b57cec5SDimitry Andric
isBuiltinHeader(const FileEntry * File)3915ffd83dbSDimitry Andric bool ModuleMap::isBuiltinHeader(const FileEntry *File) {
3925ffd83dbSDimitry Andric return File->getDir() == BuiltinIncludeDir &&
3935ffd83dbSDimitry Andric ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()));
3945ffd83dbSDimitry Andric }
3955ffd83dbSDimitry Andric
3960b57cec5SDimitry Andric ModuleMap::HeadersMap::iterator
findKnownHeader(const FileEntry * File)3970b57cec5SDimitry Andric ModuleMap::findKnownHeader(const FileEntry *File) {
3980b57cec5SDimitry Andric resolveHeaderDirectives(File);
3990b57cec5SDimitry Andric HeadersMap::iterator Known = Headers.find(File);
4000b57cec5SDimitry Andric if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
4015ffd83dbSDimitry Andric Known == Headers.end() && ModuleMap::isBuiltinHeader(File)) {
4020b57cec5SDimitry Andric HeaderInfo.loadTopLevelSystemModules();
4030b57cec5SDimitry Andric return Headers.find(File);
4040b57cec5SDimitry Andric }
4050b57cec5SDimitry Andric return Known;
4060b57cec5SDimitry Andric }
4070b57cec5SDimitry Andric
4080b57cec5SDimitry Andric ModuleMap::KnownHeader
findHeaderInUmbrellaDirs(const FileEntry * File,SmallVectorImpl<const DirectoryEntry * > & IntermediateDirs)4090b57cec5SDimitry Andric ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File,
4100b57cec5SDimitry Andric SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) {
4110b57cec5SDimitry Andric if (UmbrellaDirs.empty())
4120b57cec5SDimitry Andric return {};
4130b57cec5SDimitry Andric
4140b57cec5SDimitry Andric const DirectoryEntry *Dir = File->getDir();
4150b57cec5SDimitry Andric assert(Dir && "file in no directory");
4160b57cec5SDimitry Andric
4170b57cec5SDimitry Andric // Note: as an egregious but useful hack we use the real path here, because
4180b57cec5SDimitry Andric // frameworks moving from top-level frameworks to embedded frameworks tend
4190b57cec5SDimitry Andric // to be symlinked from the top-level location to the embedded location,
4200b57cec5SDimitry Andric // and we need to resolve lookups as if we had found the embedded location.
4210b57cec5SDimitry Andric StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir);
4220b57cec5SDimitry Andric
4230b57cec5SDimitry Andric // Keep walking up the directory hierarchy, looking for a directory with
4240b57cec5SDimitry Andric // an umbrella header.
4250b57cec5SDimitry Andric do {
4260b57cec5SDimitry Andric auto KnownDir = UmbrellaDirs.find(Dir);
4270b57cec5SDimitry Andric if (KnownDir != UmbrellaDirs.end())
4280b57cec5SDimitry Andric return KnownHeader(KnownDir->second, NormalHeader);
4290b57cec5SDimitry Andric
4300b57cec5SDimitry Andric IntermediateDirs.push_back(Dir);
4310b57cec5SDimitry Andric
4320b57cec5SDimitry Andric // Retrieve our parent path.
4330b57cec5SDimitry Andric DirName = llvm::sys::path::parent_path(DirName);
4340b57cec5SDimitry Andric if (DirName.empty())
4350b57cec5SDimitry Andric break;
4360b57cec5SDimitry Andric
4370b57cec5SDimitry Andric // Resolve the parent path to a directory entry.
438a7dea167SDimitry Andric if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName))
439a7dea167SDimitry Andric Dir = *DirEntry;
440a7dea167SDimitry Andric else
441a7dea167SDimitry Andric Dir = nullptr;
4420b57cec5SDimitry Andric } while (Dir);
4430b57cec5SDimitry Andric return {};
4440b57cec5SDimitry Andric }
4450b57cec5SDimitry Andric
violatesPrivateInclude(Module * RequestingModule,const FileEntry * IncFileEnt,ModuleMap::KnownHeader Header)4460b57cec5SDimitry Andric static bool violatesPrivateInclude(Module *RequestingModule,
4470b57cec5SDimitry Andric const FileEntry *IncFileEnt,
4480b57cec5SDimitry Andric ModuleMap::KnownHeader Header) {
4490b57cec5SDimitry Andric #ifndef NDEBUG
4500b57cec5SDimitry Andric if (Header.getRole() & ModuleMap::PrivateHeader) {
4510b57cec5SDimitry Andric // Check for consistency between the module header role
4520b57cec5SDimitry Andric // as obtained from the lookup and as obtained from the module.
4530b57cec5SDimitry Andric // This check is not cheap, so enable it only for debugging.
4540b57cec5SDimitry Andric bool IsPrivate = false;
4550b57cec5SDimitry Andric SmallVectorImpl<Module::Header> *HeaderList[] = {
4560b57cec5SDimitry Andric &Header.getModule()->Headers[Module::HK_Private],
4570b57cec5SDimitry Andric &Header.getModule()->Headers[Module::HK_PrivateTextual]};
4580b57cec5SDimitry Andric for (auto *Hs : HeaderList)
4590b57cec5SDimitry Andric IsPrivate |=
4600b57cec5SDimitry Andric std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) {
4610b57cec5SDimitry Andric return H.Entry == IncFileEnt;
4620b57cec5SDimitry Andric }) != Hs->end();
4630b57cec5SDimitry Andric assert(IsPrivate && "inconsistent headers and roles");
4640b57cec5SDimitry Andric }
4650b57cec5SDimitry Andric #endif
4660b57cec5SDimitry Andric return !Header.isAccessibleFrom(RequestingModule);
4670b57cec5SDimitry Andric }
4680b57cec5SDimitry Andric
getTopLevelOrNull(Module * M)4690b57cec5SDimitry Andric static Module *getTopLevelOrNull(Module *M) {
4700b57cec5SDimitry Andric return M ? M->getTopLevelModule() : nullptr;
4710b57cec5SDimitry Andric }
4720b57cec5SDimitry Andric
diagnoseHeaderInclusion(Module * RequestingModule,bool RequestingModuleIsModuleInterface,SourceLocation FilenameLoc,StringRef Filename,const FileEntry * File)4730b57cec5SDimitry Andric void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule,
4740b57cec5SDimitry Andric bool RequestingModuleIsModuleInterface,
4750b57cec5SDimitry Andric SourceLocation FilenameLoc,
4760b57cec5SDimitry Andric StringRef Filename,
4770b57cec5SDimitry Andric const FileEntry *File) {
4780b57cec5SDimitry Andric // No errors for indirect modules. This may be a bit of a problem for modules
4790b57cec5SDimitry Andric // with no source files.
4800b57cec5SDimitry Andric if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule))
4810b57cec5SDimitry Andric return;
4820b57cec5SDimitry Andric
4830b57cec5SDimitry Andric if (RequestingModule) {
4840b57cec5SDimitry Andric resolveUses(RequestingModule, /*Complain=*/false);
4850b57cec5SDimitry Andric resolveHeaderDirectives(RequestingModule);
4860b57cec5SDimitry Andric }
4870b57cec5SDimitry Andric
4880b57cec5SDimitry Andric bool Excluded = false;
4890b57cec5SDimitry Andric Module *Private = nullptr;
4900b57cec5SDimitry Andric Module *NotUsed = nullptr;
4910b57cec5SDimitry Andric
4920b57cec5SDimitry Andric HeadersMap::iterator Known = findKnownHeader(File);
4930b57cec5SDimitry Andric if (Known != Headers.end()) {
4940b57cec5SDimitry Andric for (const KnownHeader &Header : Known->second) {
4950b57cec5SDimitry Andric // Remember private headers for later printing of a diagnostic.
4960b57cec5SDimitry Andric if (violatesPrivateInclude(RequestingModule, File, Header)) {
4970b57cec5SDimitry Andric Private = Header.getModule();
4980b57cec5SDimitry Andric continue;
4990b57cec5SDimitry Andric }
5000b57cec5SDimitry Andric
5010b57cec5SDimitry Andric // If uses need to be specified explicitly, we are only allowed to return
5020b57cec5SDimitry Andric // modules that are explicitly used by the requesting module.
5030b57cec5SDimitry Andric if (RequestingModule && LangOpts.ModulesDeclUse &&
5040b57cec5SDimitry Andric !RequestingModule->directlyUses(Header.getModule())) {
5050b57cec5SDimitry Andric NotUsed = Header.getModule();
5060b57cec5SDimitry Andric continue;
5070b57cec5SDimitry Andric }
5080b57cec5SDimitry Andric
5090b57cec5SDimitry Andric // We have found a module that we can happily use.
5100b57cec5SDimitry Andric return;
5110b57cec5SDimitry Andric }
5120b57cec5SDimitry Andric
5130b57cec5SDimitry Andric Excluded = true;
5140b57cec5SDimitry Andric }
5150b57cec5SDimitry Andric
5160b57cec5SDimitry Andric // We have found a header, but it is private.
5170b57cec5SDimitry Andric if (Private) {
5180b57cec5SDimitry Andric Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module)
5190b57cec5SDimitry Andric << Filename;
5200b57cec5SDimitry Andric return;
5210b57cec5SDimitry Andric }
5220b57cec5SDimitry Andric
5230b57cec5SDimitry Andric // We have found a module, but we don't use it.
5240b57cec5SDimitry Andric if (NotUsed) {
5250b57cec5SDimitry Andric Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5260b57cec5SDimitry Andric << RequestingModule->getTopLevelModule()->Name << Filename;
5270b57cec5SDimitry Andric return;
5280b57cec5SDimitry Andric }
5290b57cec5SDimitry Andric
5300b57cec5SDimitry Andric if (Excluded || isHeaderInUmbrellaDirs(File))
5310b57cec5SDimitry Andric return;
5320b57cec5SDimitry Andric
5330b57cec5SDimitry Andric // At this point, only non-modular includes remain.
5340b57cec5SDimitry Andric
5350b57cec5SDimitry Andric if (RequestingModule && LangOpts.ModulesStrictDeclUse) {
5360b57cec5SDimitry Andric Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module)
5370b57cec5SDimitry Andric << RequestingModule->getTopLevelModule()->Name << Filename;
5380b57cec5SDimitry Andric } else if (RequestingModule && RequestingModuleIsModuleInterface &&
5390b57cec5SDimitry Andric LangOpts.isCompilingModule()) {
5400b57cec5SDimitry Andric // Do not diagnose when we are not compiling a module.
5410b57cec5SDimitry Andric diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ?
5420b57cec5SDimitry Andric diag::warn_non_modular_include_in_framework_module :
5430b57cec5SDimitry Andric diag::warn_non_modular_include_in_module;
5440b57cec5SDimitry Andric Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName()
5450b57cec5SDimitry Andric << File->getName();
5460b57cec5SDimitry Andric }
5470b57cec5SDimitry Andric }
5480b57cec5SDimitry Andric
isBetterKnownHeader(const ModuleMap::KnownHeader & New,const ModuleMap::KnownHeader & Old)5490b57cec5SDimitry Andric static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New,
5500b57cec5SDimitry Andric const ModuleMap::KnownHeader &Old) {
5510b57cec5SDimitry Andric // Prefer available modules.
5525ffd83dbSDimitry Andric // FIXME: Considering whether the module is available rather than merely
5535ffd83dbSDimitry Andric // importable is non-hermetic and can result in surprising behavior for
5545ffd83dbSDimitry Andric // prebuilt modules. Consider only checking for importability here.
5550b57cec5SDimitry Andric if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable())
5560b57cec5SDimitry Andric return true;
5570b57cec5SDimitry Andric
5580b57cec5SDimitry Andric // Prefer a public header over a private header.
5590b57cec5SDimitry Andric if ((New.getRole() & ModuleMap::PrivateHeader) !=
5600b57cec5SDimitry Andric (Old.getRole() & ModuleMap::PrivateHeader))
5610b57cec5SDimitry Andric return !(New.getRole() & ModuleMap::PrivateHeader);
5620b57cec5SDimitry Andric
5630b57cec5SDimitry Andric // Prefer a non-textual header over a textual header.
5640b57cec5SDimitry Andric if ((New.getRole() & ModuleMap::TextualHeader) !=
5650b57cec5SDimitry Andric (Old.getRole() & ModuleMap::TextualHeader))
5660b57cec5SDimitry Andric return !(New.getRole() & ModuleMap::TextualHeader);
5670b57cec5SDimitry Andric
5680b57cec5SDimitry Andric // Don't have a reason to choose between these. Just keep the first one.
5690b57cec5SDimitry Andric return false;
5700b57cec5SDimitry Andric }
5710b57cec5SDimitry Andric
findModuleForHeader(const FileEntry * File,bool AllowTextual)5720b57cec5SDimitry Andric ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
5730b57cec5SDimitry Andric bool AllowTextual) {
5740b57cec5SDimitry Andric auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
5750b57cec5SDimitry Andric if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
5760b57cec5SDimitry Andric return {};
5770b57cec5SDimitry Andric return R;
5780b57cec5SDimitry Andric };
5790b57cec5SDimitry Andric
5800b57cec5SDimitry Andric HeadersMap::iterator Known = findKnownHeader(File);
5810b57cec5SDimitry Andric if (Known != Headers.end()) {
5820b57cec5SDimitry Andric ModuleMap::KnownHeader Result;
5830b57cec5SDimitry Andric // Iterate over all modules that 'File' is part of to find the best fit.
5840b57cec5SDimitry Andric for (KnownHeader &H : Known->second) {
5850b57cec5SDimitry Andric // Prefer a header from the source module over all others.
5860b57cec5SDimitry Andric if (H.getModule()->getTopLevelModule() == SourceModule)
5870b57cec5SDimitry Andric return MakeResult(H);
5880b57cec5SDimitry Andric if (!Result || isBetterKnownHeader(H, Result))
5890b57cec5SDimitry Andric Result = H;
5900b57cec5SDimitry Andric }
5910b57cec5SDimitry Andric return MakeResult(Result);
5920b57cec5SDimitry Andric }
5930b57cec5SDimitry Andric
5940b57cec5SDimitry Andric return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File));
5950b57cec5SDimitry Andric }
5960b57cec5SDimitry Andric
5970b57cec5SDimitry Andric ModuleMap::KnownHeader
findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry * File)5980b57cec5SDimitry Andric ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) {
5990b57cec5SDimitry Andric assert(!Headers.count(File) && "already have a module for this header");
6000b57cec5SDimitry Andric
6010b57cec5SDimitry Andric SmallVector<const DirectoryEntry *, 2> SkippedDirs;
6020b57cec5SDimitry Andric KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs);
6030b57cec5SDimitry Andric if (H) {
6040b57cec5SDimitry Andric Module *Result = H.getModule();
6050b57cec5SDimitry Andric
6060b57cec5SDimitry Andric // Search up the module stack until we find a module with an umbrella
6070b57cec5SDimitry Andric // directory.
6080b57cec5SDimitry Andric Module *UmbrellaModule = Result;
6090b57cec5SDimitry Andric while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
6100b57cec5SDimitry Andric UmbrellaModule = UmbrellaModule->Parent;
6110b57cec5SDimitry Andric
6120b57cec5SDimitry Andric if (UmbrellaModule->InferSubmodules) {
6130b57cec5SDimitry Andric const FileEntry *UmbrellaModuleMap =
6140b57cec5SDimitry Andric getModuleMapFileForUniquing(UmbrellaModule);
6150b57cec5SDimitry Andric
6160b57cec5SDimitry Andric // Infer submodules for each of the directories we found between
6170b57cec5SDimitry Andric // the directory of the umbrella header and the directory where
6180b57cec5SDimitry Andric // the actual header is located.
6190b57cec5SDimitry Andric bool Explicit = UmbrellaModule->InferExplicitSubmodules;
6200b57cec5SDimitry Andric
6210b57cec5SDimitry Andric for (unsigned I = SkippedDirs.size(); I != 0; --I) {
6220b57cec5SDimitry Andric // Find or create the module that corresponds to this directory name.
6230b57cec5SDimitry Andric SmallString<32> NameBuf;
6240b57cec5SDimitry Andric StringRef Name = sanitizeFilenameAsIdentifier(
6250b57cec5SDimitry Andric llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf);
6260b57cec5SDimitry Andric Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6270b57cec5SDimitry Andric Explicit).first;
6280b57cec5SDimitry Andric InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
6290b57cec5SDimitry Andric Result->IsInferred = true;
6300b57cec5SDimitry Andric
6310b57cec5SDimitry Andric // Associate the module and the directory.
6320b57cec5SDimitry Andric UmbrellaDirs[SkippedDirs[I-1]] = Result;
6330b57cec5SDimitry Andric
6340b57cec5SDimitry Andric // If inferred submodules export everything they import, add a
6350b57cec5SDimitry Andric // wildcard to the set of exports.
6360b57cec5SDimitry Andric if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
6370b57cec5SDimitry Andric Result->Exports.push_back(Module::ExportDecl(nullptr, true));
6380b57cec5SDimitry Andric }
6390b57cec5SDimitry Andric
6400b57cec5SDimitry Andric // Infer a submodule with the same name as this header file.
6410b57cec5SDimitry Andric SmallString<32> NameBuf;
6420b57cec5SDimitry Andric StringRef Name = sanitizeFilenameAsIdentifier(
6430b57cec5SDimitry Andric llvm::sys::path::stem(File->getName()), NameBuf);
6440b57cec5SDimitry Andric Result = findOrCreateModule(Name, Result, /*IsFramework=*/false,
6450b57cec5SDimitry Andric Explicit).first;
6460b57cec5SDimitry Andric InferredModuleAllowedBy[Result] = UmbrellaModuleMap;
6470b57cec5SDimitry Andric Result->IsInferred = true;
6480b57cec5SDimitry Andric Result->addTopHeader(File);
6490b57cec5SDimitry Andric
6500b57cec5SDimitry Andric // If inferred submodules export everything they import, add a
6510b57cec5SDimitry Andric // wildcard to the set of exports.
6520b57cec5SDimitry Andric if (UmbrellaModule->InferExportWildcard && Result->Exports.empty())
6530b57cec5SDimitry Andric Result->Exports.push_back(Module::ExportDecl(nullptr, true));
6540b57cec5SDimitry Andric } else {
6550b57cec5SDimitry Andric // Record each of the directories we stepped through as being part of
6560b57cec5SDimitry Andric // the module we found, since the umbrella header covers them all.
6570b57cec5SDimitry Andric for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I)
6580b57cec5SDimitry Andric UmbrellaDirs[SkippedDirs[I]] = Result;
6590b57cec5SDimitry Andric }
6600b57cec5SDimitry Andric
6610b57cec5SDimitry Andric KnownHeader Header(Result, NormalHeader);
6620b57cec5SDimitry Andric Headers[File].push_back(Header);
6630b57cec5SDimitry Andric return Header;
6640b57cec5SDimitry Andric }
6650b57cec5SDimitry Andric
6660b57cec5SDimitry Andric return {};
6670b57cec5SDimitry Andric }
6680b57cec5SDimitry Andric
6690b57cec5SDimitry Andric ArrayRef<ModuleMap::KnownHeader>
findAllModulesForHeader(const FileEntry * File)6705ffd83dbSDimitry Andric ModuleMap::findAllModulesForHeader(const FileEntry *File) {
6715ffd83dbSDimitry Andric HeadersMap::iterator Known = findKnownHeader(File);
6725ffd83dbSDimitry Andric if (Known != Headers.end())
6735ffd83dbSDimitry Andric return Known->second;
6745ffd83dbSDimitry Andric
6755ffd83dbSDimitry Andric if (findOrCreateModuleForHeaderInUmbrellaDir(File))
6765ffd83dbSDimitry Andric return Headers.find(File)->second;
6775ffd83dbSDimitry Andric
6785ffd83dbSDimitry Andric return None;
6795ffd83dbSDimitry Andric }
6805ffd83dbSDimitry Andric
6815ffd83dbSDimitry Andric ArrayRef<ModuleMap::KnownHeader>
findResolvedModulesForHeader(const FileEntry * File) const6825ffd83dbSDimitry Andric ModuleMap::findResolvedModulesForHeader(const FileEntry *File) const {
6835ffd83dbSDimitry Andric // FIXME: Is this necessary?
6840b57cec5SDimitry Andric resolveHeaderDirectives(File);
6850b57cec5SDimitry Andric auto It = Headers.find(File);
6860b57cec5SDimitry Andric if (It == Headers.end())
6870b57cec5SDimitry Andric return None;
6880b57cec5SDimitry Andric return It->second;
6890b57cec5SDimitry Andric }
6900b57cec5SDimitry Andric
isHeaderInUnavailableModule(const FileEntry * Header) const6910b57cec5SDimitry Andric bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const {
6920b57cec5SDimitry Andric return isHeaderUnavailableInModule(Header, nullptr);
6930b57cec5SDimitry Andric }
6940b57cec5SDimitry Andric
6950b57cec5SDimitry Andric bool
isHeaderUnavailableInModule(const FileEntry * Header,const Module * RequestingModule) const6960b57cec5SDimitry Andric ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header,
6970b57cec5SDimitry Andric const Module *RequestingModule) const {
6980b57cec5SDimitry Andric resolveHeaderDirectives(Header);
6990b57cec5SDimitry Andric HeadersMap::const_iterator Known = Headers.find(Header);
7000b57cec5SDimitry Andric if (Known != Headers.end()) {
7010b57cec5SDimitry Andric for (SmallVectorImpl<KnownHeader>::const_iterator
7020b57cec5SDimitry Andric I = Known->second.begin(),
7030b57cec5SDimitry Andric E = Known->second.end();
7040b57cec5SDimitry Andric I != E; ++I) {
7050b57cec5SDimitry Andric
7060b57cec5SDimitry Andric if (I->isAvailable() &&
7070b57cec5SDimitry Andric (!RequestingModule ||
7080b57cec5SDimitry Andric I->getModule()->isSubModuleOf(RequestingModule))) {
7090b57cec5SDimitry Andric // When no requesting module is available, the caller is looking if a
7100b57cec5SDimitry Andric // header is part a module by only looking into the module map. This is
7110b57cec5SDimitry Andric // done by warn_uncovered_module_header checks; don't consider textual
7120b57cec5SDimitry Andric // headers part of it in this mode, otherwise we get misleading warnings
7130b57cec5SDimitry Andric // that a umbrella header is not including a textual header.
7140b57cec5SDimitry Andric if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader)
7150b57cec5SDimitry Andric continue;
7160b57cec5SDimitry Andric return false;
7170b57cec5SDimitry Andric }
7180b57cec5SDimitry Andric }
7190b57cec5SDimitry Andric return true;
7200b57cec5SDimitry Andric }
7210b57cec5SDimitry Andric
7220b57cec5SDimitry Andric const DirectoryEntry *Dir = Header->getDir();
7230b57cec5SDimitry Andric SmallVector<const DirectoryEntry *, 2> SkippedDirs;
7240b57cec5SDimitry Andric StringRef DirName = Dir->getName();
7250b57cec5SDimitry Andric
7260b57cec5SDimitry Andric auto IsUnavailable = [&](const Module *M) {
7270b57cec5SDimitry Andric return !M->isAvailable() && (!RequestingModule ||
7280b57cec5SDimitry Andric M->isSubModuleOf(RequestingModule));
7290b57cec5SDimitry Andric };
7300b57cec5SDimitry Andric
7310b57cec5SDimitry Andric // Keep walking up the directory hierarchy, looking for a directory with
7320b57cec5SDimitry Andric // an umbrella header.
7330b57cec5SDimitry Andric do {
7340b57cec5SDimitry Andric llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir
7350b57cec5SDimitry Andric = UmbrellaDirs.find(Dir);
7360b57cec5SDimitry Andric if (KnownDir != UmbrellaDirs.end()) {
7370b57cec5SDimitry Andric Module *Found = KnownDir->second;
7380b57cec5SDimitry Andric if (IsUnavailable(Found))
7390b57cec5SDimitry Andric return true;
7400b57cec5SDimitry Andric
7410b57cec5SDimitry Andric // Search up the module stack until we find a module with an umbrella
7420b57cec5SDimitry Andric // directory.
7430b57cec5SDimitry Andric Module *UmbrellaModule = Found;
7440b57cec5SDimitry Andric while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent)
7450b57cec5SDimitry Andric UmbrellaModule = UmbrellaModule->Parent;
7460b57cec5SDimitry Andric
7470b57cec5SDimitry Andric if (UmbrellaModule->InferSubmodules) {
7480b57cec5SDimitry Andric for (unsigned I = SkippedDirs.size(); I != 0; --I) {
7490b57cec5SDimitry Andric // Find or create the module that corresponds to this directory name.
7500b57cec5SDimitry Andric SmallString<32> NameBuf;
7510b57cec5SDimitry Andric StringRef Name = sanitizeFilenameAsIdentifier(
7520b57cec5SDimitry Andric llvm::sys::path::stem(SkippedDirs[I-1]->getName()),
7530b57cec5SDimitry Andric NameBuf);
7540b57cec5SDimitry Andric Found = lookupModuleQualified(Name, Found);
7550b57cec5SDimitry Andric if (!Found)
7560b57cec5SDimitry Andric return false;
7570b57cec5SDimitry Andric if (IsUnavailable(Found))
7580b57cec5SDimitry Andric return true;
7590b57cec5SDimitry Andric }
7600b57cec5SDimitry Andric
7610b57cec5SDimitry Andric // Infer a submodule with the same name as this header file.
7620b57cec5SDimitry Andric SmallString<32> NameBuf;
7630b57cec5SDimitry Andric StringRef Name = sanitizeFilenameAsIdentifier(
7640b57cec5SDimitry Andric llvm::sys::path::stem(Header->getName()),
7650b57cec5SDimitry Andric NameBuf);
7660b57cec5SDimitry Andric Found = lookupModuleQualified(Name, Found);
7670b57cec5SDimitry Andric if (!Found)
7680b57cec5SDimitry Andric return false;
7690b57cec5SDimitry Andric }
7700b57cec5SDimitry Andric
7710b57cec5SDimitry Andric return IsUnavailable(Found);
7720b57cec5SDimitry Andric }
7730b57cec5SDimitry Andric
7740b57cec5SDimitry Andric SkippedDirs.push_back(Dir);
7750b57cec5SDimitry Andric
7760b57cec5SDimitry Andric // Retrieve our parent path.
7770b57cec5SDimitry Andric DirName = llvm::sys::path::parent_path(DirName);
7780b57cec5SDimitry Andric if (DirName.empty())
7790b57cec5SDimitry Andric break;
7800b57cec5SDimitry Andric
7810b57cec5SDimitry Andric // Resolve the parent path to a directory entry.
782a7dea167SDimitry Andric if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName))
783a7dea167SDimitry Andric Dir = *DirEntry;
784a7dea167SDimitry Andric else
785a7dea167SDimitry Andric Dir = nullptr;
7860b57cec5SDimitry Andric } while (Dir);
7870b57cec5SDimitry Andric
7880b57cec5SDimitry Andric return false;
7890b57cec5SDimitry Andric }
7900b57cec5SDimitry Andric
findModule(StringRef Name) const7910b57cec5SDimitry Andric Module *ModuleMap::findModule(StringRef Name) const {
7920b57cec5SDimitry Andric llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name);
7930b57cec5SDimitry Andric if (Known != Modules.end())
7940b57cec5SDimitry Andric return Known->getValue();
7950b57cec5SDimitry Andric
7960b57cec5SDimitry Andric return nullptr;
7970b57cec5SDimitry Andric }
7980b57cec5SDimitry Andric
lookupModuleUnqualified(StringRef Name,Module * Context) const7990b57cec5SDimitry Andric Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
8000b57cec5SDimitry Andric Module *Context) const {
8010b57cec5SDimitry Andric for(; Context; Context = Context->Parent) {
8020b57cec5SDimitry Andric if (Module *Sub = lookupModuleQualified(Name, Context))
8030b57cec5SDimitry Andric return Sub;
8040b57cec5SDimitry Andric }
8050b57cec5SDimitry Andric
8060b57cec5SDimitry Andric return findModule(Name);
8070b57cec5SDimitry Andric }
8080b57cec5SDimitry Andric
lookupModuleQualified(StringRef Name,Module * Context) const8090b57cec5SDimitry Andric Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{
8100b57cec5SDimitry Andric if (!Context)
8110b57cec5SDimitry Andric return findModule(Name);
8120b57cec5SDimitry Andric
8130b57cec5SDimitry Andric return Context->findSubmodule(Name);
8140b57cec5SDimitry Andric }
8150b57cec5SDimitry Andric
findOrCreateModule(StringRef Name,Module * Parent,bool IsFramework,bool IsExplicit)8160b57cec5SDimitry Andric std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
8170b57cec5SDimitry Andric Module *Parent,
8180b57cec5SDimitry Andric bool IsFramework,
8190b57cec5SDimitry Andric bool IsExplicit) {
8200b57cec5SDimitry Andric // Try to find an existing module with this name.
8210b57cec5SDimitry Andric if (Module *Sub = lookupModuleQualified(Name, Parent))
8220b57cec5SDimitry Andric return std::make_pair(Sub, false);
8230b57cec5SDimitry Andric
8240b57cec5SDimitry Andric // Create a new module with this name.
8250b57cec5SDimitry Andric Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
8260b57cec5SDimitry Andric IsExplicit, NumCreatedModules++);
8270b57cec5SDimitry Andric if (!Parent) {
8280b57cec5SDimitry Andric if (LangOpts.CurrentModule == Name)
8290b57cec5SDimitry Andric SourceModule = Result;
8300b57cec5SDimitry Andric Modules[Name] = Result;
8310b57cec5SDimitry Andric ModuleScopeIDs[Result] = CurrentModuleScopeID;
8320b57cec5SDimitry Andric }
8330b57cec5SDimitry Andric return std::make_pair(Result, true);
8340b57cec5SDimitry Andric }
8350b57cec5SDimitry Andric
createGlobalModuleFragmentForModuleUnit(SourceLocation Loc)8360b57cec5SDimitry Andric Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc) {
8370b57cec5SDimitry Andric PendingSubmodules.emplace_back(
8380b57cec5SDimitry Andric new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
8390b57cec5SDimitry Andric /*IsExplicit*/ true, NumCreatedModules++));
8400b57cec5SDimitry Andric PendingSubmodules.back()->Kind = Module::GlobalModuleFragment;
8410b57cec5SDimitry Andric return PendingSubmodules.back().get();
8420b57cec5SDimitry Andric }
8430b57cec5SDimitry Andric
8440b57cec5SDimitry Andric Module *
createPrivateModuleFragmentForInterfaceUnit(Module * Parent,SourceLocation Loc)8450b57cec5SDimitry Andric ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
8460b57cec5SDimitry Andric SourceLocation Loc) {
8470b57cec5SDimitry Andric auto *Result =
8480b57cec5SDimitry Andric new Module("<private>", Loc, Parent, /*IsFramework*/ false,
8490b57cec5SDimitry Andric /*IsExplicit*/ true, NumCreatedModules++);
8500b57cec5SDimitry Andric Result->Kind = Module::PrivateModuleFragment;
8510b57cec5SDimitry Andric return Result;
8520b57cec5SDimitry Andric }
8530b57cec5SDimitry Andric
createModuleForInterfaceUnit(SourceLocation Loc,StringRef Name,Module * GlobalModule)8540b57cec5SDimitry Andric Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
8550b57cec5SDimitry Andric StringRef Name,
8560b57cec5SDimitry Andric Module *GlobalModule) {
8570b57cec5SDimitry Andric assert(LangOpts.CurrentModule == Name && "module name mismatch");
8580b57cec5SDimitry Andric assert(!Modules[Name] && "redefining existing module");
8590b57cec5SDimitry Andric
8600b57cec5SDimitry Andric auto *Result =
8610b57cec5SDimitry Andric new Module(Name, Loc, nullptr, /*IsFramework*/ false,
8620b57cec5SDimitry Andric /*IsExplicit*/ false, NumCreatedModules++);
8630b57cec5SDimitry Andric Result->Kind = Module::ModuleInterfaceUnit;
8640b57cec5SDimitry Andric Modules[Name] = SourceModule = Result;
8650b57cec5SDimitry Andric
8660b57cec5SDimitry Andric // Reparent the current global module fragment as a submodule of this module.
8670b57cec5SDimitry Andric for (auto &Submodule : PendingSubmodules) {
8680b57cec5SDimitry Andric Submodule->setParent(Result);
8690b57cec5SDimitry Andric Submodule.release(); // now owned by parent
8700b57cec5SDimitry Andric }
8710b57cec5SDimitry Andric PendingSubmodules.clear();
8720b57cec5SDimitry Andric
8730b57cec5SDimitry Andric // Mark the main source file as being within the newly-created module so that
8740b57cec5SDimitry Andric // declarations and macros are properly visibility-restricted to it.
8750b57cec5SDimitry Andric auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
8760b57cec5SDimitry Andric assert(MainFile && "no input file for module interface");
8770b57cec5SDimitry Andric Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader));
8780b57cec5SDimitry Andric
8790b57cec5SDimitry Andric return Result;
8800b57cec5SDimitry Andric }
8810b57cec5SDimitry Andric
createHeaderModule(StringRef Name,ArrayRef<Module::Header> Headers)8820b57cec5SDimitry Andric Module *ModuleMap::createHeaderModule(StringRef Name,
8830b57cec5SDimitry Andric ArrayRef<Module::Header> Headers) {
8840b57cec5SDimitry Andric assert(LangOpts.CurrentModule == Name && "module name mismatch");
8850b57cec5SDimitry Andric assert(!Modules[Name] && "redefining existing module");
8860b57cec5SDimitry Andric
8870b57cec5SDimitry Andric auto *Result =
8880b57cec5SDimitry Andric new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false,
8890b57cec5SDimitry Andric /*IsExplicit*/ false, NumCreatedModules++);
8900b57cec5SDimitry Andric Result->Kind = Module::ModuleInterfaceUnit;
8910b57cec5SDimitry Andric Modules[Name] = SourceModule = Result;
8920b57cec5SDimitry Andric
8930b57cec5SDimitry Andric for (const Module::Header &H : Headers) {
8940b57cec5SDimitry Andric auto *M = new Module(H.NameAsWritten, SourceLocation(), Result,
8950b57cec5SDimitry Andric /*IsFramework*/ false,
8960b57cec5SDimitry Andric /*IsExplicit*/ true, NumCreatedModules++);
8970b57cec5SDimitry Andric // Header modules are implicitly 'export *'.
8980b57cec5SDimitry Andric M->Exports.push_back(Module::ExportDecl(nullptr, true));
8990b57cec5SDimitry Andric addHeader(M, H, NormalHeader);
9000b57cec5SDimitry Andric }
9010b57cec5SDimitry Andric
9020b57cec5SDimitry Andric return Result;
9030b57cec5SDimitry Andric }
9040b57cec5SDimitry Andric
9050b57cec5SDimitry Andric /// For a framework module, infer the framework against which we
9060b57cec5SDimitry Andric /// should link.
inferFrameworkLink(Module * Mod,const DirectoryEntry * FrameworkDir,FileManager & FileMgr)9070b57cec5SDimitry Andric static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir,
9080b57cec5SDimitry Andric FileManager &FileMgr) {
9090b57cec5SDimitry Andric assert(Mod->IsFramework && "Can only infer linking for framework modules");
9100b57cec5SDimitry Andric assert(!Mod->isSubFramework() &&
9110b57cec5SDimitry Andric "Can only infer linking for top-level frameworks");
9120b57cec5SDimitry Andric
9130b57cec5SDimitry Andric SmallString<128> LibName;
9140b57cec5SDimitry Andric LibName += FrameworkDir->getName();
9150b57cec5SDimitry Andric llvm::sys::path::append(LibName, Mod->Name);
9160b57cec5SDimitry Andric
9170b57cec5SDimitry Andric // The library name of a framework has more than one possible extension since
9180b57cec5SDimitry Andric // the introduction of the text-based dynamic library format. We need to check
9190b57cec5SDimitry Andric // for both before we give up.
9200b57cec5SDimitry Andric for (const char *extension : {"", ".tbd"}) {
9210b57cec5SDimitry Andric llvm::sys::path::replace_extension(LibName, extension);
9220b57cec5SDimitry Andric if (FileMgr.getFile(LibName)) {
9230b57cec5SDimitry Andric Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name,
9240b57cec5SDimitry Andric /*IsFramework=*/true));
9250b57cec5SDimitry Andric return;
9260b57cec5SDimitry Andric }
9270b57cec5SDimitry Andric }
9280b57cec5SDimitry Andric }
9290b57cec5SDimitry Andric
inferFrameworkModule(const DirectoryEntry * FrameworkDir,bool IsSystem,Module * Parent)9300b57cec5SDimitry Andric Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
9310b57cec5SDimitry Andric bool IsSystem, Module *Parent) {
9320b57cec5SDimitry Andric Attributes Attrs;
9330b57cec5SDimitry Andric Attrs.IsSystem = IsSystem;
9340b57cec5SDimitry Andric return inferFrameworkModule(FrameworkDir, Attrs, Parent);
9350b57cec5SDimitry Andric }
9360b57cec5SDimitry Andric
inferFrameworkModule(const DirectoryEntry * FrameworkDir,Attributes Attrs,Module * Parent)9370b57cec5SDimitry Andric Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir,
9380b57cec5SDimitry Andric Attributes Attrs, Module *Parent) {
9390b57cec5SDimitry Andric // Note: as an egregious but useful hack we use the real path here, because
9400b57cec5SDimitry Andric // we might be looking at an embedded framework that symlinks out to a
9410b57cec5SDimitry Andric // top-level framework, and we need to infer as if we were naming the
9420b57cec5SDimitry Andric // top-level framework.
9430b57cec5SDimitry Andric StringRef FrameworkDirName =
9440b57cec5SDimitry Andric SourceMgr.getFileManager().getCanonicalName(FrameworkDir);
9450b57cec5SDimitry Andric
9460b57cec5SDimitry Andric // In case this is a case-insensitive filesystem, use the canonical
9470b57cec5SDimitry Andric // directory name as the ModuleName, since modules are case-sensitive.
9480b57cec5SDimitry Andric // FIXME: we should be able to give a fix-it hint for the correct spelling.
9490b57cec5SDimitry Andric SmallString<32> ModuleNameStorage;
9500b57cec5SDimitry Andric StringRef ModuleName = sanitizeFilenameAsIdentifier(
9510b57cec5SDimitry Andric llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage);
9520b57cec5SDimitry Andric
9530b57cec5SDimitry Andric // Check whether we've already found this module.
9540b57cec5SDimitry Andric if (Module *Mod = lookupModuleQualified(ModuleName, Parent))
9550b57cec5SDimitry Andric return Mod;
9560b57cec5SDimitry Andric
9570b57cec5SDimitry Andric FileManager &FileMgr = SourceMgr.getFileManager();
9580b57cec5SDimitry Andric
9590b57cec5SDimitry Andric // If the framework has a parent path from which we're allowed to infer
9600b57cec5SDimitry Andric // a framework module, do so.
9610b57cec5SDimitry Andric const FileEntry *ModuleMapFile = nullptr;
9620b57cec5SDimitry Andric if (!Parent) {
9630b57cec5SDimitry Andric // Determine whether we're allowed to infer a module map.
9640b57cec5SDimitry Andric bool canInfer = false;
9650b57cec5SDimitry Andric if (llvm::sys::path::has_parent_path(FrameworkDirName)) {
9660b57cec5SDimitry Andric // Figure out the parent path.
9670b57cec5SDimitry Andric StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName);
968a7dea167SDimitry Andric if (auto ParentDir = FileMgr.getDirectory(Parent)) {
9690b57cec5SDimitry Andric // Check whether we have already looked into the parent directory
9700b57cec5SDimitry Andric // for a module map.
9710b57cec5SDimitry Andric llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator
972a7dea167SDimitry Andric inferred = InferredDirectories.find(*ParentDir);
9730b57cec5SDimitry Andric if (inferred == InferredDirectories.end()) {
9740b57cec5SDimitry Andric // We haven't looked here before. Load a module map, if there is
9750b57cec5SDimitry Andric // one.
9760b57cec5SDimitry Andric bool IsFrameworkDir = Parent.endswith(".framework");
9770b57cec5SDimitry Andric if (const FileEntry *ModMapFile =
978a7dea167SDimitry Andric HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) {
979a7dea167SDimitry Andric parseModuleMapFile(ModMapFile, Attrs.IsSystem, *ParentDir);
980a7dea167SDimitry Andric inferred = InferredDirectories.find(*ParentDir);
9810b57cec5SDimitry Andric }
9820b57cec5SDimitry Andric
9830b57cec5SDimitry Andric if (inferred == InferredDirectories.end())
9840b57cec5SDimitry Andric inferred = InferredDirectories.insert(
985a7dea167SDimitry Andric std::make_pair(*ParentDir, InferredDirectory())).first;
9860b57cec5SDimitry Andric }
9870b57cec5SDimitry Andric
9880b57cec5SDimitry Andric if (inferred->second.InferModules) {
9890b57cec5SDimitry Andric // We're allowed to infer for this directory, but make sure it's okay
9900b57cec5SDimitry Andric // to infer this particular module.
9910b57cec5SDimitry Andric StringRef Name = llvm::sys::path::stem(FrameworkDirName);
9920b57cec5SDimitry Andric canInfer = std::find(inferred->second.ExcludedModules.begin(),
9930b57cec5SDimitry Andric inferred->second.ExcludedModules.end(),
9940b57cec5SDimitry Andric Name) == inferred->second.ExcludedModules.end();
9950b57cec5SDimitry Andric
9960b57cec5SDimitry Andric Attrs.IsSystem |= inferred->second.Attrs.IsSystem;
9970b57cec5SDimitry Andric Attrs.IsExternC |= inferred->second.Attrs.IsExternC;
9980b57cec5SDimitry Andric Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive;
9990b57cec5SDimitry Andric Attrs.NoUndeclaredIncludes |=
10000b57cec5SDimitry Andric inferred->second.Attrs.NoUndeclaredIncludes;
10010b57cec5SDimitry Andric ModuleMapFile = inferred->second.ModuleMapFile;
10020b57cec5SDimitry Andric }
10030b57cec5SDimitry Andric }
10040b57cec5SDimitry Andric }
10050b57cec5SDimitry Andric
10060b57cec5SDimitry Andric // If we're not allowed to infer a framework module, don't.
10070b57cec5SDimitry Andric if (!canInfer)
10080b57cec5SDimitry Andric return nullptr;
10090b57cec5SDimitry Andric } else
10100b57cec5SDimitry Andric ModuleMapFile = getModuleMapFileForUniquing(Parent);
10110b57cec5SDimitry Andric
10120b57cec5SDimitry Andric
10130b57cec5SDimitry Andric // Look for an umbrella header.
10140b57cec5SDimitry Andric SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName());
10150b57cec5SDimitry Andric llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h");
1016*5f7ddb14SDimitry Andric auto UmbrellaHeader = FileMgr.getFile(UmbrellaName);
10170b57cec5SDimitry Andric
10180b57cec5SDimitry Andric // FIXME: If there's no umbrella header, we could probably scan the
10190b57cec5SDimitry Andric // framework to load *everything*. But, it's not clear that this is a good
10200b57cec5SDimitry Andric // idea.
10210b57cec5SDimitry Andric if (!UmbrellaHeader)
10220b57cec5SDimitry Andric return nullptr;
10230b57cec5SDimitry Andric
10240b57cec5SDimitry Andric Module *Result = new Module(ModuleName, SourceLocation(), Parent,
10250b57cec5SDimitry Andric /*IsFramework=*/true, /*IsExplicit=*/false,
10260b57cec5SDimitry Andric NumCreatedModules++);
10270b57cec5SDimitry Andric InferredModuleAllowedBy[Result] = ModuleMapFile;
10280b57cec5SDimitry Andric Result->IsInferred = true;
10290b57cec5SDimitry Andric if (!Parent) {
10300b57cec5SDimitry Andric if (LangOpts.CurrentModule == ModuleName)
10310b57cec5SDimitry Andric SourceModule = Result;
10320b57cec5SDimitry Andric Modules[ModuleName] = Result;
10330b57cec5SDimitry Andric ModuleScopeIDs[Result] = CurrentModuleScopeID;
10340b57cec5SDimitry Andric }
10350b57cec5SDimitry Andric
10360b57cec5SDimitry Andric Result->IsSystem |= Attrs.IsSystem;
10370b57cec5SDimitry Andric Result->IsExternC |= Attrs.IsExternC;
10380b57cec5SDimitry Andric Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
10390b57cec5SDimitry Andric Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
10400b57cec5SDimitry Andric Result->Directory = FrameworkDir;
10410b57cec5SDimitry Andric
1042*5f7ddb14SDimitry Andric // Chop off the first framework bit, as that is implied.
1043*5f7ddb14SDimitry Andric StringRef RelativePath = UmbrellaName.str().substr(
1044*5f7ddb14SDimitry Andric Result->getTopLevelModule()->Directory->getName().size());
1045*5f7ddb14SDimitry Andric RelativePath = llvm::sys::path::relative_path(RelativePath);
1046*5f7ddb14SDimitry Andric
10470b57cec5SDimitry Andric // umbrella header "umbrella-header-name"
1048*5f7ddb14SDimitry Andric setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h", RelativePath);
10490b57cec5SDimitry Andric
10500b57cec5SDimitry Andric // export *
10510b57cec5SDimitry Andric Result->Exports.push_back(Module::ExportDecl(nullptr, true));
10520b57cec5SDimitry Andric
10530b57cec5SDimitry Andric // module * { export * }
10540b57cec5SDimitry Andric Result->InferSubmodules = true;
10550b57cec5SDimitry Andric Result->InferExportWildcard = true;
10560b57cec5SDimitry Andric
10570b57cec5SDimitry Andric // Look for subframeworks.
10580b57cec5SDimitry Andric std::error_code EC;
10590b57cec5SDimitry Andric SmallString<128> SubframeworksDirName
10600b57cec5SDimitry Andric = StringRef(FrameworkDir->getName());
10610b57cec5SDimitry Andric llvm::sys::path::append(SubframeworksDirName, "Frameworks");
10620b57cec5SDimitry Andric llvm::sys::path::native(SubframeworksDirName);
10630b57cec5SDimitry Andric llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
10640b57cec5SDimitry Andric for (llvm::vfs::directory_iterator
10650b57cec5SDimitry Andric Dir = FS.dir_begin(SubframeworksDirName, EC),
10660b57cec5SDimitry Andric DirEnd;
10670b57cec5SDimitry Andric Dir != DirEnd && !EC; Dir.increment(EC)) {
10680b57cec5SDimitry Andric if (!StringRef(Dir->path()).endswith(".framework"))
10690b57cec5SDimitry Andric continue;
10700b57cec5SDimitry Andric
1071a7dea167SDimitry Andric if (auto SubframeworkDir =
10720b57cec5SDimitry Andric FileMgr.getDirectory(Dir->path())) {
10730b57cec5SDimitry Andric // Note: as an egregious but useful hack, we use the real path here and
10740b57cec5SDimitry Andric // check whether it is actually a subdirectory of the parent directory.
10750b57cec5SDimitry Andric // This will not be the case if the 'subframework' is actually a symlink
10760b57cec5SDimitry Andric // out to a top-level framework.
1077a7dea167SDimitry Andric StringRef SubframeworkDirName =
1078a7dea167SDimitry Andric FileMgr.getCanonicalName(*SubframeworkDir);
10790b57cec5SDimitry Andric bool FoundParent = false;
10800b57cec5SDimitry Andric do {
10810b57cec5SDimitry Andric // Get the parent directory name.
10820b57cec5SDimitry Andric SubframeworkDirName
10830b57cec5SDimitry Andric = llvm::sys::path::parent_path(SubframeworkDirName);
10840b57cec5SDimitry Andric if (SubframeworkDirName.empty())
10850b57cec5SDimitry Andric break;
10860b57cec5SDimitry Andric
1087a7dea167SDimitry Andric if (auto SubDir = FileMgr.getDirectory(SubframeworkDirName)) {
1088a7dea167SDimitry Andric if (*SubDir == FrameworkDir) {
10890b57cec5SDimitry Andric FoundParent = true;
10900b57cec5SDimitry Andric break;
10910b57cec5SDimitry Andric }
1092a7dea167SDimitry Andric }
10930b57cec5SDimitry Andric } while (true);
10940b57cec5SDimitry Andric
10950b57cec5SDimitry Andric if (!FoundParent)
10960b57cec5SDimitry Andric continue;
10970b57cec5SDimitry Andric
10980b57cec5SDimitry Andric // FIXME: Do we want to warn about subframeworks without umbrella headers?
1099a7dea167SDimitry Andric inferFrameworkModule(*SubframeworkDir, Attrs, Result);
11000b57cec5SDimitry Andric }
11010b57cec5SDimitry Andric }
11020b57cec5SDimitry Andric
11030b57cec5SDimitry Andric // If the module is a top-level framework, automatically link against the
11040b57cec5SDimitry Andric // framework.
11050b57cec5SDimitry Andric if (!Result->isSubFramework()) {
11060b57cec5SDimitry Andric inferFrameworkLink(Result, FrameworkDir, FileMgr);
11070b57cec5SDimitry Andric }
11080b57cec5SDimitry Andric
11090b57cec5SDimitry Andric return Result;
11100b57cec5SDimitry Andric }
11110b57cec5SDimitry Andric
createShadowedModule(StringRef Name,bool IsFramework,Module * ShadowingModule)11120b57cec5SDimitry Andric Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
11130b57cec5SDimitry Andric Module *ShadowingModule) {
11140b57cec5SDimitry Andric
11150b57cec5SDimitry Andric // Create a new module with this name.
11160b57cec5SDimitry Andric Module *Result =
11170b57cec5SDimitry Andric new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
11180b57cec5SDimitry Andric /*IsExplicit=*/false, NumCreatedModules++);
11190b57cec5SDimitry Andric Result->ShadowingModule = ShadowingModule;
11205ffd83dbSDimitry Andric Result->markUnavailable(/*Unimportable*/true);
11210b57cec5SDimitry Andric ModuleScopeIDs[Result] = CurrentModuleScopeID;
11220b57cec5SDimitry Andric ShadowModules.push_back(Result);
11230b57cec5SDimitry Andric
11240b57cec5SDimitry Andric return Result;
11250b57cec5SDimitry Andric }
11260b57cec5SDimitry Andric
setUmbrellaHeader(Module * Mod,const FileEntry * UmbrellaHeader,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)1127*5f7ddb14SDimitry Andric void ModuleMap::setUmbrellaHeader(
1128*5f7ddb14SDimitry Andric Module *Mod, const FileEntry *UmbrellaHeader, const Twine &NameAsWritten,
1129*5f7ddb14SDimitry Andric const Twine &PathRelativeToRootModuleDirectory) {
11300b57cec5SDimitry Andric Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader));
1131*5f7ddb14SDimitry Andric Mod->Umbrella = UmbrellaHeader;
11320b57cec5SDimitry Andric Mod->UmbrellaAsWritten = NameAsWritten.str();
1133*5f7ddb14SDimitry Andric Mod->UmbrellaRelativeToRootModuleDirectory =
1134*5f7ddb14SDimitry Andric PathRelativeToRootModuleDirectory.str();
1135*5f7ddb14SDimitry Andric UmbrellaDirs[UmbrellaHeader->getDir()] = Mod;
11360b57cec5SDimitry Andric
11370b57cec5SDimitry Andric // Notify callbacks that we just added a new header.
11380b57cec5SDimitry Andric for (const auto &Cb : Callbacks)
11390b57cec5SDimitry Andric Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader);
11400b57cec5SDimitry Andric }
11410b57cec5SDimitry Andric
setUmbrellaDir(Module * Mod,const DirectoryEntry * UmbrellaDir,const Twine & NameAsWritten,const Twine & PathRelativeToRootModuleDirectory)1142*5f7ddb14SDimitry Andric void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir,
1143*5f7ddb14SDimitry Andric const Twine &NameAsWritten,
1144*5f7ddb14SDimitry Andric const Twine &PathRelativeToRootModuleDirectory) {
1145*5f7ddb14SDimitry Andric Mod->Umbrella = UmbrellaDir;
11460b57cec5SDimitry Andric Mod->UmbrellaAsWritten = NameAsWritten.str();
1147*5f7ddb14SDimitry Andric Mod->UmbrellaRelativeToRootModuleDirectory =
1148*5f7ddb14SDimitry Andric PathRelativeToRootModuleDirectory.str();
11490b57cec5SDimitry Andric UmbrellaDirs[UmbrellaDir] = Mod;
11500b57cec5SDimitry Andric }
11510b57cec5SDimitry Andric
addUnresolvedHeader(Module * Mod,Module::UnresolvedHeaderDirective Header,bool & NeedsFramework)11520b57cec5SDimitry Andric void ModuleMap::addUnresolvedHeader(Module *Mod,
11530b57cec5SDimitry Andric Module::UnresolvedHeaderDirective Header,
11540b57cec5SDimitry Andric bool &NeedsFramework) {
11550b57cec5SDimitry Andric // If there is a builtin counterpart to this file, add it now so it can
11560b57cec5SDimitry Andric // wrap the system header.
11570b57cec5SDimitry Andric if (resolveAsBuiltinHeader(Mod, Header)) {
11580b57cec5SDimitry Andric // If we have both a builtin and system version of the file, the
11590b57cec5SDimitry Andric // builtin version may want to inject macros into the system header, so
11600b57cec5SDimitry Andric // force the system header to be treated as a textual header in this
11610b57cec5SDimitry Andric // case.
11620b57cec5SDimitry Andric Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole(
11630b57cec5SDimitry Andric headerKindToRole(Header.Kind) | ModuleMap::TextualHeader));
11640b57cec5SDimitry Andric Header.HasBuiltinHeader = true;
11650b57cec5SDimitry Andric }
11660b57cec5SDimitry Andric
11670b57cec5SDimitry Andric // If possible, don't stat the header until we need to. This requires the
11680b57cec5SDimitry Andric // user to have provided us with some stat information about the file.
11690b57cec5SDimitry Andric // FIXME: Add support for lazily stat'ing umbrella headers and excluded
11700b57cec5SDimitry Andric // headers.
11710b57cec5SDimitry Andric if ((Header.Size || Header.ModTime) && !Header.IsUmbrella &&
11720b57cec5SDimitry Andric Header.Kind != Module::HK_Excluded) {
11730b57cec5SDimitry Andric // We expect more variation in mtime than size, so if we're given both,
11740b57cec5SDimitry Andric // use the mtime as the key.
11750b57cec5SDimitry Andric if (Header.ModTime)
11760b57cec5SDimitry Andric LazyHeadersByModTime[*Header.ModTime].push_back(Mod);
11770b57cec5SDimitry Andric else
11780b57cec5SDimitry Andric LazyHeadersBySize[*Header.Size].push_back(Mod);
11790b57cec5SDimitry Andric Mod->UnresolvedHeaders.push_back(Header);
11800b57cec5SDimitry Andric return;
11810b57cec5SDimitry Andric }
11820b57cec5SDimitry Andric
11830b57cec5SDimitry Andric // We don't have stat information or can't defer looking this file up.
11840b57cec5SDimitry Andric // Perform the lookup now.
11850b57cec5SDimitry Andric resolveHeader(Mod, Header, NeedsFramework);
11860b57cec5SDimitry Andric }
11870b57cec5SDimitry Andric
resolveHeaderDirectives(const FileEntry * File) const11880b57cec5SDimitry Andric void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const {
11890b57cec5SDimitry Andric auto BySize = LazyHeadersBySize.find(File->getSize());
11900b57cec5SDimitry Andric if (BySize != LazyHeadersBySize.end()) {
11910b57cec5SDimitry Andric for (auto *M : BySize->second)
11920b57cec5SDimitry Andric resolveHeaderDirectives(M);
11930b57cec5SDimitry Andric LazyHeadersBySize.erase(BySize);
11940b57cec5SDimitry Andric }
11950b57cec5SDimitry Andric
11960b57cec5SDimitry Andric auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime());
11970b57cec5SDimitry Andric if (ByModTime != LazyHeadersByModTime.end()) {
11980b57cec5SDimitry Andric for (auto *M : ByModTime->second)
11990b57cec5SDimitry Andric resolveHeaderDirectives(M);
12000b57cec5SDimitry Andric LazyHeadersByModTime.erase(ByModTime);
12010b57cec5SDimitry Andric }
12020b57cec5SDimitry Andric }
12030b57cec5SDimitry Andric
resolveHeaderDirectives(Module * Mod) const12040b57cec5SDimitry Andric void ModuleMap::resolveHeaderDirectives(Module *Mod) const {
12050b57cec5SDimitry Andric bool NeedsFramework = false;
12060b57cec5SDimitry Andric for (auto &Header : Mod->UnresolvedHeaders)
12070b57cec5SDimitry Andric // This operation is logically const; we're just changing how we represent
12080b57cec5SDimitry Andric // the header information for this file.
12090b57cec5SDimitry Andric const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework);
12100b57cec5SDimitry Andric Mod->UnresolvedHeaders.clear();
12110b57cec5SDimitry Andric }
12120b57cec5SDimitry Andric
addHeader(Module * Mod,Module::Header Header,ModuleHeaderRole Role,bool Imported)12130b57cec5SDimitry Andric void ModuleMap::addHeader(Module *Mod, Module::Header Header,
12140b57cec5SDimitry Andric ModuleHeaderRole Role, bool Imported) {
12150b57cec5SDimitry Andric KnownHeader KH(Mod, Role);
12160b57cec5SDimitry Andric
12170b57cec5SDimitry Andric // Only add each header to the headers list once.
12180b57cec5SDimitry Andric // FIXME: Should we diagnose if a header is listed twice in the
12190b57cec5SDimitry Andric // same module definition?
12200b57cec5SDimitry Andric auto &HeaderList = Headers[Header.Entry];
12210b57cec5SDimitry Andric for (auto H : HeaderList)
12220b57cec5SDimitry Andric if (H == KH)
12230b57cec5SDimitry Andric return;
12240b57cec5SDimitry Andric
12250b57cec5SDimitry Andric HeaderList.push_back(KH);
12260b57cec5SDimitry Andric Mod->Headers[headerRoleToKind(Role)].push_back(Header);
12270b57cec5SDimitry Andric
12280b57cec5SDimitry Andric bool isCompilingModuleHeader =
12290b57cec5SDimitry Andric LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule;
12300b57cec5SDimitry Andric if (!Imported || isCompilingModuleHeader) {
12310b57cec5SDimitry Andric // When we import HeaderFileInfo, the external source is expected to
12320b57cec5SDimitry Andric // set the isModuleHeader flag itself.
12330b57cec5SDimitry Andric HeaderInfo.MarkFileModuleHeader(Header.Entry, Role,
12340b57cec5SDimitry Andric isCompilingModuleHeader);
12350b57cec5SDimitry Andric }
12360b57cec5SDimitry Andric
12370b57cec5SDimitry Andric // Notify callbacks that we just added a new header.
12380b57cec5SDimitry Andric for (const auto &Cb : Callbacks)
12390b57cec5SDimitry Andric Cb->moduleMapAddHeader(Header.Entry->getName());
12400b57cec5SDimitry Andric }
12410b57cec5SDimitry Andric
excludeHeader(Module * Mod,Module::Header Header)12420b57cec5SDimitry Andric void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) {
12430b57cec5SDimitry Andric // Add this as a known header so we won't implicitly add it to any
12440b57cec5SDimitry Andric // umbrella directory module.
12450b57cec5SDimitry Andric // FIXME: Should we only exclude it from umbrella modules within the
12460b57cec5SDimitry Andric // specified module?
12470b57cec5SDimitry Andric (void) Headers[Header.Entry];
12480b57cec5SDimitry Andric
12490b57cec5SDimitry Andric Mod->Headers[Module::HK_Excluded].push_back(std::move(Header));
12500b57cec5SDimitry Andric }
12510b57cec5SDimitry Andric
12520b57cec5SDimitry Andric const FileEntry *
getContainingModuleMapFile(const Module * Module) const12530b57cec5SDimitry Andric ModuleMap::getContainingModuleMapFile(const Module *Module) const {
12540b57cec5SDimitry Andric if (Module->DefinitionLoc.isInvalid())
12550b57cec5SDimitry Andric return nullptr;
12560b57cec5SDimitry Andric
12570b57cec5SDimitry Andric return SourceMgr.getFileEntryForID(
12580b57cec5SDimitry Andric SourceMgr.getFileID(Module->DefinitionLoc));
12590b57cec5SDimitry Andric }
12600b57cec5SDimitry Andric
getModuleMapFileForUniquing(const Module * M) const12610b57cec5SDimitry Andric const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const {
12620b57cec5SDimitry Andric if (M->IsInferred) {
12630b57cec5SDimitry Andric assert(InferredModuleAllowedBy.count(M) && "missing inferred module map");
12640b57cec5SDimitry Andric return InferredModuleAllowedBy.find(M)->second;
12650b57cec5SDimitry Andric }
12660b57cec5SDimitry Andric return getContainingModuleMapFile(M);
12670b57cec5SDimitry Andric }
12680b57cec5SDimitry Andric
setInferredModuleAllowedBy(Module * M,const FileEntry * ModMap)12690b57cec5SDimitry Andric void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) {
12700b57cec5SDimitry Andric assert(M->IsInferred && "module not inferred");
12710b57cec5SDimitry Andric InferredModuleAllowedBy[M] = ModMap;
12720b57cec5SDimitry Andric }
12730b57cec5SDimitry Andric
addAdditionalModuleMapFile(const Module * M,const FileEntry * ModuleMap)12745ffd83dbSDimitry Andric void ModuleMap::addAdditionalModuleMapFile(const Module *M,
12755ffd83dbSDimitry Andric const FileEntry *ModuleMap) {
12765ffd83dbSDimitry Andric AdditionalModMaps[M].insert(ModuleMap);
12775ffd83dbSDimitry Andric }
12785ffd83dbSDimitry Andric
dump()12790b57cec5SDimitry Andric LLVM_DUMP_METHOD void ModuleMap::dump() {
12800b57cec5SDimitry Andric llvm::errs() << "Modules:";
12810b57cec5SDimitry Andric for (llvm::StringMap<Module *>::iterator M = Modules.begin(),
12820b57cec5SDimitry Andric MEnd = Modules.end();
12830b57cec5SDimitry Andric M != MEnd; ++M)
12840b57cec5SDimitry Andric M->getValue()->print(llvm::errs(), 2);
12850b57cec5SDimitry Andric
12860b57cec5SDimitry Andric llvm::errs() << "Headers:";
12870b57cec5SDimitry Andric for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end();
12880b57cec5SDimitry Andric H != HEnd; ++H) {
12890b57cec5SDimitry Andric llvm::errs() << " \"" << H->first->getName() << "\" -> ";
12900b57cec5SDimitry Andric for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(),
12910b57cec5SDimitry Andric E = H->second.end();
12920b57cec5SDimitry Andric I != E; ++I) {
12930b57cec5SDimitry Andric if (I != H->second.begin())
12940b57cec5SDimitry Andric llvm::errs() << ",";
12950b57cec5SDimitry Andric llvm::errs() << I->getModule()->getFullModuleName();
12960b57cec5SDimitry Andric }
12970b57cec5SDimitry Andric llvm::errs() << "\n";
12980b57cec5SDimitry Andric }
12990b57cec5SDimitry Andric }
13000b57cec5SDimitry Andric
resolveExports(Module * Mod,bool Complain)13010b57cec5SDimitry Andric bool ModuleMap::resolveExports(Module *Mod, bool Complain) {
13020b57cec5SDimitry Andric auto Unresolved = std::move(Mod->UnresolvedExports);
13030b57cec5SDimitry Andric Mod->UnresolvedExports.clear();
13040b57cec5SDimitry Andric for (auto &UE : Unresolved) {
13050b57cec5SDimitry Andric Module::ExportDecl Export = resolveExport(Mod, UE, Complain);
13060b57cec5SDimitry Andric if (Export.getPointer() || Export.getInt())
13070b57cec5SDimitry Andric Mod->Exports.push_back(Export);
13080b57cec5SDimitry Andric else
13090b57cec5SDimitry Andric Mod->UnresolvedExports.push_back(UE);
13100b57cec5SDimitry Andric }
13110b57cec5SDimitry Andric return !Mod->UnresolvedExports.empty();
13120b57cec5SDimitry Andric }
13130b57cec5SDimitry Andric
resolveUses(Module * Mod,bool Complain)13140b57cec5SDimitry Andric bool ModuleMap::resolveUses(Module *Mod, bool Complain) {
13150b57cec5SDimitry Andric auto Unresolved = std::move(Mod->UnresolvedDirectUses);
13160b57cec5SDimitry Andric Mod->UnresolvedDirectUses.clear();
13170b57cec5SDimitry Andric for (auto &UDU : Unresolved) {
13180b57cec5SDimitry Andric Module *DirectUse = resolveModuleId(UDU, Mod, Complain);
13190b57cec5SDimitry Andric if (DirectUse)
13200b57cec5SDimitry Andric Mod->DirectUses.push_back(DirectUse);
13210b57cec5SDimitry Andric else
13220b57cec5SDimitry Andric Mod->UnresolvedDirectUses.push_back(UDU);
13230b57cec5SDimitry Andric }
13240b57cec5SDimitry Andric return !Mod->UnresolvedDirectUses.empty();
13250b57cec5SDimitry Andric }
13260b57cec5SDimitry Andric
resolveConflicts(Module * Mod,bool Complain)13270b57cec5SDimitry Andric bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) {
13280b57cec5SDimitry Andric auto Unresolved = std::move(Mod->UnresolvedConflicts);
13290b57cec5SDimitry Andric Mod->UnresolvedConflicts.clear();
13300b57cec5SDimitry Andric for (auto &UC : Unresolved) {
13310b57cec5SDimitry Andric if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) {
13320b57cec5SDimitry Andric Module::Conflict Conflict;
13330b57cec5SDimitry Andric Conflict.Other = OtherMod;
13340b57cec5SDimitry Andric Conflict.Message = UC.Message;
13350b57cec5SDimitry Andric Mod->Conflicts.push_back(Conflict);
13360b57cec5SDimitry Andric } else
13370b57cec5SDimitry Andric Mod->UnresolvedConflicts.push_back(UC);
13380b57cec5SDimitry Andric }
13390b57cec5SDimitry Andric return !Mod->UnresolvedConflicts.empty();
13400b57cec5SDimitry Andric }
13410b57cec5SDimitry Andric
13420b57cec5SDimitry Andric //----------------------------------------------------------------------------//
13430b57cec5SDimitry Andric // Module map file parser
13440b57cec5SDimitry Andric //----------------------------------------------------------------------------//
13450b57cec5SDimitry Andric
13460b57cec5SDimitry Andric namespace clang {
13470b57cec5SDimitry Andric
13480b57cec5SDimitry Andric /// A token in a module map file.
13490b57cec5SDimitry Andric struct MMToken {
13500b57cec5SDimitry Andric enum TokenKind {
13510b57cec5SDimitry Andric Comma,
13520b57cec5SDimitry Andric ConfigMacros,
13530b57cec5SDimitry Andric Conflict,
13540b57cec5SDimitry Andric EndOfFile,
13550b57cec5SDimitry Andric HeaderKeyword,
13560b57cec5SDimitry Andric Identifier,
13570b57cec5SDimitry Andric Exclaim,
13580b57cec5SDimitry Andric ExcludeKeyword,
13590b57cec5SDimitry Andric ExplicitKeyword,
13600b57cec5SDimitry Andric ExportKeyword,
13610b57cec5SDimitry Andric ExportAsKeyword,
13620b57cec5SDimitry Andric ExternKeyword,
13630b57cec5SDimitry Andric FrameworkKeyword,
13640b57cec5SDimitry Andric LinkKeyword,
13650b57cec5SDimitry Andric ModuleKeyword,
13660b57cec5SDimitry Andric Period,
13670b57cec5SDimitry Andric PrivateKeyword,
13680b57cec5SDimitry Andric UmbrellaKeyword,
13690b57cec5SDimitry Andric UseKeyword,
13700b57cec5SDimitry Andric RequiresKeyword,
13710b57cec5SDimitry Andric Star,
13720b57cec5SDimitry Andric StringLiteral,
13730b57cec5SDimitry Andric IntegerLiteral,
13740b57cec5SDimitry Andric TextualKeyword,
13750b57cec5SDimitry Andric LBrace,
13760b57cec5SDimitry Andric RBrace,
13770b57cec5SDimitry Andric LSquare,
13780b57cec5SDimitry Andric RSquare
13790b57cec5SDimitry Andric } Kind;
13800b57cec5SDimitry Andric
1381*5f7ddb14SDimitry Andric SourceLocation::UIntTy Location;
13820b57cec5SDimitry Andric unsigned StringLength;
13830b57cec5SDimitry Andric union {
13840b57cec5SDimitry Andric // If Kind != IntegerLiteral.
13850b57cec5SDimitry Andric const char *StringData;
13860b57cec5SDimitry Andric
13870b57cec5SDimitry Andric // If Kind == IntegerLiteral.
13880b57cec5SDimitry Andric uint64_t IntegerValue;
13890b57cec5SDimitry Andric };
13900b57cec5SDimitry Andric
clearclang::MMToken13910b57cec5SDimitry Andric void clear() {
13920b57cec5SDimitry Andric Kind = EndOfFile;
13930b57cec5SDimitry Andric Location = 0;
13940b57cec5SDimitry Andric StringLength = 0;
13950b57cec5SDimitry Andric StringData = nullptr;
13960b57cec5SDimitry Andric }
13970b57cec5SDimitry Andric
isclang::MMToken13980b57cec5SDimitry Andric bool is(TokenKind K) const { return Kind == K; }
13990b57cec5SDimitry Andric
getLocationclang::MMToken14000b57cec5SDimitry Andric SourceLocation getLocation() const {
14010b57cec5SDimitry Andric return SourceLocation::getFromRawEncoding(Location);
14020b57cec5SDimitry Andric }
14030b57cec5SDimitry Andric
getIntegerclang::MMToken14040b57cec5SDimitry Andric uint64_t getInteger() const {
14050b57cec5SDimitry Andric return Kind == IntegerLiteral ? IntegerValue : 0;
14060b57cec5SDimitry Andric }
14070b57cec5SDimitry Andric
getStringclang::MMToken14080b57cec5SDimitry Andric StringRef getString() const {
14090b57cec5SDimitry Andric return Kind == IntegerLiteral ? StringRef()
14100b57cec5SDimitry Andric : StringRef(StringData, StringLength);
14110b57cec5SDimitry Andric }
14120b57cec5SDimitry Andric };
14130b57cec5SDimitry Andric
14140b57cec5SDimitry Andric class ModuleMapParser {
14150b57cec5SDimitry Andric Lexer &L;
14160b57cec5SDimitry Andric SourceManager &SourceMgr;
14170b57cec5SDimitry Andric
14180b57cec5SDimitry Andric /// Default target information, used only for string literal
14190b57cec5SDimitry Andric /// parsing.
14200b57cec5SDimitry Andric const TargetInfo *Target;
14210b57cec5SDimitry Andric
14220b57cec5SDimitry Andric DiagnosticsEngine &Diags;
14230b57cec5SDimitry Andric ModuleMap ⤅
14240b57cec5SDimitry Andric
14250b57cec5SDimitry Andric /// The current module map file.
14260b57cec5SDimitry Andric const FileEntry *ModuleMapFile;
14270b57cec5SDimitry Andric
14280b57cec5SDimitry Andric /// Source location of most recent parsed module declaration
14290b57cec5SDimitry Andric SourceLocation CurrModuleDeclLoc;
14300b57cec5SDimitry Andric
14310b57cec5SDimitry Andric /// The directory that file names in this module map file should
14320b57cec5SDimitry Andric /// be resolved relative to.
14330b57cec5SDimitry Andric const DirectoryEntry *Directory;
14340b57cec5SDimitry Andric
14350b57cec5SDimitry Andric /// Whether this module map is in a system header directory.
14360b57cec5SDimitry Andric bool IsSystem;
14370b57cec5SDimitry Andric
14380b57cec5SDimitry Andric /// Whether an error occurred.
14390b57cec5SDimitry Andric bool HadError = false;
14400b57cec5SDimitry Andric
14410b57cec5SDimitry Andric /// Stores string data for the various string literals referenced
14420b57cec5SDimitry Andric /// during parsing.
14430b57cec5SDimitry Andric llvm::BumpPtrAllocator StringData;
14440b57cec5SDimitry Andric
14450b57cec5SDimitry Andric /// The current token.
14460b57cec5SDimitry Andric MMToken Tok;
14470b57cec5SDimitry Andric
14480b57cec5SDimitry Andric /// The active module.
14490b57cec5SDimitry Andric Module *ActiveModule = nullptr;
14500b57cec5SDimitry Andric
14510b57cec5SDimitry Andric /// Whether a module uses the 'requires excluded' hack to mark its
14520b57cec5SDimitry Andric /// contents as 'textual'.
14530b57cec5SDimitry Andric ///
14540b57cec5SDimitry Andric /// On older Darwin SDK versions, 'requires excluded' is used to mark the
14550b57cec5SDimitry Andric /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as
14560b57cec5SDimitry Andric /// non-modular headers. For backwards compatibility, we continue to
14570b57cec5SDimitry Andric /// support this idiom for just these modules, and map the headers to
14580b57cec5SDimitry Andric /// 'textual' to match the original intent.
14590b57cec5SDimitry Andric llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack;
14600b57cec5SDimitry Andric
14610b57cec5SDimitry Andric /// Consume the current token and return its location.
14620b57cec5SDimitry Andric SourceLocation consumeToken();
14630b57cec5SDimitry Andric
14640b57cec5SDimitry Andric /// Skip tokens until we reach the a token with the given kind
14650b57cec5SDimitry Andric /// (or the end of the file).
14660b57cec5SDimitry Andric void skipUntil(MMToken::TokenKind K);
14670b57cec5SDimitry Andric
14680b57cec5SDimitry Andric using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>;
14690b57cec5SDimitry Andric
14700b57cec5SDimitry Andric bool parseModuleId(ModuleId &Id);
14710b57cec5SDimitry Andric void parseModuleDecl();
14720b57cec5SDimitry Andric void parseExternModuleDecl();
14730b57cec5SDimitry Andric void parseRequiresDecl();
14740b57cec5SDimitry Andric void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc);
14750b57cec5SDimitry Andric void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc);
14760b57cec5SDimitry Andric void parseExportDecl();
14770b57cec5SDimitry Andric void parseExportAsDecl();
14780b57cec5SDimitry Andric void parseUseDecl();
14790b57cec5SDimitry Andric void parseLinkDecl();
14800b57cec5SDimitry Andric void parseConfigMacros();
14810b57cec5SDimitry Andric void parseConflict();
14820b57cec5SDimitry Andric void parseInferredModuleDecl(bool Framework, bool Explicit);
14830b57cec5SDimitry Andric
14840b57cec5SDimitry Andric /// Private modules are canonicalized as Foo_Private. Clang provides extra
14850b57cec5SDimitry Andric /// module map search logic to find the appropriate private module when PCH
14860b57cec5SDimitry Andric /// is used with implicit module maps. Warn when private modules are written
14870b57cec5SDimitry Andric /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
14880b57cec5SDimitry Andric void diagnosePrivateModules(SourceLocation ExplicitLoc,
14890b57cec5SDimitry Andric SourceLocation FrameworkLoc);
14900b57cec5SDimitry Andric
14910b57cec5SDimitry Andric using Attributes = ModuleMap::Attributes;
14920b57cec5SDimitry Andric
14930b57cec5SDimitry Andric bool parseOptionalAttributes(Attributes &Attrs);
14940b57cec5SDimitry Andric
14950b57cec5SDimitry Andric public:
ModuleMapParser(Lexer & L,SourceManager & SourceMgr,const TargetInfo * Target,DiagnosticsEngine & Diags,ModuleMap & Map,const FileEntry * ModuleMapFile,const DirectoryEntry * Directory,bool IsSystem)14960b57cec5SDimitry Andric explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr,
14970b57cec5SDimitry Andric const TargetInfo *Target, DiagnosticsEngine &Diags,
14980b57cec5SDimitry Andric ModuleMap &Map, const FileEntry *ModuleMapFile,
14990b57cec5SDimitry Andric const DirectoryEntry *Directory, bool IsSystem)
15000b57cec5SDimitry Andric : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map),
15010b57cec5SDimitry Andric ModuleMapFile(ModuleMapFile), Directory(Directory),
15020b57cec5SDimitry Andric IsSystem(IsSystem) {
15030b57cec5SDimitry Andric Tok.clear();
15040b57cec5SDimitry Andric consumeToken();
15050b57cec5SDimitry Andric }
15060b57cec5SDimitry Andric
15070b57cec5SDimitry Andric bool parseModuleMapFile();
15080b57cec5SDimitry Andric
terminatedByDirective()15090b57cec5SDimitry Andric bool terminatedByDirective() { return false; }
getLocation()15100b57cec5SDimitry Andric SourceLocation getLocation() { return Tok.getLocation(); }
15110b57cec5SDimitry Andric };
15120b57cec5SDimitry Andric
15130b57cec5SDimitry Andric } // namespace clang
15140b57cec5SDimitry Andric
consumeToken()15150b57cec5SDimitry Andric SourceLocation ModuleMapParser::consumeToken() {
15160b57cec5SDimitry Andric SourceLocation Result = Tok.getLocation();
15170b57cec5SDimitry Andric
15180b57cec5SDimitry Andric retry:
15190b57cec5SDimitry Andric Tok.clear();
15200b57cec5SDimitry Andric Token LToken;
15210b57cec5SDimitry Andric L.LexFromRawLexer(LToken);
15220b57cec5SDimitry Andric Tok.Location = LToken.getLocation().getRawEncoding();
15230b57cec5SDimitry Andric switch (LToken.getKind()) {
15240b57cec5SDimitry Andric case tok::raw_identifier: {
15250b57cec5SDimitry Andric StringRef RI = LToken.getRawIdentifier();
15260b57cec5SDimitry Andric Tok.StringData = RI.data();
15270b57cec5SDimitry Andric Tok.StringLength = RI.size();
15280b57cec5SDimitry Andric Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI)
15290b57cec5SDimitry Andric .Case("config_macros", MMToken::ConfigMacros)
15300b57cec5SDimitry Andric .Case("conflict", MMToken::Conflict)
15310b57cec5SDimitry Andric .Case("exclude", MMToken::ExcludeKeyword)
15320b57cec5SDimitry Andric .Case("explicit", MMToken::ExplicitKeyword)
15330b57cec5SDimitry Andric .Case("export", MMToken::ExportKeyword)
15340b57cec5SDimitry Andric .Case("export_as", MMToken::ExportAsKeyword)
15350b57cec5SDimitry Andric .Case("extern", MMToken::ExternKeyword)
15360b57cec5SDimitry Andric .Case("framework", MMToken::FrameworkKeyword)
15370b57cec5SDimitry Andric .Case("header", MMToken::HeaderKeyword)
15380b57cec5SDimitry Andric .Case("link", MMToken::LinkKeyword)
15390b57cec5SDimitry Andric .Case("module", MMToken::ModuleKeyword)
15400b57cec5SDimitry Andric .Case("private", MMToken::PrivateKeyword)
15410b57cec5SDimitry Andric .Case("requires", MMToken::RequiresKeyword)
15420b57cec5SDimitry Andric .Case("textual", MMToken::TextualKeyword)
15430b57cec5SDimitry Andric .Case("umbrella", MMToken::UmbrellaKeyword)
15440b57cec5SDimitry Andric .Case("use", MMToken::UseKeyword)
15450b57cec5SDimitry Andric .Default(MMToken::Identifier);
15460b57cec5SDimitry Andric break;
15470b57cec5SDimitry Andric }
15480b57cec5SDimitry Andric
15490b57cec5SDimitry Andric case tok::comma:
15500b57cec5SDimitry Andric Tok.Kind = MMToken::Comma;
15510b57cec5SDimitry Andric break;
15520b57cec5SDimitry Andric
15530b57cec5SDimitry Andric case tok::eof:
15540b57cec5SDimitry Andric Tok.Kind = MMToken::EndOfFile;
15550b57cec5SDimitry Andric break;
15560b57cec5SDimitry Andric
15570b57cec5SDimitry Andric case tok::l_brace:
15580b57cec5SDimitry Andric Tok.Kind = MMToken::LBrace;
15590b57cec5SDimitry Andric break;
15600b57cec5SDimitry Andric
15610b57cec5SDimitry Andric case tok::l_square:
15620b57cec5SDimitry Andric Tok.Kind = MMToken::LSquare;
15630b57cec5SDimitry Andric break;
15640b57cec5SDimitry Andric
15650b57cec5SDimitry Andric case tok::period:
15660b57cec5SDimitry Andric Tok.Kind = MMToken::Period;
15670b57cec5SDimitry Andric break;
15680b57cec5SDimitry Andric
15690b57cec5SDimitry Andric case tok::r_brace:
15700b57cec5SDimitry Andric Tok.Kind = MMToken::RBrace;
15710b57cec5SDimitry Andric break;
15720b57cec5SDimitry Andric
15730b57cec5SDimitry Andric case tok::r_square:
15740b57cec5SDimitry Andric Tok.Kind = MMToken::RSquare;
15750b57cec5SDimitry Andric break;
15760b57cec5SDimitry Andric
15770b57cec5SDimitry Andric case tok::star:
15780b57cec5SDimitry Andric Tok.Kind = MMToken::Star;
15790b57cec5SDimitry Andric break;
15800b57cec5SDimitry Andric
15810b57cec5SDimitry Andric case tok::exclaim:
15820b57cec5SDimitry Andric Tok.Kind = MMToken::Exclaim;
15830b57cec5SDimitry Andric break;
15840b57cec5SDimitry Andric
15850b57cec5SDimitry Andric case tok::string_literal: {
15860b57cec5SDimitry Andric if (LToken.hasUDSuffix()) {
15870b57cec5SDimitry Andric Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl);
15880b57cec5SDimitry Andric HadError = true;
15890b57cec5SDimitry Andric goto retry;
15900b57cec5SDimitry Andric }
15910b57cec5SDimitry Andric
15920b57cec5SDimitry Andric // Parse the string literal.
15930b57cec5SDimitry Andric LangOptions LangOpts;
15940b57cec5SDimitry Andric StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target);
15950b57cec5SDimitry Andric if (StringLiteral.hadError)
15960b57cec5SDimitry Andric goto retry;
15970b57cec5SDimitry Andric
15980b57cec5SDimitry Andric // Copy the string literal into our string data allocator.
15990b57cec5SDimitry Andric unsigned Length = StringLiteral.GetStringLength();
16000b57cec5SDimitry Andric char *Saved = StringData.Allocate<char>(Length + 1);
16010b57cec5SDimitry Andric memcpy(Saved, StringLiteral.GetString().data(), Length);
16020b57cec5SDimitry Andric Saved[Length] = 0;
16030b57cec5SDimitry Andric
16040b57cec5SDimitry Andric // Form the token.
16050b57cec5SDimitry Andric Tok.Kind = MMToken::StringLiteral;
16060b57cec5SDimitry Andric Tok.StringData = Saved;
16070b57cec5SDimitry Andric Tok.StringLength = Length;
16080b57cec5SDimitry Andric break;
16090b57cec5SDimitry Andric }
16100b57cec5SDimitry Andric
16110b57cec5SDimitry Andric case tok::numeric_constant: {
16120b57cec5SDimitry Andric // We don't support any suffixes or other complications.
16130b57cec5SDimitry Andric SmallString<32> SpellingBuffer;
16140b57cec5SDimitry Andric SpellingBuffer.resize(LToken.getLength() + 1);
16150b57cec5SDimitry Andric const char *Start = SpellingBuffer.data();
16160b57cec5SDimitry Andric unsigned Length =
16170b57cec5SDimitry Andric Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts());
16180b57cec5SDimitry Andric uint64_t Value;
16190b57cec5SDimitry Andric if (StringRef(Start, Length).getAsInteger(0, Value)) {
16200b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
16210b57cec5SDimitry Andric HadError = true;
16220b57cec5SDimitry Andric goto retry;
16230b57cec5SDimitry Andric }
16240b57cec5SDimitry Andric
16250b57cec5SDimitry Andric Tok.Kind = MMToken::IntegerLiteral;
16260b57cec5SDimitry Andric Tok.IntegerValue = Value;
16270b57cec5SDimitry Andric break;
16280b57cec5SDimitry Andric }
16290b57cec5SDimitry Andric
16300b57cec5SDimitry Andric case tok::comment:
16310b57cec5SDimitry Andric goto retry;
16320b57cec5SDimitry Andric
16330b57cec5SDimitry Andric case tok::hash:
16340b57cec5SDimitry Andric // A module map can be terminated prematurely by
16350b57cec5SDimitry Andric // #pragma clang module contents
16360b57cec5SDimitry Andric // When building the module, we'll treat the rest of the file as the
16370b57cec5SDimitry Andric // contents of the module.
16380b57cec5SDimitry Andric {
16390b57cec5SDimitry Andric auto NextIsIdent = [&](StringRef Str) -> bool {
16400b57cec5SDimitry Andric L.LexFromRawLexer(LToken);
16410b57cec5SDimitry Andric return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) &&
16420b57cec5SDimitry Andric LToken.getRawIdentifier() == Str;
16430b57cec5SDimitry Andric };
16440b57cec5SDimitry Andric if (NextIsIdent("pragma") && NextIsIdent("clang") &&
16450b57cec5SDimitry Andric NextIsIdent("module") && NextIsIdent("contents")) {
16460b57cec5SDimitry Andric Tok.Kind = MMToken::EndOfFile;
16470b57cec5SDimitry Andric break;
16480b57cec5SDimitry Andric }
16490b57cec5SDimitry Andric }
16500b57cec5SDimitry Andric LLVM_FALLTHROUGH;
16510b57cec5SDimitry Andric
16520b57cec5SDimitry Andric default:
16530b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token);
16540b57cec5SDimitry Andric HadError = true;
16550b57cec5SDimitry Andric goto retry;
16560b57cec5SDimitry Andric }
16570b57cec5SDimitry Andric
16580b57cec5SDimitry Andric return Result;
16590b57cec5SDimitry Andric }
16600b57cec5SDimitry Andric
skipUntil(MMToken::TokenKind K)16610b57cec5SDimitry Andric void ModuleMapParser::skipUntil(MMToken::TokenKind K) {
16620b57cec5SDimitry Andric unsigned braceDepth = 0;
16630b57cec5SDimitry Andric unsigned squareDepth = 0;
16640b57cec5SDimitry Andric do {
16650b57cec5SDimitry Andric switch (Tok.Kind) {
16660b57cec5SDimitry Andric case MMToken::EndOfFile:
16670b57cec5SDimitry Andric return;
16680b57cec5SDimitry Andric
16690b57cec5SDimitry Andric case MMToken::LBrace:
16700b57cec5SDimitry Andric if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
16710b57cec5SDimitry Andric return;
16720b57cec5SDimitry Andric
16730b57cec5SDimitry Andric ++braceDepth;
16740b57cec5SDimitry Andric break;
16750b57cec5SDimitry Andric
16760b57cec5SDimitry Andric case MMToken::LSquare:
16770b57cec5SDimitry Andric if (Tok.is(K) && braceDepth == 0 && squareDepth == 0)
16780b57cec5SDimitry Andric return;
16790b57cec5SDimitry Andric
16800b57cec5SDimitry Andric ++squareDepth;
16810b57cec5SDimitry Andric break;
16820b57cec5SDimitry Andric
16830b57cec5SDimitry Andric case MMToken::RBrace:
16840b57cec5SDimitry Andric if (braceDepth > 0)
16850b57cec5SDimitry Andric --braceDepth;
16860b57cec5SDimitry Andric else if (Tok.is(K))
16870b57cec5SDimitry Andric return;
16880b57cec5SDimitry Andric break;
16890b57cec5SDimitry Andric
16900b57cec5SDimitry Andric case MMToken::RSquare:
16910b57cec5SDimitry Andric if (squareDepth > 0)
16920b57cec5SDimitry Andric --squareDepth;
16930b57cec5SDimitry Andric else if (Tok.is(K))
16940b57cec5SDimitry Andric return;
16950b57cec5SDimitry Andric break;
16960b57cec5SDimitry Andric
16970b57cec5SDimitry Andric default:
16980b57cec5SDimitry Andric if (braceDepth == 0 && squareDepth == 0 && Tok.is(K))
16990b57cec5SDimitry Andric return;
17000b57cec5SDimitry Andric break;
17010b57cec5SDimitry Andric }
17020b57cec5SDimitry Andric
17030b57cec5SDimitry Andric consumeToken();
17040b57cec5SDimitry Andric } while (true);
17050b57cec5SDimitry Andric }
17060b57cec5SDimitry Andric
17070b57cec5SDimitry Andric /// Parse a module-id.
17080b57cec5SDimitry Andric ///
17090b57cec5SDimitry Andric /// module-id:
17100b57cec5SDimitry Andric /// identifier
17110b57cec5SDimitry Andric /// identifier '.' module-id
17120b57cec5SDimitry Andric ///
17130b57cec5SDimitry Andric /// \returns true if an error occurred, false otherwise.
parseModuleId(ModuleId & Id)17140b57cec5SDimitry Andric bool ModuleMapParser::parseModuleId(ModuleId &Id) {
17150b57cec5SDimitry Andric Id.clear();
17160b57cec5SDimitry Andric do {
17170b57cec5SDimitry Andric if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) {
17185ffd83dbSDimitry Andric Id.push_back(
17195ffd83dbSDimitry Andric std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
17200b57cec5SDimitry Andric consumeToken();
17210b57cec5SDimitry Andric } else {
17220b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name);
17230b57cec5SDimitry Andric return true;
17240b57cec5SDimitry Andric }
17250b57cec5SDimitry Andric
17260b57cec5SDimitry Andric if (!Tok.is(MMToken::Period))
17270b57cec5SDimitry Andric break;
17280b57cec5SDimitry Andric
17290b57cec5SDimitry Andric consumeToken();
17300b57cec5SDimitry Andric } while (true);
17310b57cec5SDimitry Andric
17320b57cec5SDimitry Andric return false;
17330b57cec5SDimitry Andric }
17340b57cec5SDimitry Andric
17350b57cec5SDimitry Andric namespace {
17360b57cec5SDimitry Andric
17370b57cec5SDimitry Andric /// Enumerates the known attributes.
17380b57cec5SDimitry Andric enum AttributeKind {
17390b57cec5SDimitry Andric /// An unknown attribute.
17400b57cec5SDimitry Andric AT_unknown,
17410b57cec5SDimitry Andric
17420b57cec5SDimitry Andric /// The 'system' attribute.
17430b57cec5SDimitry Andric AT_system,
17440b57cec5SDimitry Andric
17450b57cec5SDimitry Andric /// The 'extern_c' attribute.
17460b57cec5SDimitry Andric AT_extern_c,
17470b57cec5SDimitry Andric
17480b57cec5SDimitry Andric /// The 'exhaustive' attribute.
17490b57cec5SDimitry Andric AT_exhaustive,
17500b57cec5SDimitry Andric
17510b57cec5SDimitry Andric /// The 'no_undeclared_includes' attribute.
17520b57cec5SDimitry Andric AT_no_undeclared_includes
17530b57cec5SDimitry Andric };
17540b57cec5SDimitry Andric
17550b57cec5SDimitry Andric } // namespace
17560b57cec5SDimitry Andric
17570b57cec5SDimitry Andric /// Private modules are canonicalized as Foo_Private. Clang provides extra
17580b57cec5SDimitry Andric /// module map search logic to find the appropriate private module when PCH
17590b57cec5SDimitry Andric /// is used with implicit module maps. Warn when private modules are written
17600b57cec5SDimitry Andric /// in other ways (FooPrivate and Foo.Private), providing notes and fixits.
diagnosePrivateModules(SourceLocation ExplicitLoc,SourceLocation FrameworkLoc)17610b57cec5SDimitry Andric void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc,
17620b57cec5SDimitry Andric SourceLocation FrameworkLoc) {
17630b57cec5SDimitry Andric auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical,
17640b57cec5SDimitry Andric const Module *M, SourceRange ReplLoc) {
17650b57cec5SDimitry Andric auto D = Diags.Report(ActiveModule->DefinitionLoc,
17660b57cec5SDimitry Andric diag::note_mmap_rename_top_level_private_module);
17670b57cec5SDimitry Andric D << BadName << M->Name;
17680b57cec5SDimitry Andric D << FixItHint::CreateReplacement(ReplLoc, Canonical);
17690b57cec5SDimitry Andric };
17700b57cec5SDimitry Andric
17710b57cec5SDimitry Andric for (auto E = Map.module_begin(); E != Map.module_end(); ++E) {
17720b57cec5SDimitry Andric auto const *M = E->getValue();
17730b57cec5SDimitry Andric if (M->Directory != ActiveModule->Directory)
17740b57cec5SDimitry Andric continue;
17750b57cec5SDimitry Andric
17760b57cec5SDimitry Andric SmallString<128> FullName(ActiveModule->getFullModuleName());
17770b57cec5SDimitry Andric if (!FullName.startswith(M->Name) && !FullName.endswith("Private"))
17780b57cec5SDimitry Andric continue;
17790b57cec5SDimitry Andric SmallString<128> FixedPrivModDecl;
17800b57cec5SDimitry Andric SmallString<128> Canonical(M->Name);
17810b57cec5SDimitry Andric Canonical.append("_Private");
17820b57cec5SDimitry Andric
17830b57cec5SDimitry Andric // Foo.Private -> Foo_Private
17840b57cec5SDimitry Andric if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent &&
17850b57cec5SDimitry Andric M->Name == ActiveModule->Parent->Name) {
17860b57cec5SDimitry Andric Diags.Report(ActiveModule->DefinitionLoc,
17870b57cec5SDimitry Andric diag::warn_mmap_mismatched_private_submodule)
17880b57cec5SDimitry Andric << FullName;
17890b57cec5SDimitry Andric
17900b57cec5SDimitry Andric SourceLocation FixItInitBegin = CurrModuleDeclLoc;
17910b57cec5SDimitry Andric if (FrameworkLoc.isValid())
17920b57cec5SDimitry Andric FixItInitBegin = FrameworkLoc;
17930b57cec5SDimitry Andric if (ExplicitLoc.isValid())
17940b57cec5SDimitry Andric FixItInitBegin = ExplicitLoc;
17950b57cec5SDimitry Andric
17960b57cec5SDimitry Andric if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework)
17970b57cec5SDimitry Andric FixedPrivModDecl.append("framework ");
17980b57cec5SDimitry Andric FixedPrivModDecl.append("module ");
17990b57cec5SDimitry Andric FixedPrivModDecl.append(Canonical);
18000b57cec5SDimitry Andric
18010b57cec5SDimitry Andric GenNoteAndFixIt(FullName, FixedPrivModDecl, M,
18020b57cec5SDimitry Andric SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc));
18030b57cec5SDimitry Andric continue;
18040b57cec5SDimitry Andric }
18050b57cec5SDimitry Andric
18060b57cec5SDimitry Andric // FooPrivate and whatnots -> Foo_Private
18070b57cec5SDimitry Andric if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name &&
18080b57cec5SDimitry Andric ActiveModule->Name != Canonical) {
18090b57cec5SDimitry Andric Diags.Report(ActiveModule->DefinitionLoc,
18100b57cec5SDimitry Andric diag::warn_mmap_mismatched_private_module_name)
18110b57cec5SDimitry Andric << ActiveModule->Name;
18120b57cec5SDimitry Andric GenNoteAndFixIt(ActiveModule->Name, Canonical, M,
18130b57cec5SDimitry Andric SourceRange(ActiveModule->DefinitionLoc));
18140b57cec5SDimitry Andric }
18150b57cec5SDimitry Andric }
18160b57cec5SDimitry Andric }
18170b57cec5SDimitry Andric
18180b57cec5SDimitry Andric /// Parse a module declaration.
18190b57cec5SDimitry Andric ///
18200b57cec5SDimitry Andric /// module-declaration:
18210b57cec5SDimitry Andric /// 'extern' 'module' module-id string-literal
18220b57cec5SDimitry Andric /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt]
18230b57cec5SDimitry Andric /// { module-member* }
18240b57cec5SDimitry Andric ///
18250b57cec5SDimitry Andric /// module-member:
18260b57cec5SDimitry Andric /// requires-declaration
18270b57cec5SDimitry Andric /// header-declaration
18280b57cec5SDimitry Andric /// submodule-declaration
18290b57cec5SDimitry Andric /// export-declaration
18300b57cec5SDimitry Andric /// export-as-declaration
18310b57cec5SDimitry Andric /// link-declaration
18320b57cec5SDimitry Andric ///
18330b57cec5SDimitry Andric /// submodule-declaration:
18340b57cec5SDimitry Andric /// module-declaration
18350b57cec5SDimitry Andric /// inferred-submodule-declaration
parseModuleDecl()18360b57cec5SDimitry Andric void ModuleMapParser::parseModuleDecl() {
18370b57cec5SDimitry Andric assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) ||
18380b57cec5SDimitry Andric Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword));
18390b57cec5SDimitry Andric if (Tok.is(MMToken::ExternKeyword)) {
18400b57cec5SDimitry Andric parseExternModuleDecl();
18410b57cec5SDimitry Andric return;
18420b57cec5SDimitry Andric }
18430b57cec5SDimitry Andric
18440b57cec5SDimitry Andric // Parse 'explicit' or 'framework' keyword, if present.
18450b57cec5SDimitry Andric SourceLocation ExplicitLoc;
18460b57cec5SDimitry Andric SourceLocation FrameworkLoc;
18470b57cec5SDimitry Andric bool Explicit = false;
18480b57cec5SDimitry Andric bool Framework = false;
18490b57cec5SDimitry Andric
18500b57cec5SDimitry Andric // Parse 'explicit' keyword, if present.
18510b57cec5SDimitry Andric if (Tok.is(MMToken::ExplicitKeyword)) {
18520b57cec5SDimitry Andric ExplicitLoc = consumeToken();
18530b57cec5SDimitry Andric Explicit = true;
18540b57cec5SDimitry Andric }
18550b57cec5SDimitry Andric
18560b57cec5SDimitry Andric // Parse 'framework' keyword, if present.
18570b57cec5SDimitry Andric if (Tok.is(MMToken::FrameworkKeyword)) {
18580b57cec5SDimitry Andric FrameworkLoc = consumeToken();
18590b57cec5SDimitry Andric Framework = true;
18600b57cec5SDimitry Andric }
18610b57cec5SDimitry Andric
18620b57cec5SDimitry Andric // Parse 'module' keyword.
18630b57cec5SDimitry Andric if (!Tok.is(MMToken::ModuleKeyword)) {
18640b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
18650b57cec5SDimitry Andric consumeToken();
18660b57cec5SDimitry Andric HadError = true;
18670b57cec5SDimitry Andric return;
18680b57cec5SDimitry Andric }
18690b57cec5SDimitry Andric CurrModuleDeclLoc = consumeToken(); // 'module' keyword
18700b57cec5SDimitry Andric
18710b57cec5SDimitry Andric // If we have a wildcard for the module name, this is an inferred submodule.
18720b57cec5SDimitry Andric // Parse it.
18730b57cec5SDimitry Andric if (Tok.is(MMToken::Star))
18740b57cec5SDimitry Andric return parseInferredModuleDecl(Framework, Explicit);
18750b57cec5SDimitry Andric
18760b57cec5SDimitry Andric // Parse the module name.
18770b57cec5SDimitry Andric ModuleId Id;
18780b57cec5SDimitry Andric if (parseModuleId(Id)) {
18790b57cec5SDimitry Andric HadError = true;
18800b57cec5SDimitry Andric return;
18810b57cec5SDimitry Andric }
18820b57cec5SDimitry Andric
18830b57cec5SDimitry Andric if (ActiveModule) {
18840b57cec5SDimitry Andric if (Id.size() > 1) {
18850b57cec5SDimitry Andric Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id)
18860b57cec5SDimitry Andric << SourceRange(Id.front().second, Id.back().second);
18870b57cec5SDimitry Andric
18880b57cec5SDimitry Andric HadError = true;
18890b57cec5SDimitry Andric return;
18900b57cec5SDimitry Andric }
18910b57cec5SDimitry Andric } else if (Id.size() == 1 && Explicit) {
18920b57cec5SDimitry Andric // Top-level modules can't be explicit.
18930b57cec5SDimitry Andric Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level);
18940b57cec5SDimitry Andric Explicit = false;
18950b57cec5SDimitry Andric ExplicitLoc = SourceLocation();
18960b57cec5SDimitry Andric HadError = true;
18970b57cec5SDimitry Andric }
18980b57cec5SDimitry Andric
18990b57cec5SDimitry Andric Module *PreviousActiveModule = ActiveModule;
19000b57cec5SDimitry Andric if (Id.size() > 1) {
19010b57cec5SDimitry Andric // This module map defines a submodule. Go find the module of which it
19020b57cec5SDimitry Andric // is a submodule.
19030b57cec5SDimitry Andric ActiveModule = nullptr;
19040b57cec5SDimitry Andric const Module *TopLevelModule = nullptr;
19050b57cec5SDimitry Andric for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) {
19060b57cec5SDimitry Andric if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) {
19070b57cec5SDimitry Andric if (I == 0)
19080b57cec5SDimitry Andric TopLevelModule = Next;
19090b57cec5SDimitry Andric ActiveModule = Next;
19100b57cec5SDimitry Andric continue;
19110b57cec5SDimitry Andric }
19120b57cec5SDimitry Andric
1913af732203SDimitry Andric Diags.Report(Id[I].second, diag::err_mmap_missing_parent_module)
1914af732203SDimitry Andric << Id[I].first << (ActiveModule != nullptr)
1915af732203SDimitry Andric << (ActiveModule
1916af732203SDimitry Andric ? ActiveModule->getTopLevelModule()->getFullModuleName()
1917af732203SDimitry Andric : "");
19180b57cec5SDimitry Andric HadError = true;
19190b57cec5SDimitry Andric }
19200b57cec5SDimitry Andric
1921af732203SDimitry Andric if (TopLevelModule &&
1922af732203SDimitry Andric ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) {
19230b57cec5SDimitry Andric assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) &&
19240b57cec5SDimitry Andric "submodule defined in same file as 'module *' that allowed its "
19250b57cec5SDimitry Andric "top-level module");
19260b57cec5SDimitry Andric Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile);
19270b57cec5SDimitry Andric }
19280b57cec5SDimitry Andric }
19290b57cec5SDimitry Andric
19300b57cec5SDimitry Andric StringRef ModuleName = Id.back().first;
19310b57cec5SDimitry Andric SourceLocation ModuleNameLoc = Id.back().second;
19320b57cec5SDimitry Andric
19330b57cec5SDimitry Andric // Parse the optional attribute list.
19340b57cec5SDimitry Andric Attributes Attrs;
19350b57cec5SDimitry Andric if (parseOptionalAttributes(Attrs))
19360b57cec5SDimitry Andric return;
19370b57cec5SDimitry Andric
19380b57cec5SDimitry Andric // Parse the opening brace.
19390b57cec5SDimitry Andric if (!Tok.is(MMToken::LBrace)) {
19400b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace)
19410b57cec5SDimitry Andric << ModuleName;
19420b57cec5SDimitry Andric HadError = true;
19430b57cec5SDimitry Andric return;
19440b57cec5SDimitry Andric }
19450b57cec5SDimitry Andric SourceLocation LBraceLoc = consumeToken();
19460b57cec5SDimitry Andric
19470b57cec5SDimitry Andric // Determine whether this (sub)module has already been defined.
19480b57cec5SDimitry Andric Module *ShadowingModule = nullptr;
19490b57cec5SDimitry Andric if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) {
19500b57cec5SDimitry Andric // We might see a (re)definition of a module that we already have a
19510b57cec5SDimitry Andric // definition for in two cases:
19520b57cec5SDimitry Andric // - If we loaded one definition from an AST file and we've just found a
19530b57cec5SDimitry Andric // corresponding definition in a module map file, or
19540b57cec5SDimitry Andric bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid();
19550b57cec5SDimitry Andric // - If we're building a (preprocessed) module and we've just loaded the
19560b57cec5SDimitry Andric // module map file from which it was created.
19570b57cec5SDimitry Andric bool ParsedAsMainInput =
19580b57cec5SDimitry Andric Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap &&
19590b57cec5SDimitry Andric Map.LangOpts.CurrentModule == ModuleName &&
19600b57cec5SDimitry Andric SourceMgr.getDecomposedLoc(ModuleNameLoc).first !=
19610b57cec5SDimitry Andric SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first;
19620b57cec5SDimitry Andric if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) {
19630b57cec5SDimitry Andric // Skip the module definition.
19640b57cec5SDimitry Andric skipUntil(MMToken::RBrace);
19650b57cec5SDimitry Andric if (Tok.is(MMToken::RBrace))
19660b57cec5SDimitry Andric consumeToken();
19670b57cec5SDimitry Andric else {
19680b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
19690b57cec5SDimitry Andric Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
19700b57cec5SDimitry Andric HadError = true;
19710b57cec5SDimitry Andric }
19720b57cec5SDimitry Andric return;
19730b57cec5SDimitry Andric }
19740b57cec5SDimitry Andric
19750b57cec5SDimitry Andric if (!Existing->Parent && Map.mayShadowNewModule(Existing)) {
19760b57cec5SDimitry Andric ShadowingModule = Existing;
19770b57cec5SDimitry Andric } else {
19780b57cec5SDimitry Andric // This is not a shawdowed module decl, it is an illegal redefinition.
19790b57cec5SDimitry Andric Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition)
19800b57cec5SDimitry Andric << ModuleName;
19810b57cec5SDimitry Andric Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition);
19820b57cec5SDimitry Andric
19830b57cec5SDimitry Andric // Skip the module definition.
19840b57cec5SDimitry Andric skipUntil(MMToken::RBrace);
19850b57cec5SDimitry Andric if (Tok.is(MMToken::RBrace))
19860b57cec5SDimitry Andric consumeToken();
19870b57cec5SDimitry Andric
19880b57cec5SDimitry Andric HadError = true;
19890b57cec5SDimitry Andric return;
19900b57cec5SDimitry Andric }
19910b57cec5SDimitry Andric }
19920b57cec5SDimitry Andric
19930b57cec5SDimitry Andric // Start defining this module.
19940b57cec5SDimitry Andric if (ShadowingModule) {
19950b57cec5SDimitry Andric ActiveModule =
19960b57cec5SDimitry Andric Map.createShadowedModule(ModuleName, Framework, ShadowingModule);
19970b57cec5SDimitry Andric } else {
19980b57cec5SDimitry Andric ActiveModule =
19990b57cec5SDimitry Andric Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit)
20000b57cec5SDimitry Andric .first;
20010b57cec5SDimitry Andric }
20020b57cec5SDimitry Andric
20030b57cec5SDimitry Andric ActiveModule->DefinitionLoc = ModuleNameLoc;
20040b57cec5SDimitry Andric if (Attrs.IsSystem || IsSystem)
20050b57cec5SDimitry Andric ActiveModule->IsSystem = true;
20060b57cec5SDimitry Andric if (Attrs.IsExternC)
20070b57cec5SDimitry Andric ActiveModule->IsExternC = true;
20080b57cec5SDimitry Andric if (Attrs.NoUndeclaredIncludes ||
20090b57cec5SDimitry Andric (!ActiveModule->Parent && ModuleName == "Darwin"))
20100b57cec5SDimitry Andric ActiveModule->NoUndeclaredIncludes = true;
20110b57cec5SDimitry Andric ActiveModule->Directory = Directory;
20120b57cec5SDimitry Andric
20130b57cec5SDimitry Andric StringRef MapFileName(ModuleMapFile->getName());
20140b57cec5SDimitry Andric if (MapFileName.endswith("module.private.modulemap") ||
20150b57cec5SDimitry Andric MapFileName.endswith("module_private.map")) {
20160b57cec5SDimitry Andric ActiveModule->ModuleMapIsPrivate = true;
20170b57cec5SDimitry Andric }
20180b57cec5SDimitry Andric
20190b57cec5SDimitry Andric // Private modules named as FooPrivate, Foo.Private or similar are likely a
20200b57cec5SDimitry Andric // user error; provide warnings, notes and fixits to direct users to use
20210b57cec5SDimitry Andric // Foo_Private instead.
20220b57cec5SDimitry Andric SourceLocation StartLoc =
20230b57cec5SDimitry Andric SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID());
20240b57cec5SDimitry Andric if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps &&
20250b57cec5SDimitry Andric !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule,
20260b57cec5SDimitry Andric StartLoc) &&
20270b57cec5SDimitry Andric !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name,
20280b57cec5SDimitry Andric StartLoc) &&
20290b57cec5SDimitry Andric ActiveModule->ModuleMapIsPrivate)
20300b57cec5SDimitry Andric diagnosePrivateModules(ExplicitLoc, FrameworkLoc);
20310b57cec5SDimitry Andric
20320b57cec5SDimitry Andric bool Done = false;
20330b57cec5SDimitry Andric do {
20340b57cec5SDimitry Andric switch (Tok.Kind) {
20350b57cec5SDimitry Andric case MMToken::EndOfFile:
20360b57cec5SDimitry Andric case MMToken::RBrace:
20370b57cec5SDimitry Andric Done = true;
20380b57cec5SDimitry Andric break;
20390b57cec5SDimitry Andric
20400b57cec5SDimitry Andric case MMToken::ConfigMacros:
20410b57cec5SDimitry Andric parseConfigMacros();
20420b57cec5SDimitry Andric break;
20430b57cec5SDimitry Andric
20440b57cec5SDimitry Andric case MMToken::Conflict:
20450b57cec5SDimitry Andric parseConflict();
20460b57cec5SDimitry Andric break;
20470b57cec5SDimitry Andric
20480b57cec5SDimitry Andric case MMToken::ExplicitKeyword:
20490b57cec5SDimitry Andric case MMToken::ExternKeyword:
20500b57cec5SDimitry Andric case MMToken::FrameworkKeyword:
20510b57cec5SDimitry Andric case MMToken::ModuleKeyword:
20520b57cec5SDimitry Andric parseModuleDecl();
20530b57cec5SDimitry Andric break;
20540b57cec5SDimitry Andric
20550b57cec5SDimitry Andric case MMToken::ExportKeyword:
20560b57cec5SDimitry Andric parseExportDecl();
20570b57cec5SDimitry Andric break;
20580b57cec5SDimitry Andric
20590b57cec5SDimitry Andric case MMToken::ExportAsKeyword:
20600b57cec5SDimitry Andric parseExportAsDecl();
20610b57cec5SDimitry Andric break;
20620b57cec5SDimitry Andric
20630b57cec5SDimitry Andric case MMToken::UseKeyword:
20640b57cec5SDimitry Andric parseUseDecl();
20650b57cec5SDimitry Andric break;
20660b57cec5SDimitry Andric
20670b57cec5SDimitry Andric case MMToken::RequiresKeyword:
20680b57cec5SDimitry Andric parseRequiresDecl();
20690b57cec5SDimitry Andric break;
20700b57cec5SDimitry Andric
20710b57cec5SDimitry Andric case MMToken::TextualKeyword:
20720b57cec5SDimitry Andric parseHeaderDecl(MMToken::TextualKeyword, consumeToken());
20730b57cec5SDimitry Andric break;
20740b57cec5SDimitry Andric
20750b57cec5SDimitry Andric case MMToken::UmbrellaKeyword: {
20760b57cec5SDimitry Andric SourceLocation UmbrellaLoc = consumeToken();
20770b57cec5SDimitry Andric if (Tok.is(MMToken::HeaderKeyword))
20780b57cec5SDimitry Andric parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc);
20790b57cec5SDimitry Andric else
20800b57cec5SDimitry Andric parseUmbrellaDirDecl(UmbrellaLoc);
20810b57cec5SDimitry Andric break;
20820b57cec5SDimitry Andric }
20830b57cec5SDimitry Andric
20840b57cec5SDimitry Andric case MMToken::ExcludeKeyword:
20850b57cec5SDimitry Andric parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken());
20860b57cec5SDimitry Andric break;
20870b57cec5SDimitry Andric
20880b57cec5SDimitry Andric case MMToken::PrivateKeyword:
20890b57cec5SDimitry Andric parseHeaderDecl(MMToken::PrivateKeyword, consumeToken());
20900b57cec5SDimitry Andric break;
20910b57cec5SDimitry Andric
20920b57cec5SDimitry Andric case MMToken::HeaderKeyword:
20930b57cec5SDimitry Andric parseHeaderDecl(MMToken::HeaderKeyword, consumeToken());
20940b57cec5SDimitry Andric break;
20950b57cec5SDimitry Andric
20960b57cec5SDimitry Andric case MMToken::LinkKeyword:
20970b57cec5SDimitry Andric parseLinkDecl();
20980b57cec5SDimitry Andric break;
20990b57cec5SDimitry Andric
21000b57cec5SDimitry Andric default:
21010b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member);
21020b57cec5SDimitry Andric consumeToken();
21030b57cec5SDimitry Andric break;
21040b57cec5SDimitry Andric }
21050b57cec5SDimitry Andric } while (!Done);
21060b57cec5SDimitry Andric
21070b57cec5SDimitry Andric if (Tok.is(MMToken::RBrace))
21080b57cec5SDimitry Andric consumeToken();
21090b57cec5SDimitry Andric else {
21100b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
21110b57cec5SDimitry Andric Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
21120b57cec5SDimitry Andric HadError = true;
21130b57cec5SDimitry Andric }
21140b57cec5SDimitry Andric
21150b57cec5SDimitry Andric // If the active module is a top-level framework, and there are no link
21160b57cec5SDimitry Andric // libraries, automatically link against the framework.
21170b57cec5SDimitry Andric if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() &&
21180b57cec5SDimitry Andric ActiveModule->LinkLibraries.empty()) {
21190b57cec5SDimitry Andric inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager());
21200b57cec5SDimitry Andric }
21210b57cec5SDimitry Andric
21220b57cec5SDimitry Andric // If the module meets all requirements but is still unavailable, mark the
21230b57cec5SDimitry Andric // whole tree as unavailable to prevent it from building.
21245ffd83dbSDimitry Andric if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable &&
21250b57cec5SDimitry Andric ActiveModule->Parent) {
21265ffd83dbSDimitry Andric ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false);
21270b57cec5SDimitry Andric ActiveModule->getTopLevelModule()->MissingHeaders.append(
21280b57cec5SDimitry Andric ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end());
21290b57cec5SDimitry Andric }
21300b57cec5SDimitry Andric
21310b57cec5SDimitry Andric // We're done parsing this module. Pop back to the previous module.
21320b57cec5SDimitry Andric ActiveModule = PreviousActiveModule;
21330b57cec5SDimitry Andric }
21340b57cec5SDimitry Andric
21350b57cec5SDimitry Andric /// Parse an extern module declaration.
21360b57cec5SDimitry Andric ///
21370b57cec5SDimitry Andric /// extern module-declaration:
21380b57cec5SDimitry Andric /// 'extern' 'module' module-id string-literal
parseExternModuleDecl()21390b57cec5SDimitry Andric void ModuleMapParser::parseExternModuleDecl() {
21400b57cec5SDimitry Andric assert(Tok.is(MMToken::ExternKeyword));
21410b57cec5SDimitry Andric SourceLocation ExternLoc = consumeToken(); // 'extern' keyword
21420b57cec5SDimitry Andric
21430b57cec5SDimitry Andric // Parse 'module' keyword.
21440b57cec5SDimitry Andric if (!Tok.is(MMToken::ModuleKeyword)) {
21450b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
21460b57cec5SDimitry Andric consumeToken();
21470b57cec5SDimitry Andric HadError = true;
21480b57cec5SDimitry Andric return;
21490b57cec5SDimitry Andric }
21500b57cec5SDimitry Andric consumeToken(); // 'module' keyword
21510b57cec5SDimitry Andric
21520b57cec5SDimitry Andric // Parse the module name.
21530b57cec5SDimitry Andric ModuleId Id;
21540b57cec5SDimitry Andric if (parseModuleId(Id)) {
21550b57cec5SDimitry Andric HadError = true;
21560b57cec5SDimitry Andric return;
21570b57cec5SDimitry Andric }
21580b57cec5SDimitry Andric
21590b57cec5SDimitry Andric // Parse the referenced module map file name.
21600b57cec5SDimitry Andric if (!Tok.is(MMToken::StringLiteral)) {
21610b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file);
21620b57cec5SDimitry Andric HadError = true;
21630b57cec5SDimitry Andric return;
21640b57cec5SDimitry Andric }
21655ffd83dbSDimitry Andric std::string FileName = std::string(Tok.getString());
21660b57cec5SDimitry Andric consumeToken(); // filename
21670b57cec5SDimitry Andric
21680b57cec5SDimitry Andric StringRef FileNameRef = FileName;
21690b57cec5SDimitry Andric SmallString<128> ModuleMapFileName;
21700b57cec5SDimitry Andric if (llvm::sys::path::is_relative(FileNameRef)) {
21710b57cec5SDimitry Andric ModuleMapFileName += Directory->getName();
21720b57cec5SDimitry Andric llvm::sys::path::append(ModuleMapFileName, FileName);
21730b57cec5SDimitry Andric FileNameRef = ModuleMapFileName;
21740b57cec5SDimitry Andric }
2175a7dea167SDimitry Andric if (auto File = SourceMgr.getFileManager().getFile(FileNameRef))
21760b57cec5SDimitry Andric Map.parseModuleMapFile(
2177a7dea167SDimitry Andric *File, /*IsSystem=*/false,
21780b57cec5SDimitry Andric Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd
21790b57cec5SDimitry Andric ? Directory
2180a7dea167SDimitry Andric : (*File)->getDir(),
21810b57cec5SDimitry Andric FileID(), nullptr, ExternLoc);
21820b57cec5SDimitry Andric }
21830b57cec5SDimitry Andric
21840b57cec5SDimitry Andric /// Whether to add the requirement \p Feature to the module \p M.
21850b57cec5SDimitry Andric ///
21860b57cec5SDimitry Andric /// This preserves backwards compatibility for two hacks in the Darwin system
21870b57cec5SDimitry Andric /// module map files:
21880b57cec5SDimitry Andric ///
21890b57cec5SDimitry Andric /// 1. The use of 'requires excluded' to make headers non-modular, which
21900b57cec5SDimitry Andric /// should really be mapped to 'textual' now that we have this feature. We
21910b57cec5SDimitry Andric /// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to
21920b57cec5SDimitry Andric /// true. Later, this bit will be used to map all the headers inside this
21930b57cec5SDimitry Andric /// module to 'textual'.
21940b57cec5SDimitry Andric ///
21950b57cec5SDimitry Andric /// This affects Darwin.C.excluded (for assert.h) and Tcl.Private.
21960b57cec5SDimitry Andric ///
21970b57cec5SDimitry Andric /// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement
21980b57cec5SDimitry Andric /// was never correct and causes issues now that we check it, so drop it.
shouldAddRequirement(Module * M,StringRef Feature,bool & IsRequiresExcludedHack)21990b57cec5SDimitry Andric static bool shouldAddRequirement(Module *M, StringRef Feature,
22000b57cec5SDimitry Andric bool &IsRequiresExcludedHack) {
22010b57cec5SDimitry Andric if (Feature == "excluded" &&
22020b57cec5SDimitry Andric (M->fullModuleNameIs({"Darwin", "C", "excluded"}) ||
22030b57cec5SDimitry Andric M->fullModuleNameIs({"Tcl", "Private"}))) {
22040b57cec5SDimitry Andric IsRequiresExcludedHack = true;
22050b57cec5SDimitry Andric return false;
22060b57cec5SDimitry Andric } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) {
22070b57cec5SDimitry Andric return false;
22080b57cec5SDimitry Andric }
22090b57cec5SDimitry Andric
22100b57cec5SDimitry Andric return true;
22110b57cec5SDimitry Andric }
22120b57cec5SDimitry Andric
22130b57cec5SDimitry Andric /// Parse a requires declaration.
22140b57cec5SDimitry Andric ///
22150b57cec5SDimitry Andric /// requires-declaration:
22160b57cec5SDimitry Andric /// 'requires' feature-list
22170b57cec5SDimitry Andric ///
22180b57cec5SDimitry Andric /// feature-list:
22190b57cec5SDimitry Andric /// feature ',' feature-list
22200b57cec5SDimitry Andric /// feature
22210b57cec5SDimitry Andric ///
22220b57cec5SDimitry Andric /// feature:
22230b57cec5SDimitry Andric /// '!'[opt] identifier
parseRequiresDecl()22240b57cec5SDimitry Andric void ModuleMapParser::parseRequiresDecl() {
22250b57cec5SDimitry Andric assert(Tok.is(MMToken::RequiresKeyword));
22260b57cec5SDimitry Andric
22270b57cec5SDimitry Andric // Parse 'requires' keyword.
22280b57cec5SDimitry Andric consumeToken();
22290b57cec5SDimitry Andric
22300b57cec5SDimitry Andric // Parse the feature-list.
22310b57cec5SDimitry Andric do {
22320b57cec5SDimitry Andric bool RequiredState = true;
22330b57cec5SDimitry Andric if (Tok.is(MMToken::Exclaim)) {
22340b57cec5SDimitry Andric RequiredState = false;
22350b57cec5SDimitry Andric consumeToken();
22360b57cec5SDimitry Andric }
22370b57cec5SDimitry Andric
22380b57cec5SDimitry Andric if (!Tok.is(MMToken::Identifier)) {
22390b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature);
22400b57cec5SDimitry Andric HadError = true;
22410b57cec5SDimitry Andric return;
22420b57cec5SDimitry Andric }
22430b57cec5SDimitry Andric
22440b57cec5SDimitry Andric // Consume the feature name.
22455ffd83dbSDimitry Andric std::string Feature = std::string(Tok.getString());
22460b57cec5SDimitry Andric consumeToken();
22470b57cec5SDimitry Andric
22480b57cec5SDimitry Andric bool IsRequiresExcludedHack = false;
22490b57cec5SDimitry Andric bool ShouldAddRequirement =
22500b57cec5SDimitry Andric shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack);
22510b57cec5SDimitry Andric
22520b57cec5SDimitry Andric if (IsRequiresExcludedHack)
22530b57cec5SDimitry Andric UsesRequiresExcludedHack.insert(ActiveModule);
22540b57cec5SDimitry Andric
22550b57cec5SDimitry Andric if (ShouldAddRequirement) {
22560b57cec5SDimitry Andric // Add this feature.
22570b57cec5SDimitry Andric ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts,
22580b57cec5SDimitry Andric *Map.Target);
22590b57cec5SDimitry Andric }
22600b57cec5SDimitry Andric
22610b57cec5SDimitry Andric if (!Tok.is(MMToken::Comma))
22620b57cec5SDimitry Andric break;
22630b57cec5SDimitry Andric
22640b57cec5SDimitry Andric // Consume the comma.
22650b57cec5SDimitry Andric consumeToken();
22660b57cec5SDimitry Andric } while (true);
22670b57cec5SDimitry Andric }
22680b57cec5SDimitry Andric
22690b57cec5SDimitry Andric /// Parse a header declaration.
22700b57cec5SDimitry Andric ///
22710b57cec5SDimitry Andric /// header-declaration:
22720b57cec5SDimitry Andric /// 'textual'[opt] 'header' string-literal
22730b57cec5SDimitry Andric /// 'private' 'textual'[opt] 'header' string-literal
22740b57cec5SDimitry Andric /// 'exclude' 'header' string-literal
22750b57cec5SDimitry Andric /// 'umbrella' 'header' string-literal
22760b57cec5SDimitry Andric ///
22770b57cec5SDimitry Andric /// FIXME: Support 'private textual header'.
parseHeaderDecl(MMToken::TokenKind LeadingToken,SourceLocation LeadingLoc)22780b57cec5SDimitry Andric void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken,
22790b57cec5SDimitry Andric SourceLocation LeadingLoc) {
22800b57cec5SDimitry Andric // We've already consumed the first token.
22810b57cec5SDimitry Andric ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader;
22820b57cec5SDimitry Andric if (LeadingToken == MMToken::PrivateKeyword) {
22830b57cec5SDimitry Andric Role = ModuleMap::PrivateHeader;
22840b57cec5SDimitry Andric // 'private' may optionally be followed by 'textual'.
22850b57cec5SDimitry Andric if (Tok.is(MMToken::TextualKeyword)) {
22860b57cec5SDimitry Andric LeadingToken = Tok.Kind;
22870b57cec5SDimitry Andric consumeToken();
22880b57cec5SDimitry Andric }
22890b57cec5SDimitry Andric }
22900b57cec5SDimitry Andric
22910b57cec5SDimitry Andric if (LeadingToken == MMToken::TextualKeyword)
22920b57cec5SDimitry Andric Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
22930b57cec5SDimitry Andric
22940b57cec5SDimitry Andric if (UsesRequiresExcludedHack.count(ActiveModule)) {
22950b57cec5SDimitry Andric // Mark this header 'textual' (see doc comment for
22960b57cec5SDimitry Andric // Module::UsesRequiresExcludedHack).
22970b57cec5SDimitry Andric Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader);
22980b57cec5SDimitry Andric }
22990b57cec5SDimitry Andric
23000b57cec5SDimitry Andric if (LeadingToken != MMToken::HeaderKeyword) {
23010b57cec5SDimitry Andric if (!Tok.is(MMToken::HeaderKeyword)) {
23020b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
23030b57cec5SDimitry Andric << (LeadingToken == MMToken::PrivateKeyword ? "private" :
23040b57cec5SDimitry Andric LeadingToken == MMToken::ExcludeKeyword ? "exclude" :
23050b57cec5SDimitry Andric LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella");
23060b57cec5SDimitry Andric return;
23070b57cec5SDimitry Andric }
23080b57cec5SDimitry Andric consumeToken();
23090b57cec5SDimitry Andric }
23100b57cec5SDimitry Andric
23110b57cec5SDimitry Andric // Parse the header name.
23120b57cec5SDimitry Andric if (!Tok.is(MMToken::StringLiteral)) {
23130b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
23140b57cec5SDimitry Andric << "header";
23150b57cec5SDimitry Andric HadError = true;
23160b57cec5SDimitry Andric return;
23170b57cec5SDimitry Andric }
23180b57cec5SDimitry Andric Module::UnresolvedHeaderDirective Header;
23195ffd83dbSDimitry Andric Header.FileName = std::string(Tok.getString());
23200b57cec5SDimitry Andric Header.FileNameLoc = consumeToken();
23210b57cec5SDimitry Andric Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword;
23220b57cec5SDimitry Andric Header.Kind =
23230b57cec5SDimitry Andric (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded
23240b57cec5SDimitry Andric : Map.headerRoleToKind(Role));
23250b57cec5SDimitry Andric
23260b57cec5SDimitry Andric // Check whether we already have an umbrella.
23270b57cec5SDimitry Andric if (Header.IsUmbrella && ActiveModule->Umbrella) {
23280b57cec5SDimitry Andric Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash)
23290b57cec5SDimitry Andric << ActiveModule->getFullModuleName();
23300b57cec5SDimitry Andric HadError = true;
23310b57cec5SDimitry Andric return;
23320b57cec5SDimitry Andric }
23330b57cec5SDimitry Andric
23340b57cec5SDimitry Andric // If we were given stat information, parse it so we can skip looking for
23350b57cec5SDimitry Andric // the file.
23360b57cec5SDimitry Andric if (Tok.is(MMToken::LBrace)) {
23370b57cec5SDimitry Andric SourceLocation LBraceLoc = consumeToken();
23380b57cec5SDimitry Andric
23390b57cec5SDimitry Andric while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) {
23400b57cec5SDimitry Andric enum Attribute { Size, ModTime, Unknown };
23410b57cec5SDimitry Andric StringRef Str = Tok.getString();
23420b57cec5SDimitry Andric SourceLocation Loc = consumeToken();
23430b57cec5SDimitry Andric switch (llvm::StringSwitch<Attribute>(Str)
23440b57cec5SDimitry Andric .Case("size", Size)
23450b57cec5SDimitry Andric .Case("mtime", ModTime)
23460b57cec5SDimitry Andric .Default(Unknown)) {
23470b57cec5SDimitry Andric case Size:
23480b57cec5SDimitry Andric if (Header.Size)
23490b57cec5SDimitry Andric Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
23500b57cec5SDimitry Andric if (!Tok.is(MMToken::IntegerLiteral)) {
23510b57cec5SDimitry Andric Diags.Report(Tok.getLocation(),
23520b57cec5SDimitry Andric diag::err_mmap_invalid_header_attribute_value) << Str;
23530b57cec5SDimitry Andric skipUntil(MMToken::RBrace);
23540b57cec5SDimitry Andric break;
23550b57cec5SDimitry Andric }
23560b57cec5SDimitry Andric Header.Size = Tok.getInteger();
23570b57cec5SDimitry Andric consumeToken();
23580b57cec5SDimitry Andric break;
23590b57cec5SDimitry Andric
23600b57cec5SDimitry Andric case ModTime:
23610b57cec5SDimitry Andric if (Header.ModTime)
23620b57cec5SDimitry Andric Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str;
23630b57cec5SDimitry Andric if (!Tok.is(MMToken::IntegerLiteral)) {
23640b57cec5SDimitry Andric Diags.Report(Tok.getLocation(),
23650b57cec5SDimitry Andric diag::err_mmap_invalid_header_attribute_value) << Str;
23660b57cec5SDimitry Andric skipUntil(MMToken::RBrace);
23670b57cec5SDimitry Andric break;
23680b57cec5SDimitry Andric }
23690b57cec5SDimitry Andric Header.ModTime = Tok.getInteger();
23700b57cec5SDimitry Andric consumeToken();
23710b57cec5SDimitry Andric break;
23720b57cec5SDimitry Andric
23730b57cec5SDimitry Andric case Unknown:
23740b57cec5SDimitry Andric Diags.Report(Loc, diag::err_mmap_expected_header_attribute);
23750b57cec5SDimitry Andric skipUntil(MMToken::RBrace);
23760b57cec5SDimitry Andric break;
23770b57cec5SDimitry Andric }
23780b57cec5SDimitry Andric }
23790b57cec5SDimitry Andric
23800b57cec5SDimitry Andric if (Tok.is(MMToken::RBrace))
23810b57cec5SDimitry Andric consumeToken();
23820b57cec5SDimitry Andric else {
23830b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
23840b57cec5SDimitry Andric Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
23850b57cec5SDimitry Andric HadError = true;
23860b57cec5SDimitry Andric }
23870b57cec5SDimitry Andric }
23880b57cec5SDimitry Andric
23890b57cec5SDimitry Andric bool NeedsFramework = false;
23900b57cec5SDimitry Andric Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework);
23910b57cec5SDimitry Andric
23920b57cec5SDimitry Andric if (NeedsFramework && ActiveModule)
23930b57cec5SDimitry Andric Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword)
23940b57cec5SDimitry Andric << ActiveModule->getFullModuleName()
23950b57cec5SDimitry Andric << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module");
23960b57cec5SDimitry Andric }
23970b57cec5SDimitry Andric
compareModuleHeaders(const Module::Header * A,const Module::Header * B)23980b57cec5SDimitry Andric static int compareModuleHeaders(const Module::Header *A,
23990b57cec5SDimitry Andric const Module::Header *B) {
24000b57cec5SDimitry Andric return A->NameAsWritten.compare(B->NameAsWritten);
24010b57cec5SDimitry Andric }
24020b57cec5SDimitry Andric
24030b57cec5SDimitry Andric /// Parse an umbrella directory declaration.
24040b57cec5SDimitry Andric ///
24050b57cec5SDimitry Andric /// umbrella-dir-declaration:
24060b57cec5SDimitry Andric /// umbrella string-literal
parseUmbrellaDirDecl(SourceLocation UmbrellaLoc)24070b57cec5SDimitry Andric void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) {
24080b57cec5SDimitry Andric // Parse the directory name.
24090b57cec5SDimitry Andric if (!Tok.is(MMToken::StringLiteral)) {
24100b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header)
24110b57cec5SDimitry Andric << "umbrella";
24120b57cec5SDimitry Andric HadError = true;
24130b57cec5SDimitry Andric return;
24140b57cec5SDimitry Andric }
24150b57cec5SDimitry Andric
24165ffd83dbSDimitry Andric std::string DirName = std::string(Tok.getString());
2417*5f7ddb14SDimitry Andric std::string DirNameAsWritten = DirName;
24180b57cec5SDimitry Andric SourceLocation DirNameLoc = consumeToken();
24190b57cec5SDimitry Andric
24200b57cec5SDimitry Andric // Check whether we already have an umbrella.
24210b57cec5SDimitry Andric if (ActiveModule->Umbrella) {
24220b57cec5SDimitry Andric Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash)
24230b57cec5SDimitry Andric << ActiveModule->getFullModuleName();
24240b57cec5SDimitry Andric HadError = true;
24250b57cec5SDimitry Andric return;
24260b57cec5SDimitry Andric }
24270b57cec5SDimitry Andric
24280b57cec5SDimitry Andric // Look for this file.
2429*5f7ddb14SDimitry Andric const DirectoryEntry *Dir = nullptr;
2430a7dea167SDimitry Andric if (llvm::sys::path::is_absolute(DirName)) {
2431*5f7ddb14SDimitry Andric if (auto D = SourceMgr.getFileManager().getDirectory(DirName))
2432a7dea167SDimitry Andric Dir = *D;
2433a7dea167SDimitry Andric } else {
24340b57cec5SDimitry Andric SmallString<128> PathName;
24350b57cec5SDimitry Andric PathName = Directory->getName();
24360b57cec5SDimitry Andric llvm::sys::path::append(PathName, DirName);
2437*5f7ddb14SDimitry Andric if (auto D = SourceMgr.getFileManager().getDirectory(PathName))
2438a7dea167SDimitry Andric Dir = *D;
24390b57cec5SDimitry Andric }
24400b57cec5SDimitry Andric
24410b57cec5SDimitry Andric if (!Dir) {
24420b57cec5SDimitry Andric Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found)
24430b57cec5SDimitry Andric << DirName;
24440b57cec5SDimitry Andric return;
24450b57cec5SDimitry Andric }
24460b57cec5SDimitry Andric
24470b57cec5SDimitry Andric if (UsesRequiresExcludedHack.count(ActiveModule)) {
24480b57cec5SDimitry Andric // Mark this header 'textual' (see doc comment for
24490b57cec5SDimitry Andric // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the
24500b57cec5SDimitry Andric // directory is relatively expensive, in practice this only applies to the
24510b57cec5SDimitry Andric // uncommonly used Tcl module on Darwin platforms.
24520b57cec5SDimitry Andric std::error_code EC;
24530b57cec5SDimitry Andric SmallVector<Module::Header, 6> Headers;
24540b57cec5SDimitry Andric llvm::vfs::FileSystem &FS =
24550b57cec5SDimitry Andric SourceMgr.getFileManager().getVirtualFileSystem();
24560b57cec5SDimitry Andric for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E;
24570b57cec5SDimitry Andric I != E && !EC; I.increment(EC)) {
2458*5f7ddb14SDimitry Andric if (auto FE = SourceMgr.getFileManager().getFile(I->path())) {
2459*5f7ddb14SDimitry Andric Module::Header Header = {"", std::string(I->path()), *FE};
24600b57cec5SDimitry Andric Headers.push_back(std::move(Header));
24610b57cec5SDimitry Andric }
24620b57cec5SDimitry Andric }
24630b57cec5SDimitry Andric
24640b57cec5SDimitry Andric // Sort header paths so that the pcm doesn't depend on iteration order.
24650b57cec5SDimitry Andric llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders);
24660b57cec5SDimitry Andric
24670b57cec5SDimitry Andric for (auto &Header : Headers)
24680b57cec5SDimitry Andric Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader);
24690b57cec5SDimitry Andric return;
24700b57cec5SDimitry Andric }
24710b57cec5SDimitry Andric
2472*5f7ddb14SDimitry Andric if (Module *OwningModule = Map.UmbrellaDirs[Dir]) {
24730b57cec5SDimitry Andric Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash)
24740b57cec5SDimitry Andric << OwningModule->getFullModuleName();
24750b57cec5SDimitry Andric HadError = true;
24760b57cec5SDimitry Andric return;
24770b57cec5SDimitry Andric }
24780b57cec5SDimitry Andric
24790b57cec5SDimitry Andric // Record this umbrella directory.
2480*5f7ddb14SDimitry Andric Map.setUmbrellaDir(ActiveModule, Dir, DirNameAsWritten, DirName);
24810b57cec5SDimitry Andric }
24820b57cec5SDimitry Andric
24830b57cec5SDimitry Andric /// Parse a module export declaration.
24840b57cec5SDimitry Andric ///
24850b57cec5SDimitry Andric /// export-declaration:
24860b57cec5SDimitry Andric /// 'export' wildcard-module-id
24870b57cec5SDimitry Andric ///
24880b57cec5SDimitry Andric /// wildcard-module-id:
24890b57cec5SDimitry Andric /// identifier
24900b57cec5SDimitry Andric /// '*'
24910b57cec5SDimitry Andric /// identifier '.' wildcard-module-id
parseExportDecl()24920b57cec5SDimitry Andric void ModuleMapParser::parseExportDecl() {
24930b57cec5SDimitry Andric assert(Tok.is(MMToken::ExportKeyword));
24940b57cec5SDimitry Andric SourceLocation ExportLoc = consumeToken();
24950b57cec5SDimitry Andric
24960b57cec5SDimitry Andric // Parse the module-id with an optional wildcard at the end.
24970b57cec5SDimitry Andric ModuleId ParsedModuleId;
24980b57cec5SDimitry Andric bool Wildcard = false;
24990b57cec5SDimitry Andric do {
25000b57cec5SDimitry Andric // FIXME: Support string-literal module names here.
25010b57cec5SDimitry Andric if (Tok.is(MMToken::Identifier)) {
25025ffd83dbSDimitry Andric ParsedModuleId.push_back(
25035ffd83dbSDimitry Andric std::make_pair(std::string(Tok.getString()), Tok.getLocation()));
25040b57cec5SDimitry Andric consumeToken();
25050b57cec5SDimitry Andric
25060b57cec5SDimitry Andric if (Tok.is(MMToken::Period)) {
25070b57cec5SDimitry Andric consumeToken();
25080b57cec5SDimitry Andric continue;
25090b57cec5SDimitry Andric }
25100b57cec5SDimitry Andric
25110b57cec5SDimitry Andric break;
25120b57cec5SDimitry Andric }
25130b57cec5SDimitry Andric
25140b57cec5SDimitry Andric if(Tok.is(MMToken::Star)) {
25150b57cec5SDimitry Andric Wildcard = true;
25160b57cec5SDimitry Andric consumeToken();
25170b57cec5SDimitry Andric break;
25180b57cec5SDimitry Andric }
25190b57cec5SDimitry Andric
25200b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
25210b57cec5SDimitry Andric HadError = true;
25220b57cec5SDimitry Andric return;
25230b57cec5SDimitry Andric } while (true);
25240b57cec5SDimitry Andric
25250b57cec5SDimitry Andric Module::UnresolvedExportDecl Unresolved = {
25260b57cec5SDimitry Andric ExportLoc, ParsedModuleId, Wildcard
25270b57cec5SDimitry Andric };
25280b57cec5SDimitry Andric ActiveModule->UnresolvedExports.push_back(Unresolved);
25290b57cec5SDimitry Andric }
25300b57cec5SDimitry Andric
25310b57cec5SDimitry Andric /// Parse a module export_as declaration.
25320b57cec5SDimitry Andric ///
25330b57cec5SDimitry Andric /// export-as-declaration:
25340b57cec5SDimitry Andric /// 'export_as' identifier
parseExportAsDecl()25350b57cec5SDimitry Andric void ModuleMapParser::parseExportAsDecl() {
25360b57cec5SDimitry Andric assert(Tok.is(MMToken::ExportAsKeyword));
25370b57cec5SDimitry Andric consumeToken();
25380b57cec5SDimitry Andric
25390b57cec5SDimitry Andric if (!Tok.is(MMToken::Identifier)) {
25400b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_module_id);
25410b57cec5SDimitry Andric HadError = true;
25420b57cec5SDimitry Andric return;
25430b57cec5SDimitry Andric }
25440b57cec5SDimitry Andric
25450b57cec5SDimitry Andric if (ActiveModule->Parent) {
25460b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as);
25470b57cec5SDimitry Andric consumeToken();
25480b57cec5SDimitry Andric return;
25490b57cec5SDimitry Andric }
25500b57cec5SDimitry Andric
25510b57cec5SDimitry Andric if (!ActiveModule->ExportAsModule.empty()) {
25520b57cec5SDimitry Andric if (ActiveModule->ExportAsModule == Tok.getString()) {
25530b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as)
25540b57cec5SDimitry Andric << ActiveModule->Name << Tok.getString();
25550b57cec5SDimitry Andric } else {
25560b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as)
25570b57cec5SDimitry Andric << ActiveModule->Name << ActiveModule->ExportAsModule
25580b57cec5SDimitry Andric << Tok.getString();
25590b57cec5SDimitry Andric }
25600b57cec5SDimitry Andric }
25610b57cec5SDimitry Andric
25625ffd83dbSDimitry Andric ActiveModule->ExportAsModule = std::string(Tok.getString());
25630b57cec5SDimitry Andric Map.addLinkAsDependency(ActiveModule);
25640b57cec5SDimitry Andric
25650b57cec5SDimitry Andric consumeToken();
25660b57cec5SDimitry Andric }
25670b57cec5SDimitry Andric
25680b57cec5SDimitry Andric /// Parse a module use declaration.
25690b57cec5SDimitry Andric ///
25700b57cec5SDimitry Andric /// use-declaration:
25710b57cec5SDimitry Andric /// 'use' wildcard-module-id
parseUseDecl()25720b57cec5SDimitry Andric void ModuleMapParser::parseUseDecl() {
25730b57cec5SDimitry Andric assert(Tok.is(MMToken::UseKeyword));
25740b57cec5SDimitry Andric auto KWLoc = consumeToken();
25750b57cec5SDimitry Andric // Parse the module-id.
25760b57cec5SDimitry Andric ModuleId ParsedModuleId;
25770b57cec5SDimitry Andric parseModuleId(ParsedModuleId);
25780b57cec5SDimitry Andric
25790b57cec5SDimitry Andric if (ActiveModule->Parent)
25800b57cec5SDimitry Andric Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule);
25810b57cec5SDimitry Andric else
25820b57cec5SDimitry Andric ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId);
25830b57cec5SDimitry Andric }
25840b57cec5SDimitry Andric
25850b57cec5SDimitry Andric /// Parse a link declaration.
25860b57cec5SDimitry Andric ///
25870b57cec5SDimitry Andric /// module-declaration:
25880b57cec5SDimitry Andric /// 'link' 'framework'[opt] string-literal
parseLinkDecl()25890b57cec5SDimitry Andric void ModuleMapParser::parseLinkDecl() {
25900b57cec5SDimitry Andric assert(Tok.is(MMToken::LinkKeyword));
25910b57cec5SDimitry Andric SourceLocation LinkLoc = consumeToken();
25920b57cec5SDimitry Andric
25930b57cec5SDimitry Andric // Parse the optional 'framework' keyword.
25940b57cec5SDimitry Andric bool IsFramework = false;
25950b57cec5SDimitry Andric if (Tok.is(MMToken::FrameworkKeyword)) {
25960b57cec5SDimitry Andric consumeToken();
25970b57cec5SDimitry Andric IsFramework = true;
25980b57cec5SDimitry Andric }
25990b57cec5SDimitry Andric
26000b57cec5SDimitry Andric // Parse the library name
26010b57cec5SDimitry Andric if (!Tok.is(MMToken::StringLiteral)) {
26020b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name)
26030b57cec5SDimitry Andric << IsFramework << SourceRange(LinkLoc);
26040b57cec5SDimitry Andric HadError = true;
26050b57cec5SDimitry Andric return;
26060b57cec5SDimitry Andric }
26070b57cec5SDimitry Andric
26085ffd83dbSDimitry Andric std::string LibraryName = std::string(Tok.getString());
26090b57cec5SDimitry Andric consumeToken();
26100b57cec5SDimitry Andric ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName,
26110b57cec5SDimitry Andric IsFramework));
26120b57cec5SDimitry Andric }
26130b57cec5SDimitry Andric
26140b57cec5SDimitry Andric /// Parse a configuration macro declaration.
26150b57cec5SDimitry Andric ///
26160b57cec5SDimitry Andric /// module-declaration:
26170b57cec5SDimitry Andric /// 'config_macros' attributes[opt] config-macro-list?
26180b57cec5SDimitry Andric ///
26190b57cec5SDimitry Andric /// config-macro-list:
26200b57cec5SDimitry Andric /// identifier (',' identifier)?
parseConfigMacros()26210b57cec5SDimitry Andric void ModuleMapParser::parseConfigMacros() {
26220b57cec5SDimitry Andric assert(Tok.is(MMToken::ConfigMacros));
26230b57cec5SDimitry Andric SourceLocation ConfigMacrosLoc = consumeToken();
26240b57cec5SDimitry Andric
26250b57cec5SDimitry Andric // Only top-level modules can have configuration macros.
26260b57cec5SDimitry Andric if (ActiveModule->Parent) {
26270b57cec5SDimitry Andric Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule);
26280b57cec5SDimitry Andric }
26290b57cec5SDimitry Andric
26300b57cec5SDimitry Andric // Parse the optional attributes.
26310b57cec5SDimitry Andric Attributes Attrs;
26320b57cec5SDimitry Andric if (parseOptionalAttributes(Attrs))
26330b57cec5SDimitry Andric return;
26340b57cec5SDimitry Andric
26350b57cec5SDimitry Andric if (Attrs.IsExhaustive && !ActiveModule->Parent) {
26360b57cec5SDimitry Andric ActiveModule->ConfigMacrosExhaustive = true;
26370b57cec5SDimitry Andric }
26380b57cec5SDimitry Andric
26390b57cec5SDimitry Andric // If we don't have an identifier, we're done.
26400b57cec5SDimitry Andric // FIXME: Support macros with the same name as a keyword here.
26410b57cec5SDimitry Andric if (!Tok.is(MMToken::Identifier))
26420b57cec5SDimitry Andric return;
26430b57cec5SDimitry Andric
26440b57cec5SDimitry Andric // Consume the first identifier.
26450b57cec5SDimitry Andric if (!ActiveModule->Parent) {
26460b57cec5SDimitry Andric ActiveModule->ConfigMacros.push_back(Tok.getString().str());
26470b57cec5SDimitry Andric }
26480b57cec5SDimitry Andric consumeToken();
26490b57cec5SDimitry Andric
26500b57cec5SDimitry Andric do {
26510b57cec5SDimitry Andric // If there's a comma, consume it.
26520b57cec5SDimitry Andric if (!Tok.is(MMToken::Comma))
26530b57cec5SDimitry Andric break;
26540b57cec5SDimitry Andric consumeToken();
26550b57cec5SDimitry Andric
26560b57cec5SDimitry Andric // We expect to see a macro name here.
26570b57cec5SDimitry Andric // FIXME: Support macros with the same name as a keyword here.
26580b57cec5SDimitry Andric if (!Tok.is(MMToken::Identifier)) {
26590b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro);
26600b57cec5SDimitry Andric break;
26610b57cec5SDimitry Andric }
26620b57cec5SDimitry Andric
26630b57cec5SDimitry Andric // Consume the macro name.
26640b57cec5SDimitry Andric if (!ActiveModule->Parent) {
26650b57cec5SDimitry Andric ActiveModule->ConfigMacros.push_back(Tok.getString().str());
26660b57cec5SDimitry Andric }
26670b57cec5SDimitry Andric consumeToken();
26680b57cec5SDimitry Andric } while (true);
26690b57cec5SDimitry Andric }
26700b57cec5SDimitry Andric
26710b57cec5SDimitry Andric /// Format a module-id into a string.
formatModuleId(const ModuleId & Id)26720b57cec5SDimitry Andric static std::string formatModuleId(const ModuleId &Id) {
26730b57cec5SDimitry Andric std::string result;
26740b57cec5SDimitry Andric {
26750b57cec5SDimitry Andric llvm::raw_string_ostream OS(result);
26760b57cec5SDimitry Andric
26770b57cec5SDimitry Andric for (unsigned I = 0, N = Id.size(); I != N; ++I) {
26780b57cec5SDimitry Andric if (I)
26790b57cec5SDimitry Andric OS << ".";
26800b57cec5SDimitry Andric OS << Id[I].first;
26810b57cec5SDimitry Andric }
26820b57cec5SDimitry Andric }
26830b57cec5SDimitry Andric
26840b57cec5SDimitry Andric return result;
26850b57cec5SDimitry Andric }
26860b57cec5SDimitry Andric
26870b57cec5SDimitry Andric /// Parse a conflict declaration.
26880b57cec5SDimitry Andric ///
26890b57cec5SDimitry Andric /// module-declaration:
26900b57cec5SDimitry Andric /// 'conflict' module-id ',' string-literal
parseConflict()26910b57cec5SDimitry Andric void ModuleMapParser::parseConflict() {
26920b57cec5SDimitry Andric assert(Tok.is(MMToken::Conflict));
26930b57cec5SDimitry Andric SourceLocation ConflictLoc = consumeToken();
26940b57cec5SDimitry Andric Module::UnresolvedConflict Conflict;
26950b57cec5SDimitry Andric
26960b57cec5SDimitry Andric // Parse the module-id.
26970b57cec5SDimitry Andric if (parseModuleId(Conflict.Id))
26980b57cec5SDimitry Andric return;
26990b57cec5SDimitry Andric
27000b57cec5SDimitry Andric // Parse the ','.
27010b57cec5SDimitry Andric if (!Tok.is(MMToken::Comma)) {
27020b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma)
27030b57cec5SDimitry Andric << SourceRange(ConflictLoc);
27040b57cec5SDimitry Andric return;
27050b57cec5SDimitry Andric }
27060b57cec5SDimitry Andric consumeToken();
27070b57cec5SDimitry Andric
27080b57cec5SDimitry Andric // Parse the message.
27090b57cec5SDimitry Andric if (!Tok.is(MMToken::StringLiteral)) {
27100b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message)
27110b57cec5SDimitry Andric << formatModuleId(Conflict.Id);
27120b57cec5SDimitry Andric return;
27130b57cec5SDimitry Andric }
27140b57cec5SDimitry Andric Conflict.Message = Tok.getString().str();
27150b57cec5SDimitry Andric consumeToken();
27160b57cec5SDimitry Andric
27170b57cec5SDimitry Andric // Add this unresolved conflict.
27180b57cec5SDimitry Andric ActiveModule->UnresolvedConflicts.push_back(Conflict);
27190b57cec5SDimitry Andric }
27200b57cec5SDimitry Andric
27210b57cec5SDimitry Andric /// Parse an inferred module declaration (wildcard modules).
27220b57cec5SDimitry Andric ///
27230b57cec5SDimitry Andric /// module-declaration:
27240b57cec5SDimitry Andric /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt]
27250b57cec5SDimitry Andric /// { inferred-module-member* }
27260b57cec5SDimitry Andric ///
27270b57cec5SDimitry Andric /// inferred-module-member:
27280b57cec5SDimitry Andric /// 'export' '*'
27290b57cec5SDimitry Andric /// 'exclude' identifier
parseInferredModuleDecl(bool Framework,bool Explicit)27300b57cec5SDimitry Andric void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) {
27310b57cec5SDimitry Andric assert(Tok.is(MMToken::Star));
27320b57cec5SDimitry Andric SourceLocation StarLoc = consumeToken();
27330b57cec5SDimitry Andric bool Failed = false;
27340b57cec5SDimitry Andric
27350b57cec5SDimitry Andric // Inferred modules must be submodules.
27360b57cec5SDimitry Andric if (!ActiveModule && !Framework) {
27370b57cec5SDimitry Andric Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule);
27380b57cec5SDimitry Andric Failed = true;
27390b57cec5SDimitry Andric }
27400b57cec5SDimitry Andric
27410b57cec5SDimitry Andric if (ActiveModule) {
27420b57cec5SDimitry Andric // Inferred modules must have umbrella directories.
27430b57cec5SDimitry Andric if (!Failed && ActiveModule->IsAvailable &&
27440b57cec5SDimitry Andric !ActiveModule->getUmbrellaDir()) {
27450b57cec5SDimitry Andric Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella);
27460b57cec5SDimitry Andric Failed = true;
27470b57cec5SDimitry Andric }
27480b57cec5SDimitry Andric
27490b57cec5SDimitry Andric // Check for redefinition of an inferred module.
27500b57cec5SDimitry Andric if (!Failed && ActiveModule->InferSubmodules) {
27510b57cec5SDimitry Andric Diags.Report(StarLoc, diag::err_mmap_inferred_redef);
27520b57cec5SDimitry Andric if (ActiveModule->InferredSubmoduleLoc.isValid())
27530b57cec5SDimitry Andric Diags.Report(ActiveModule->InferredSubmoduleLoc,
27540b57cec5SDimitry Andric diag::note_mmap_prev_definition);
27550b57cec5SDimitry Andric Failed = true;
27560b57cec5SDimitry Andric }
27570b57cec5SDimitry Andric
27580b57cec5SDimitry Andric // Check for the 'framework' keyword, which is not permitted here.
27590b57cec5SDimitry Andric if (Framework) {
27600b57cec5SDimitry Andric Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule);
27610b57cec5SDimitry Andric Framework = false;
27620b57cec5SDimitry Andric }
27630b57cec5SDimitry Andric } else if (Explicit) {
27640b57cec5SDimitry Andric Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework);
27650b57cec5SDimitry Andric Explicit = false;
27660b57cec5SDimitry Andric }
27670b57cec5SDimitry Andric
27680b57cec5SDimitry Andric // If there were any problems with this inferred submodule, skip its body.
27690b57cec5SDimitry Andric if (Failed) {
27700b57cec5SDimitry Andric if (Tok.is(MMToken::LBrace)) {
27710b57cec5SDimitry Andric consumeToken();
27720b57cec5SDimitry Andric skipUntil(MMToken::RBrace);
27730b57cec5SDimitry Andric if (Tok.is(MMToken::RBrace))
27740b57cec5SDimitry Andric consumeToken();
27750b57cec5SDimitry Andric }
27760b57cec5SDimitry Andric HadError = true;
27770b57cec5SDimitry Andric return;
27780b57cec5SDimitry Andric }
27790b57cec5SDimitry Andric
27800b57cec5SDimitry Andric // Parse optional attributes.
27810b57cec5SDimitry Andric Attributes Attrs;
27820b57cec5SDimitry Andric if (parseOptionalAttributes(Attrs))
27830b57cec5SDimitry Andric return;
27840b57cec5SDimitry Andric
27850b57cec5SDimitry Andric if (ActiveModule) {
27860b57cec5SDimitry Andric // Note that we have an inferred submodule.
27870b57cec5SDimitry Andric ActiveModule->InferSubmodules = true;
27880b57cec5SDimitry Andric ActiveModule->InferredSubmoduleLoc = StarLoc;
27890b57cec5SDimitry Andric ActiveModule->InferExplicitSubmodules = Explicit;
27900b57cec5SDimitry Andric } else {
27910b57cec5SDimitry Andric // We'll be inferring framework modules for this directory.
27920b57cec5SDimitry Andric Map.InferredDirectories[Directory].InferModules = true;
27930b57cec5SDimitry Andric Map.InferredDirectories[Directory].Attrs = Attrs;
27940b57cec5SDimitry Andric Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile;
27950b57cec5SDimitry Andric // FIXME: Handle the 'framework' keyword.
27960b57cec5SDimitry Andric }
27970b57cec5SDimitry Andric
27980b57cec5SDimitry Andric // Parse the opening brace.
27990b57cec5SDimitry Andric if (!Tok.is(MMToken::LBrace)) {
28000b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard);
28010b57cec5SDimitry Andric HadError = true;
28020b57cec5SDimitry Andric return;
28030b57cec5SDimitry Andric }
28040b57cec5SDimitry Andric SourceLocation LBraceLoc = consumeToken();
28050b57cec5SDimitry Andric
28060b57cec5SDimitry Andric // Parse the body of the inferred submodule.
28070b57cec5SDimitry Andric bool Done = false;
28080b57cec5SDimitry Andric do {
28090b57cec5SDimitry Andric switch (Tok.Kind) {
28100b57cec5SDimitry Andric case MMToken::EndOfFile:
28110b57cec5SDimitry Andric case MMToken::RBrace:
28120b57cec5SDimitry Andric Done = true;
28130b57cec5SDimitry Andric break;
28140b57cec5SDimitry Andric
28150b57cec5SDimitry Andric case MMToken::ExcludeKeyword:
28160b57cec5SDimitry Andric if (ActiveModule) {
28170b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
28180b57cec5SDimitry Andric << (ActiveModule != nullptr);
28190b57cec5SDimitry Andric consumeToken();
28200b57cec5SDimitry Andric break;
28210b57cec5SDimitry Andric }
28220b57cec5SDimitry Andric
28230b57cec5SDimitry Andric consumeToken();
28240b57cec5SDimitry Andric // FIXME: Support string-literal module names here.
28250b57cec5SDimitry Andric if (!Tok.is(MMToken::Identifier)) {
28260b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name);
28270b57cec5SDimitry Andric break;
28280b57cec5SDimitry Andric }
28290b57cec5SDimitry Andric
28305ffd83dbSDimitry Andric Map.InferredDirectories[Directory].ExcludedModules.push_back(
28315ffd83dbSDimitry Andric std::string(Tok.getString()));
28320b57cec5SDimitry Andric consumeToken();
28330b57cec5SDimitry Andric break;
28340b57cec5SDimitry Andric
28350b57cec5SDimitry Andric case MMToken::ExportKeyword:
28360b57cec5SDimitry Andric if (!ActiveModule) {
28370b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
28380b57cec5SDimitry Andric << (ActiveModule != nullptr);
28390b57cec5SDimitry Andric consumeToken();
28400b57cec5SDimitry Andric break;
28410b57cec5SDimitry Andric }
28420b57cec5SDimitry Andric
28430b57cec5SDimitry Andric consumeToken();
28440b57cec5SDimitry Andric if (Tok.is(MMToken::Star))
28450b57cec5SDimitry Andric ActiveModule->InferExportWildcard = true;
28460b57cec5SDimitry Andric else
28470b57cec5SDimitry Andric Diags.Report(Tok.getLocation(),
28480b57cec5SDimitry Andric diag::err_mmap_expected_export_wildcard);
28490b57cec5SDimitry Andric consumeToken();
28500b57cec5SDimitry Andric break;
28510b57cec5SDimitry Andric
28520b57cec5SDimitry Andric case MMToken::ExplicitKeyword:
28530b57cec5SDimitry Andric case MMToken::ModuleKeyword:
28540b57cec5SDimitry Andric case MMToken::HeaderKeyword:
28550b57cec5SDimitry Andric case MMToken::PrivateKeyword:
28560b57cec5SDimitry Andric case MMToken::UmbrellaKeyword:
28570b57cec5SDimitry Andric default:
28580b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member)
28590b57cec5SDimitry Andric << (ActiveModule != nullptr);
28600b57cec5SDimitry Andric consumeToken();
28610b57cec5SDimitry Andric break;
28620b57cec5SDimitry Andric }
28630b57cec5SDimitry Andric } while (!Done);
28640b57cec5SDimitry Andric
28650b57cec5SDimitry Andric if (Tok.is(MMToken::RBrace))
28660b57cec5SDimitry Andric consumeToken();
28670b57cec5SDimitry Andric else {
28680b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace);
28690b57cec5SDimitry Andric Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match);
28700b57cec5SDimitry Andric HadError = true;
28710b57cec5SDimitry Andric }
28720b57cec5SDimitry Andric }
28730b57cec5SDimitry Andric
28740b57cec5SDimitry Andric /// Parse optional attributes.
28750b57cec5SDimitry Andric ///
28760b57cec5SDimitry Andric /// attributes:
28770b57cec5SDimitry Andric /// attribute attributes
28780b57cec5SDimitry Andric /// attribute
28790b57cec5SDimitry Andric ///
28800b57cec5SDimitry Andric /// attribute:
28810b57cec5SDimitry Andric /// [ identifier ]
28820b57cec5SDimitry Andric ///
28830b57cec5SDimitry Andric /// \param Attrs Will be filled in with the parsed attributes.
28840b57cec5SDimitry Andric ///
28850b57cec5SDimitry Andric /// \returns true if an error occurred, false otherwise.
parseOptionalAttributes(Attributes & Attrs)28860b57cec5SDimitry Andric bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) {
28870b57cec5SDimitry Andric bool HadError = false;
28880b57cec5SDimitry Andric
28890b57cec5SDimitry Andric while (Tok.is(MMToken::LSquare)) {
28900b57cec5SDimitry Andric // Consume the '['.
28910b57cec5SDimitry Andric SourceLocation LSquareLoc = consumeToken();
28920b57cec5SDimitry Andric
28930b57cec5SDimitry Andric // Check whether we have an attribute name here.
28940b57cec5SDimitry Andric if (!Tok.is(MMToken::Identifier)) {
28950b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute);
28960b57cec5SDimitry Andric skipUntil(MMToken::RSquare);
28970b57cec5SDimitry Andric if (Tok.is(MMToken::RSquare))
28980b57cec5SDimitry Andric consumeToken();
28990b57cec5SDimitry Andric HadError = true;
29000b57cec5SDimitry Andric }
29010b57cec5SDimitry Andric
29020b57cec5SDimitry Andric // Decode the attribute name.
29030b57cec5SDimitry Andric AttributeKind Attribute
29040b57cec5SDimitry Andric = llvm::StringSwitch<AttributeKind>(Tok.getString())
29050b57cec5SDimitry Andric .Case("exhaustive", AT_exhaustive)
29060b57cec5SDimitry Andric .Case("extern_c", AT_extern_c)
29070b57cec5SDimitry Andric .Case("no_undeclared_includes", AT_no_undeclared_includes)
29080b57cec5SDimitry Andric .Case("system", AT_system)
29090b57cec5SDimitry Andric .Default(AT_unknown);
29100b57cec5SDimitry Andric switch (Attribute) {
29110b57cec5SDimitry Andric case AT_unknown:
29120b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute)
29130b57cec5SDimitry Andric << Tok.getString();
29140b57cec5SDimitry Andric break;
29150b57cec5SDimitry Andric
29160b57cec5SDimitry Andric case AT_system:
29170b57cec5SDimitry Andric Attrs.IsSystem = true;
29180b57cec5SDimitry Andric break;
29190b57cec5SDimitry Andric
29200b57cec5SDimitry Andric case AT_extern_c:
29210b57cec5SDimitry Andric Attrs.IsExternC = true;
29220b57cec5SDimitry Andric break;
29230b57cec5SDimitry Andric
29240b57cec5SDimitry Andric case AT_exhaustive:
29250b57cec5SDimitry Andric Attrs.IsExhaustive = true;
29260b57cec5SDimitry Andric break;
29270b57cec5SDimitry Andric
29280b57cec5SDimitry Andric case AT_no_undeclared_includes:
29290b57cec5SDimitry Andric Attrs.NoUndeclaredIncludes = true;
29300b57cec5SDimitry Andric break;
29310b57cec5SDimitry Andric }
29320b57cec5SDimitry Andric consumeToken();
29330b57cec5SDimitry Andric
29340b57cec5SDimitry Andric // Consume the ']'.
29350b57cec5SDimitry Andric if (!Tok.is(MMToken::RSquare)) {
29360b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare);
29370b57cec5SDimitry Andric Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match);
29380b57cec5SDimitry Andric skipUntil(MMToken::RSquare);
29390b57cec5SDimitry Andric HadError = true;
29400b57cec5SDimitry Andric }
29410b57cec5SDimitry Andric
29420b57cec5SDimitry Andric if (Tok.is(MMToken::RSquare))
29430b57cec5SDimitry Andric consumeToken();
29440b57cec5SDimitry Andric }
29450b57cec5SDimitry Andric
29460b57cec5SDimitry Andric return HadError;
29470b57cec5SDimitry Andric }
29480b57cec5SDimitry Andric
29490b57cec5SDimitry Andric /// Parse a module map file.
29500b57cec5SDimitry Andric ///
29510b57cec5SDimitry Andric /// module-map-file:
29520b57cec5SDimitry Andric /// module-declaration*
parseModuleMapFile()29530b57cec5SDimitry Andric bool ModuleMapParser::parseModuleMapFile() {
29540b57cec5SDimitry Andric do {
29550b57cec5SDimitry Andric switch (Tok.Kind) {
29560b57cec5SDimitry Andric case MMToken::EndOfFile:
29570b57cec5SDimitry Andric return HadError;
29580b57cec5SDimitry Andric
29590b57cec5SDimitry Andric case MMToken::ExplicitKeyword:
29600b57cec5SDimitry Andric case MMToken::ExternKeyword:
29610b57cec5SDimitry Andric case MMToken::ModuleKeyword:
29620b57cec5SDimitry Andric case MMToken::FrameworkKeyword:
29630b57cec5SDimitry Andric parseModuleDecl();
29640b57cec5SDimitry Andric break;
29650b57cec5SDimitry Andric
29660b57cec5SDimitry Andric case MMToken::Comma:
29670b57cec5SDimitry Andric case MMToken::ConfigMacros:
29680b57cec5SDimitry Andric case MMToken::Conflict:
29690b57cec5SDimitry Andric case MMToken::Exclaim:
29700b57cec5SDimitry Andric case MMToken::ExcludeKeyword:
29710b57cec5SDimitry Andric case MMToken::ExportKeyword:
29720b57cec5SDimitry Andric case MMToken::ExportAsKeyword:
29730b57cec5SDimitry Andric case MMToken::HeaderKeyword:
29740b57cec5SDimitry Andric case MMToken::Identifier:
29750b57cec5SDimitry Andric case MMToken::LBrace:
29760b57cec5SDimitry Andric case MMToken::LinkKeyword:
29770b57cec5SDimitry Andric case MMToken::LSquare:
29780b57cec5SDimitry Andric case MMToken::Period:
29790b57cec5SDimitry Andric case MMToken::PrivateKeyword:
29800b57cec5SDimitry Andric case MMToken::RBrace:
29810b57cec5SDimitry Andric case MMToken::RSquare:
29820b57cec5SDimitry Andric case MMToken::RequiresKeyword:
29830b57cec5SDimitry Andric case MMToken::Star:
29840b57cec5SDimitry Andric case MMToken::StringLiteral:
29850b57cec5SDimitry Andric case MMToken::IntegerLiteral:
29860b57cec5SDimitry Andric case MMToken::TextualKeyword:
29870b57cec5SDimitry Andric case MMToken::UmbrellaKeyword:
29880b57cec5SDimitry Andric case MMToken::UseKeyword:
29890b57cec5SDimitry Andric Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module);
29900b57cec5SDimitry Andric HadError = true;
29910b57cec5SDimitry Andric consumeToken();
29920b57cec5SDimitry Andric break;
29930b57cec5SDimitry Andric }
29940b57cec5SDimitry Andric } while (true);
29950b57cec5SDimitry Andric }
29960b57cec5SDimitry Andric
parseModuleMapFile(const FileEntry * File,bool IsSystem,const DirectoryEntry * Dir,FileID ID,unsigned * Offset,SourceLocation ExternModuleLoc)29970b57cec5SDimitry Andric bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem,
29980b57cec5SDimitry Andric const DirectoryEntry *Dir, FileID ID,
29990b57cec5SDimitry Andric unsigned *Offset,
30000b57cec5SDimitry Andric SourceLocation ExternModuleLoc) {
30010b57cec5SDimitry Andric assert(Target && "Missing target information");
30020b57cec5SDimitry Andric llvm::DenseMap<const FileEntry *, bool>::iterator Known
30030b57cec5SDimitry Andric = ParsedModuleMap.find(File);
30040b57cec5SDimitry Andric if (Known != ParsedModuleMap.end())
30050b57cec5SDimitry Andric return Known->second;
30060b57cec5SDimitry Andric
30070b57cec5SDimitry Andric // If the module map file wasn't already entered, do so now.
30080b57cec5SDimitry Andric if (ID.isInvalid()) {
30090b57cec5SDimitry Andric auto FileCharacter =
30100b57cec5SDimitry Andric IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap;
30110b57cec5SDimitry Andric ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter);
30120b57cec5SDimitry Andric }
30130b57cec5SDimitry Andric
30140b57cec5SDimitry Andric assert(Target && "Missing target information");
3015af732203SDimitry Andric llvm::Optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID);
30160b57cec5SDimitry Andric if (!Buffer)
30170b57cec5SDimitry Andric return ParsedModuleMap[File] = true;
30180b57cec5SDimitry Andric assert((!Offset || *Offset <= Buffer->getBufferSize()) &&
30190b57cec5SDimitry Andric "invalid buffer offset");
30200b57cec5SDimitry Andric
30210b57cec5SDimitry Andric // Parse this module map file.
30220b57cec5SDimitry Andric Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts,
30230b57cec5SDimitry Andric Buffer->getBufferStart(),
30240b57cec5SDimitry Andric Buffer->getBufferStart() + (Offset ? *Offset : 0),
30250b57cec5SDimitry Andric Buffer->getBufferEnd());
30260b57cec5SDimitry Andric SourceLocation Start = L.getSourceLocation();
30270b57cec5SDimitry Andric ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir,
30280b57cec5SDimitry Andric IsSystem);
30290b57cec5SDimitry Andric bool Result = Parser.parseModuleMapFile();
30300b57cec5SDimitry Andric ParsedModuleMap[File] = Result;
30310b57cec5SDimitry Andric
30320b57cec5SDimitry Andric if (Offset) {
30330b57cec5SDimitry Andric auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation());
30340b57cec5SDimitry Andric assert(Loc.first == ID && "stopped in a different file?");
30350b57cec5SDimitry Andric *Offset = Loc.second;
30360b57cec5SDimitry Andric }
30370b57cec5SDimitry Andric
30380b57cec5SDimitry Andric // Notify callbacks that we parsed it.
30390b57cec5SDimitry Andric for (const auto &Cb : Callbacks)
30400b57cec5SDimitry Andric Cb->moduleMapFileRead(Start, *File, IsSystem);
30410b57cec5SDimitry Andric
30420b57cec5SDimitry Andric return Result;
30430b57cec5SDimitry Andric }
3044