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