1afd1b1c9SEugene Zelenko //===- ModuleMap.cpp - Describe the layout of modules ---------------------===// 2718292f2SDouglas Gregor // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6718292f2SDouglas Gregor // 7718292f2SDouglas Gregor //===----------------------------------------------------------------------===// 8718292f2SDouglas Gregor // 9718292f2SDouglas Gregor // This file defines the ModuleMap implementation, which describes the layout 10718292f2SDouglas Gregor // of a module as it relates to headers. 11718292f2SDouglas Gregor // 12718292f2SDouglas Gregor //===----------------------------------------------------------------------===// 13afd1b1c9SEugene Zelenko 14718292f2SDouglas Gregor #include "clang/Lex/ModuleMap.h" 15a7d03840SJordan Rose #include "clang/Basic/CharInfo.h" 16718292f2SDouglas Gregor #include "clang/Basic/Diagnostic.h" 17718292f2SDouglas Gregor #include "clang/Basic/FileManager.h" 18afd1b1c9SEugene Zelenko #include "clang/Basic/LLVM.h" 19afd1b1c9SEugene Zelenko #include "clang/Basic/LangOptions.h" 20afd1b1c9SEugene Zelenko #include "clang/Basic/Module.h" 21afd1b1c9SEugene Zelenko #include "clang/Basic/SourceLocation.h" 22afd1b1c9SEugene Zelenko #include "clang/Basic/SourceManager.h" 23718292f2SDouglas Gregor #include "clang/Basic/TargetInfo.h" 24b146baabSArgyrios Kyrtzidis #include "clang/Lex/HeaderSearch.h" 259acb99e3SRichard Smith #include "clang/Lex/HeaderSearchOptions.h" 263a02247dSChandler Carruth #include "clang/Lex/LexDiagnostic.h" 273a02247dSChandler Carruth #include "clang/Lex/Lexer.h" 283a02247dSChandler Carruth #include "clang/Lex/LiteralSupport.h" 29afd1b1c9SEugene Zelenko #include "clang/Lex/Token.h" 30afd1b1c9SEugene Zelenko #include "llvm/ADT/DenseMap.h" 31afd1b1c9SEugene Zelenko #include "llvm/ADT/None.h" 32afd1b1c9SEugene Zelenko #include "llvm/ADT/STLExtras.h" 33afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallPtrSet.h" 34afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallString.h" 35afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallVector.h" 36afd1b1c9SEugene Zelenko #include "llvm/ADT/StringMap.h" 373a02247dSChandler Carruth #include "llvm/ADT/StringRef.h" 383a02247dSChandler Carruth #include "llvm/ADT/StringSwitch.h" 39718292f2SDouglas Gregor #include "llvm/Support/Allocator.h" 40afd1b1c9SEugene Zelenko #include "llvm/Support/Compiler.h" 41afd1b1c9SEugene Zelenko #include "llvm/Support/ErrorHandling.h" 42afd1b1c9SEugene Zelenko #include "llvm/Support/MemoryBuffer.h" 43552c169eSRafael Espindola #include "llvm/Support/Path.h" 44fc51490bSJonas Devlieghere #include "llvm/Support/VirtualFileSystem.h" 45718292f2SDouglas Gregor #include "llvm/Support/raw_ostream.h" 46afd1b1c9SEugene Zelenko #include <algorithm> 47afd1b1c9SEugene Zelenko #include <cassert> 48afd1b1c9SEugene Zelenko #include <cstdint> 49afd1b1c9SEugene Zelenko #include <cstring> 50afd1b1c9SEugene Zelenko #include <string> 51afd1b1c9SEugene Zelenko #include <system_error> 52afd1b1c9SEugene Zelenko #include <utility> 53afd1b1c9SEugene Zelenko 54718292f2SDouglas Gregor using namespace clang; 55718292f2SDouglas Gregor 56b3e902f4SRichard Trieu void ModuleMapCallbacks::anchor() {} 57b3e902f4SRichard Trieu 58a3b5f71eSBruno Cardoso Lopes void ModuleMap::resolveLinkAsDependencies(Module *Mod) { 59a3b5f71eSBruno Cardoso Lopes auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name); 60a3b5f71eSBruno Cardoso Lopes if (PendingLinkAs != PendingLinkAsModule.end()) { 61a3b5f71eSBruno Cardoso Lopes for (auto &Name : PendingLinkAs->second) { 62a3b5f71eSBruno Cardoso Lopes auto *M = findModule(Name.getKey()); 63a3b5f71eSBruno Cardoso Lopes if (M) 64a3b5f71eSBruno Cardoso Lopes M->UseExportAsModuleLinkName = true; 65a3b5f71eSBruno Cardoso Lopes } 66a3b5f71eSBruno Cardoso Lopes } 67a3b5f71eSBruno Cardoso Lopes } 68a3b5f71eSBruno Cardoso Lopes 69a3b5f71eSBruno Cardoso Lopes void ModuleMap::addLinkAsDependency(Module *Mod) { 70a3b5f71eSBruno Cardoso Lopes if (findModule(Mod->ExportAsModule)) 71a3b5f71eSBruno Cardoso Lopes Mod->UseExportAsModuleLinkName = true; 72a3b5f71eSBruno Cardoso Lopes else 73a3b5f71eSBruno Cardoso Lopes PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name); 74a3b5f71eSBruno Cardoso Lopes } 75a3b5f71eSBruno Cardoso Lopes 76040e1266SRichard Smith Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) { 77040e1266SRichard Smith switch ((int)Role) { 78040e1266SRichard Smith default: llvm_unreachable("unknown header role"); 79040e1266SRichard Smith case NormalHeader: 80040e1266SRichard Smith return Module::HK_Normal; 81040e1266SRichard Smith case PrivateHeader: 82040e1266SRichard Smith return Module::HK_Private; 83040e1266SRichard Smith case TextualHeader: 84040e1266SRichard Smith return Module::HK_Textual; 85040e1266SRichard Smith case PrivateHeader | TextualHeader: 86040e1266SRichard Smith return Module::HK_PrivateTextual; 87040e1266SRichard Smith } 88040e1266SRichard Smith } 89040e1266SRichard Smith 90040e1266SRichard Smith ModuleMap::ModuleHeaderRole 91040e1266SRichard Smith ModuleMap::headerKindToRole(Module::HeaderKind Kind) { 92040e1266SRichard Smith switch ((int)Kind) { 93040e1266SRichard Smith case Module::HK_Normal: 94040e1266SRichard Smith return NormalHeader; 95040e1266SRichard Smith case Module::HK_Private: 96040e1266SRichard Smith return PrivateHeader; 97040e1266SRichard Smith case Module::HK_Textual: 98040e1266SRichard Smith return TextualHeader; 99040e1266SRichard Smith case Module::HK_PrivateTextual: 100040e1266SRichard Smith return ModuleHeaderRole(PrivateHeader | TextualHeader); 101040e1266SRichard Smith case Module::HK_Excluded: 102040e1266SRichard Smith llvm_unreachable("unexpected header kind"); 103040e1266SRichard Smith } 104040e1266SRichard Smith llvm_unreachable("unknown header kind"); 105040e1266SRichard Smith } 106040e1266SRichard Smith 1072b82c2a5SDouglas Gregor Module::ExportDecl 1082b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod, 1092b82c2a5SDouglas Gregor const Module::UnresolvedExportDecl &Unresolved, 110e4412640SArgyrios Kyrtzidis bool Complain) const { 111f5eedd05SDouglas Gregor // We may have just a wildcard. 112f5eedd05SDouglas Gregor if (Unresolved.Id.empty()) { 113f5eedd05SDouglas Gregor assert(Unresolved.Wildcard && "Invalid unresolved export"); 114d2d442caSCraig Topper return Module::ExportDecl(nullptr, true); 115f5eedd05SDouglas Gregor } 116f5eedd05SDouglas Gregor 117fb912657SDouglas Gregor // Resolve the module-id. 118fb912657SDouglas Gregor Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain); 119fb912657SDouglas Gregor if (!Context) 120afd1b1c9SEugene Zelenko return {}; 121fb912657SDouglas Gregor 122fb912657SDouglas Gregor return Module::ExportDecl(Context, Unresolved.Wildcard); 123fb912657SDouglas Gregor } 124fb912657SDouglas Gregor 125fb912657SDouglas Gregor Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod, 126fb912657SDouglas Gregor bool Complain) const { 1272b82c2a5SDouglas Gregor // Find the starting module. 128fb912657SDouglas Gregor Module *Context = lookupModuleUnqualified(Id[0].first, Mod); 1292b82c2a5SDouglas Gregor if (!Context) { 1302b82c2a5SDouglas Gregor if (Complain) 1310761a8a0SDaniel Jasper Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified) 132fb912657SDouglas Gregor << Id[0].first << Mod->getFullModuleName(); 1332b82c2a5SDouglas Gregor 134d2d442caSCraig Topper return nullptr; 1352b82c2a5SDouglas Gregor } 1362b82c2a5SDouglas Gregor 1372b82c2a5SDouglas Gregor // Dig into the module path. 138fb912657SDouglas Gregor for (unsigned I = 1, N = Id.size(); I != N; ++I) { 139fb912657SDouglas Gregor Module *Sub = lookupModuleQualified(Id[I].first, Context); 1402b82c2a5SDouglas Gregor if (!Sub) { 1412b82c2a5SDouglas Gregor if (Complain) 1420761a8a0SDaniel Jasper Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified) 143fb912657SDouglas Gregor << Id[I].first << Context->getFullModuleName() 144fb912657SDouglas Gregor << SourceRange(Id[0].second, Id[I-1].second); 1452b82c2a5SDouglas Gregor 146d2d442caSCraig Topper return nullptr; 1472b82c2a5SDouglas Gregor } 1482b82c2a5SDouglas Gregor 1492b82c2a5SDouglas Gregor Context = Sub; 1502b82c2a5SDouglas Gregor } 1512b82c2a5SDouglas Gregor 152fb912657SDouglas Gregor return Context; 1532b82c2a5SDouglas Gregor } 1542b82c2a5SDouglas Gregor 1559fc8faf9SAdrian Prantl /// Append to \p Paths the set of paths needed to get to the 1561d60987fSRichard Smith /// subframework in which the given module lives. 1571d60987fSRichard Smith static void appendSubframeworkPaths(Module *Mod, 1581d60987fSRichard Smith SmallVectorImpl<char> &Path) { 1591d60987fSRichard Smith // Collect the framework names from the given module to the top-level module. 1601d60987fSRichard Smith SmallVector<StringRef, 2> Paths; 1611d60987fSRichard Smith for (; Mod; Mod = Mod->Parent) { 1621d60987fSRichard Smith if (Mod->IsFramework) 1631d60987fSRichard Smith Paths.push_back(Mod->Name); 1641d60987fSRichard Smith } 1651d60987fSRichard Smith 1661d60987fSRichard Smith if (Paths.empty()) 1671d60987fSRichard Smith return; 1681d60987fSRichard Smith 1691d60987fSRichard Smith // Add Frameworks/Name.framework for each subframework. 1708adb6d6dSBenjamin Kramer for (StringRef Framework : llvm::drop_begin(llvm::reverse(Paths))) 1718adb6d6dSBenjamin Kramer llvm::sys::path::append(Path, "Frameworks", Framework + ".framework"); 1721d60987fSRichard Smith } 1731d60987fSRichard Smith 174f85db7f7SDuncan P. N. Exon Smith Optional<FileEntryRef> ModuleMap::findHeader( 1759f6020bcSBruno Cardoso Lopes Module *M, const Module::UnresolvedHeaderDirective &Header, 1769f6020bcSBruno Cardoso Lopes SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) { 1779f6020bcSBruno Cardoso Lopes // Search for the header file within the module's home directory. 1789f6020bcSBruno Cardoso Lopes auto *Directory = M->Directory; 1799f6020bcSBruno Cardoso Lopes SmallString<128> FullPathName(Directory->getName()); 1809f6020bcSBruno Cardoso Lopes 181f85db7f7SDuncan P. N. Exon Smith auto GetFile = [&](StringRef Filename) -> Optional<FileEntryRef> { 182f85db7f7SDuncan P. N. Exon Smith auto File = 183f85db7f7SDuncan P. N. Exon Smith expectedToOptional(SourceMgr.getFileManager().getFileRef(Filename)); 184f85db7f7SDuncan P. N. Exon Smith if (!File || (Header.Size && File->getSize() != *Header.Size) || 185f85db7f7SDuncan P. N. Exon Smith (Header.ModTime && File->getModificationTime() != *Header.ModTime)) 186f85db7f7SDuncan P. N. Exon Smith return None; 1878d323d15SHarlan Haskins return *File; 188040e1266SRichard Smith }; 189040e1266SRichard Smith 190f85db7f7SDuncan P. N. Exon Smith auto GetFrameworkFile = [&]() -> Optional<FileEntryRef> { 1911d60987fSRichard Smith unsigned FullPathLength = FullPathName.size(); 1921d60987fSRichard Smith appendSubframeworkPaths(M, RelativePathName); 1931d60987fSRichard Smith unsigned RelativePathLength = RelativePathName.size(); 1941d60987fSRichard Smith 1951d60987fSRichard Smith // Check whether this file is in the public headers. 1961d60987fSRichard Smith llvm::sys::path::append(RelativePathName, "Headers", Header.FileName); 1971d60987fSRichard Smith llvm::sys::path::append(FullPathName, RelativePathName); 198f85db7f7SDuncan P. N. Exon Smith if (auto File = GetFile(FullPathName)) 1991d60987fSRichard Smith return File; 2001d60987fSRichard Smith 2011d60987fSRichard Smith // Check whether this file is in the private headers. 2021d60987fSRichard Smith // Ideally, private modules in the form 'FrameworkName.Private' should 2031d60987fSRichard Smith // be defined as 'module FrameworkName.Private', and not as 2041d60987fSRichard Smith // 'framework module FrameworkName.Private', since a 'Private.Framework' 2051d60987fSRichard Smith // does not usually exist. However, since both are currently widely used 2061d60987fSRichard Smith // for private modules, make sure we find the right path in both cases. 2071d60987fSRichard Smith if (M->IsFramework && M->Name == "Private") 2081d60987fSRichard Smith RelativePathName.clear(); 2091d60987fSRichard Smith else 2101d60987fSRichard Smith RelativePathName.resize(RelativePathLength); 2111d60987fSRichard Smith FullPathName.resize(FullPathLength); 2121d60987fSRichard Smith llvm::sys::path::append(RelativePathName, "PrivateHeaders", 2131d60987fSRichard Smith Header.FileName); 2141d60987fSRichard Smith llvm::sys::path::append(FullPathName, RelativePathName); 215040e1266SRichard Smith return GetFile(FullPathName); 2169f6020bcSBruno Cardoso Lopes }; 2179f6020bcSBruno Cardoso Lopes 2189f6020bcSBruno Cardoso Lopes if (llvm::sys::path::is_absolute(Header.FileName)) { 2199f6020bcSBruno Cardoso Lopes RelativePathName.clear(); 2209f6020bcSBruno Cardoso Lopes RelativePathName.append(Header.FileName.begin(), Header.FileName.end()); 2219f6020bcSBruno Cardoso Lopes return GetFile(Header.FileName); 2221d60987fSRichard Smith } 2231d60987fSRichard Smith 2249f6020bcSBruno Cardoso Lopes if (M->isPartOfFramework()) 2259f6020bcSBruno Cardoso Lopes return GetFrameworkFile(); 2269f6020bcSBruno Cardoso Lopes 2271d60987fSRichard Smith // Lookup for normal headers. 2281d60987fSRichard Smith llvm::sys::path::append(RelativePathName, Header.FileName); 2291d60987fSRichard Smith llvm::sys::path::append(FullPathName, RelativePathName); 230f85db7f7SDuncan P. N. Exon Smith auto NormalHdrFile = GetFile(FullPathName); 2319f6020bcSBruno Cardoso Lopes 2320b4c2ee3SSimon Pilgrim if (!NormalHdrFile && Directory->getName().endswith(".framework")) { 2339f6020bcSBruno Cardoso Lopes // The lack of 'framework' keyword in a module declaration it's a simple 2349f6020bcSBruno Cardoso Lopes // mistake we can diagnose when the header exists within the proper 2359f6020bcSBruno Cardoso Lopes // framework style path. 2369f6020bcSBruno Cardoso Lopes FullPathName.assign(Directory->getName()); 2379f6020bcSBruno Cardoso Lopes RelativePathName.clear(); 238d101b5d7SErich Keane if (GetFrameworkFile()) { 2399f6020bcSBruno Cardoso Lopes Diags.Report(Header.FileNameLoc, 2409f6020bcSBruno Cardoso Lopes diag::warn_mmap_incomplete_framework_module_declaration) 2419f6020bcSBruno Cardoso Lopes << Header.FileName << M->getFullModuleName(); 2429f6020bcSBruno Cardoso Lopes NeedsFramework = true; 2439f6020bcSBruno Cardoso Lopes } 244f85db7f7SDuncan P. N. Exon Smith return None; 2459f6020bcSBruno Cardoso Lopes } 2469f6020bcSBruno Cardoso Lopes 2479f6020bcSBruno Cardoso Lopes return NormalHdrFile; 2481d60987fSRichard Smith } 2491d60987fSRichard Smith 250040e1266SRichard Smith void ModuleMap::resolveHeader(Module *Mod, 2519f6020bcSBruno Cardoso Lopes const Module::UnresolvedHeaderDirective &Header, 2529f6020bcSBruno Cardoso Lopes bool &NeedsFramework) { 253040e1266SRichard Smith SmallString<128> RelativePathName; 254f85db7f7SDuncan P. N. Exon Smith if (Optional<FileEntryRef> File = 2559f6020bcSBruno Cardoso Lopes findHeader(Mod, Header, RelativePathName, NeedsFramework)) { 256040e1266SRichard Smith if (Header.IsUmbrella) { 257f85db7f7SDuncan P. N. Exon Smith const DirectoryEntry *UmbrellaDir = &File->getDir().getDirEntry(); 258040e1266SRichard Smith if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir]) 259040e1266SRichard Smith Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) 260040e1266SRichard Smith << UmbrellaMod->getFullModuleName(); 261040e1266SRichard Smith else 262040e1266SRichard Smith // Record this umbrella header. 263d3676d4bSMichael Spencer setUmbrellaHeader(Mod, *File, Header.FileName, RelativePathName.str()); 264040e1266SRichard Smith } else { 265d3676d4bSMichael Spencer Module::Header H = {Header.FileName, std::string(RelativePathName.str()), 266d3676d4bSMichael Spencer *File}; 267040e1266SRichard Smith if (Header.Kind == Module::HK_Excluded) 268040e1266SRichard Smith excludeHeader(Mod, H); 269040e1266SRichard Smith else 270040e1266SRichard Smith addHeader(Mod, H, headerKindToRole(Header.Kind)); 271040e1266SRichard Smith } 272040e1266SRichard Smith } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) { 273040e1266SRichard Smith // There's a builtin header but no corresponding on-disk header. Assume 274040e1266SRichard Smith // this was supposed to modularize the builtin header alone. 275040e1266SRichard Smith } else if (Header.Kind == Module::HK_Excluded) { 276040e1266SRichard Smith // Ignore missing excluded header files. They're optional anyway. 277040e1266SRichard Smith } else { 278040e1266SRichard Smith // If we find a module that has a missing header, we mark this module as 279040e1266SRichard Smith // unavailable and store the header directive for displaying diagnostics. 280040e1266SRichard Smith Mod->MissingHeaders.push_back(Header); 281040e1266SRichard Smith // A missing header with stat information doesn't make the module 282040e1266SRichard Smith // unavailable; this keeps our behavior consistent as headers are lazily 283040e1266SRichard Smith // resolved. (Such a module still can't be built though, except from 284040e1266SRichard Smith // preprocessed source.) 285040e1266SRichard Smith if (!Header.Size && !Header.ModTime) 286fc76b4adSRichard Smith Mod->markUnavailable(/*Unimportable=*/false); 287040e1266SRichard Smith } 288040e1266SRichard Smith } 289040e1266SRichard Smith 290040e1266SRichard Smith bool ModuleMap::resolveAsBuiltinHeader( 291040e1266SRichard Smith Module *Mod, const Module::UnresolvedHeaderDirective &Header) { 292040e1266SRichard Smith if (Header.Kind == Module::HK_Excluded || 293040e1266SRichard Smith llvm::sys::path::is_absolute(Header.FileName) || 294040e1266SRichard Smith Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella || 295040e1266SRichard Smith !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory || 296040e1266SRichard Smith !isBuiltinHeader(Header.FileName)) 297040e1266SRichard Smith return false; 2981d60987fSRichard Smith 2991d60987fSRichard Smith // This is a system module with a top-level header. This header 3001d60987fSRichard Smith // may have a counterpart (or replacement) in the set of headers 3011d60987fSRichard Smith // supplied by Clang. Find that builtin header. 302040e1266SRichard Smith SmallString<128> Path; 303040e1266SRichard Smith llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName); 30464d8c781SDuncan P. N. Exon Smith auto File = SourceMgr.getFileManager().getFile(Path); 305040e1266SRichard Smith if (!File) 306040e1266SRichard Smith return false; 307040e1266SRichard Smith 308040e1266SRichard Smith auto Role = headerKindToRole(Header.Kind); 309d3676d4bSMichael Spencer Module::Header H = {Header.FileName, std::string(Path.str()), *File}; 310040e1266SRichard Smith addHeader(Mod, H, Role); 311040e1266SRichard Smith return true; 3121d60987fSRichard Smith } 3131d60987fSRichard Smith 3140761a8a0SDaniel Jasper ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags, 315b146baabSArgyrios Kyrtzidis const LangOptions &LangOpts, const TargetInfo *Target, 316b146baabSArgyrios Kyrtzidis HeaderSearch &HeaderInfo) 3170761a8a0SDaniel Jasper : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target), 318056bf77fSRichard Smith HeaderInfo(HeaderInfo) { 3190414b857SRichard Smith MMapLangOpts.LineComment = true; 3200414b857SRichard Smith } 321718292f2SDouglas Gregor 322718292f2SDouglas Gregor ModuleMap::~ModuleMap() { 32321668754SDavide Italiano for (auto &M : Modules) 32421668754SDavide Italiano delete M.getValue(); 3258587dfd9SBruno Cardoso Lopes for (auto *M : ShadowModules) 3268587dfd9SBruno Cardoso Lopes delete M; 327718292f2SDouglas Gregor } 328718292f2SDouglas Gregor 32989929282SDouglas Gregor void ModuleMap::setTarget(const TargetInfo &Target) { 33089929282SDouglas Gregor assert((!this->Target || this->Target == &Target) && 33189929282SDouglas Gregor "Improper target override"); 33289929282SDouglas Gregor this->Target = &Target; 33389929282SDouglas Gregor } 33489929282SDouglas Gregor 3359fc8faf9SAdrian Prantl /// "Sanitize" a filename so that it can be used as an identifier. 336056396aeSDouglas Gregor static StringRef sanitizeFilenameAsIdentifier(StringRef Name, 337056396aeSDouglas Gregor SmallVectorImpl<char> &Buffer) { 338056396aeSDouglas Gregor if (Name.empty()) 339056396aeSDouglas Gregor return Name; 340056396aeSDouglas Gregor 341601102d2SCorentin Jabot if (!isValidAsciiIdentifier(Name)) { 342056396aeSDouglas Gregor // If we don't already have something with the form of an identifier, 343056396aeSDouglas Gregor // create a buffer with the sanitized name. 344056396aeSDouglas Gregor Buffer.clear(); 345a7d03840SJordan Rose if (isDigit(Name[0])) 346056396aeSDouglas Gregor Buffer.push_back('_'); 347056396aeSDouglas Gregor Buffer.reserve(Buffer.size() + Name.size()); 348056396aeSDouglas Gregor for (unsigned I = 0, N = Name.size(); I != N; ++I) { 349601102d2SCorentin Jabot if (isAsciiIdentifierContinue(Name[I])) 350056396aeSDouglas Gregor Buffer.push_back(Name[I]); 351056396aeSDouglas Gregor else 352056396aeSDouglas Gregor Buffer.push_back('_'); 353056396aeSDouglas Gregor } 354056396aeSDouglas Gregor 355056396aeSDouglas Gregor Name = StringRef(Buffer.data(), Buffer.size()); 356056396aeSDouglas Gregor } 357056396aeSDouglas Gregor 358056396aeSDouglas Gregor while (llvm::StringSwitch<bool>(Name) 359056396aeSDouglas Gregor #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true) 360056396aeSDouglas Gregor #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true) 361056396aeSDouglas Gregor #include "clang/Basic/TokenKinds.def" 362056396aeSDouglas Gregor .Default(false)) { 363056396aeSDouglas Gregor if (Name.data() != Buffer.data()) 364056396aeSDouglas Gregor Buffer.append(Name.begin(), Name.end()); 365056396aeSDouglas Gregor Buffer.push_back('_'); 366056396aeSDouglas Gregor Name = StringRef(Buffer.data(), Buffer.size()); 367056396aeSDouglas Gregor } 368056396aeSDouglas Gregor 369056396aeSDouglas Gregor return Name; 370056396aeSDouglas Gregor } 371056396aeSDouglas Gregor 3729fc8faf9SAdrian Prantl /// Determine whether the given file name is the name of a builtin 37334d52749SDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system 37434d52749SDouglas Gregor /// headers. 375ba1b5c98SBruno Cardoso Lopes bool ModuleMap::isBuiltinHeader(StringRef FileName) { 37634d52749SDouglas Gregor return llvm::StringSwitch<bool>(FileName) 37734d52749SDouglas Gregor .Case("float.h", true) 37834d52749SDouglas Gregor .Case("iso646.h", true) 37934d52749SDouglas Gregor .Case("limits.h", true) 38034d52749SDouglas Gregor .Case("stdalign.h", true) 38134d52749SDouglas Gregor .Case("stdarg.h", true) 3823c4b1290SBen Langmuir .Case("stdatomic.h", true) 38334d52749SDouglas Gregor .Case("stdbool.h", true) 38434d52749SDouglas Gregor .Case("stddef.h", true) 38534d52749SDouglas Gregor .Case("stdint.h", true) 38634d52749SDouglas Gregor .Case("tgmath.h", true) 38734d52749SDouglas Gregor .Case("unwind.h", true) 38834d52749SDouglas Gregor .Default(false); 38934d52749SDouglas Gregor } 39034d52749SDouglas Gregor 3918d74de9dSMartin Boehme bool ModuleMap::isBuiltinHeader(const FileEntry *File) { 3928d74de9dSMartin Boehme return File->getDir() == BuiltinIncludeDir && 3938d74de9dSMartin Boehme ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName())); 3948d74de9dSMartin Boehme } 3958d74de9dSMartin Boehme 39692669ee4SDaniel Jasper ModuleMap::HeadersMap::iterator 39792669ee4SDaniel Jasper ModuleMap::findKnownHeader(const FileEntry *File) { 398040e1266SRichard Smith resolveHeaderDirectives(File); 39959527666SDouglas Gregor HeadersMap::iterator Known = Headers.find(File); 40047972afdSRichard Smith if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && 4018d74de9dSMartin Boehme Known == Headers.end() && ModuleMap::isBuiltinHeader(File)) { 4024eaf0a6cSDaniel Jasper HeaderInfo.loadTopLevelSystemModules(); 40392669ee4SDaniel Jasper return Headers.find(File); 4044eaf0a6cSDaniel Jasper } 40592669ee4SDaniel Jasper return Known; 40692669ee4SDaniel Jasper } 40792669ee4SDaniel Jasper 4084469138eSBen Langmuir ModuleMap::KnownHeader 4094469138eSBen Langmuir ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File, 4104469138eSBen Langmuir SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) { 41147972afdSRichard Smith if (UmbrellaDirs.empty()) 412afd1b1c9SEugene Zelenko return {}; 41347972afdSRichard Smith 4144469138eSBen Langmuir const DirectoryEntry *Dir = File->getDir(); 4154469138eSBen Langmuir assert(Dir && "file in no directory"); 4164469138eSBen Langmuir 4174469138eSBen Langmuir // Note: as an egregious but useful hack we use the real path here, because 4184469138eSBen Langmuir // frameworks moving from top-level frameworks to embedded frameworks tend 4194469138eSBen Langmuir // to be symlinked from the top-level location to the embedded location, 4204469138eSBen Langmuir // and we need to resolve lookups as if we had found the embedded location. 4214469138eSBen Langmuir StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir); 4224469138eSBen Langmuir 4234469138eSBen Langmuir // Keep walking up the directory hierarchy, looking for a directory with 4244469138eSBen Langmuir // an umbrella header. 4254469138eSBen Langmuir do { 4264469138eSBen Langmuir auto KnownDir = UmbrellaDirs.find(Dir); 4274469138eSBen Langmuir if (KnownDir != UmbrellaDirs.end()) 4284469138eSBen Langmuir return KnownHeader(KnownDir->second, NormalHeader); 4294469138eSBen Langmuir 4304469138eSBen Langmuir IntermediateDirs.push_back(Dir); 4314469138eSBen Langmuir 4324469138eSBen Langmuir // Retrieve our parent path. 4334469138eSBen Langmuir DirName = llvm::sys::path::parent_path(DirName); 4344469138eSBen Langmuir if (DirName.empty()) 4354469138eSBen Langmuir break; 4364469138eSBen Langmuir 4374469138eSBen Langmuir // Resolve the parent path to a directory entry. 4388d323d15SHarlan Haskins if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName)) 4398d323d15SHarlan Haskins Dir = *DirEntry; 4408d323d15SHarlan Haskins else 4418d323d15SHarlan Haskins Dir = nullptr; 4424469138eSBen Langmuir } while (Dir); 443afd1b1c9SEugene Zelenko return {}; 4444469138eSBen Langmuir } 4454469138eSBen Langmuir 44692669ee4SDaniel Jasper static bool violatesPrivateInclude(Module *RequestingModule, 44792669ee4SDaniel Jasper const FileEntry *IncFileEnt, 4484eb8393cSRichard Smith ModuleMap::KnownHeader Header) { 44992669ee4SDaniel Jasper #ifndef NDEBUG 4504eb8393cSRichard Smith if (Header.getRole() & ModuleMap::PrivateHeader) { 45192669ee4SDaniel Jasper // Check for consistency between the module header role 45292669ee4SDaniel Jasper // as obtained from the lookup and as obtained from the module. 45392669ee4SDaniel Jasper // This check is not cheap, so enable it only for debugging. 4542708e520SRichard Smith bool IsPrivate = false; 4552708e520SRichard Smith SmallVectorImpl<Module::Header> *HeaderList[] = { 4564eb8393cSRichard Smith &Header.getModule()->Headers[Module::HK_Private], 4574eb8393cSRichard Smith &Header.getModule()->Headers[Module::HK_PrivateTextual]}; 4582708e520SRichard Smith for (auto *Hs : HeaderList) 4592708e520SRichard Smith IsPrivate |= 4602708e520SRichard Smith std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) { 4613c1a41adSRichard Smith return H.Entry == IncFileEnt; 4622708e520SRichard Smith }) != Hs->end(); 4634eb8393cSRichard Smith assert(IsPrivate && "inconsistent headers and roles"); 46400bc95ecSRichard Smith } 46592669ee4SDaniel Jasper #endif 4664eb8393cSRichard Smith return !Header.isAccessibleFrom(RequestingModule); 46792669ee4SDaniel Jasper } 46892669ee4SDaniel Jasper 46971e1a64fSBen Langmuir static Module *getTopLevelOrNull(Module *M) { 47071e1a64fSBen Langmuir return M ? M->getTopLevelModule() : nullptr; 47171e1a64fSBen Langmuir } 47271e1a64fSBen Langmuir 47392669ee4SDaniel Jasper void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, 4748d4e90b3SRichard Smith bool RequestingModuleIsModuleInterface, 47592669ee4SDaniel Jasper SourceLocation FilenameLoc, 47692669ee4SDaniel Jasper StringRef Filename, 47792669ee4SDaniel Jasper const FileEntry *File) { 47892669ee4SDaniel Jasper // No errors for indirect modules. This may be a bit of a problem for modules 47992669ee4SDaniel Jasper // with no source files. 48071e1a64fSBen Langmuir if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule)) 48192669ee4SDaniel Jasper return; 48292669ee4SDaniel Jasper 483040e1266SRichard Smith if (RequestingModule) { 48492669ee4SDaniel Jasper resolveUses(RequestingModule, /*Complain=*/false); 485*8f4ea36bSAdam Czachorowski resolveHeaderDirectives(RequestingModule, /*File=*/llvm::None); 486040e1266SRichard Smith } 48792669ee4SDaniel Jasper 48871e1a64fSBen Langmuir bool Excluded = false; 489d2d442caSCraig Topper Module *Private = nullptr; 490d2d442caSCraig Topper Module *NotUsed = nullptr; 49171e1a64fSBen Langmuir 49271e1a64fSBen Langmuir HeadersMap::iterator Known = findKnownHeader(File); 49371e1a64fSBen Langmuir if (Known != Headers.end()) { 49471e1a64fSBen Langmuir for (const KnownHeader &Header : Known->second) { 49592669ee4SDaniel Jasper // Remember private headers for later printing of a diagnostic. 4964eb8393cSRichard Smith if (violatesPrivateInclude(RequestingModule, File, Header)) { 49771e1a64fSBen Langmuir Private = Header.getModule(); 49892669ee4SDaniel Jasper continue; 49992669ee4SDaniel Jasper } 50092669ee4SDaniel Jasper 50192669ee4SDaniel Jasper // If uses need to be specified explicitly, we are only allowed to return 50292669ee4SDaniel Jasper // modules that are explicitly used by the requesting module. 50392669ee4SDaniel Jasper if (RequestingModule && LangOpts.ModulesDeclUse && 5048f4d3ff1SRichard Smith !RequestingModule->directlyUses(Header.getModule())) { 50571e1a64fSBen Langmuir NotUsed = Header.getModule(); 50692669ee4SDaniel Jasper continue; 50792669ee4SDaniel Jasper } 50892669ee4SDaniel Jasper 50992669ee4SDaniel Jasper // We have found a module that we can happily use. 51092669ee4SDaniel Jasper return; 51192669ee4SDaniel Jasper } 512feb54b6dSRichard Smith 513feb54b6dSRichard Smith Excluded = true; 51471e1a64fSBen Langmuir } 51592669ee4SDaniel Jasper 51692669ee4SDaniel Jasper // We have found a header, but it is private. 517d2d442caSCraig Topper if (Private) { 51811152dd5SRichard Smith Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module) 51992669ee4SDaniel Jasper << Filename; 52092669ee4SDaniel Jasper return; 52192669ee4SDaniel Jasper } 52292669ee4SDaniel Jasper 52392669ee4SDaniel Jasper // We have found a module, but we don't use it. 524d2d442caSCraig Topper if (NotUsed) { 52511152dd5SRichard Smith Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) 5264ea330c8SDaniel Jasper << RequestingModule->getTopLevelModule()->Name << Filename; 52792669ee4SDaniel Jasper return; 52892669ee4SDaniel Jasper } 52992669ee4SDaniel Jasper 53071e1a64fSBen Langmuir if (Excluded || isHeaderInUmbrellaDirs(File)) 53171e1a64fSBen Langmuir return; 53271e1a64fSBen Langmuir 53371e1a64fSBen Langmuir // At this point, only non-modular includes remain. 53471e1a64fSBen Langmuir 5355904c41eSBenjamin Kramer if (RequestingModule && LangOpts.ModulesStrictDeclUse) { 53611152dd5SRichard Smith Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) 5374ea330c8SDaniel Jasper << RequestingModule->getTopLevelModule()->Name << Filename; 538a67e4d32SManman Ren } else if (RequestingModule && RequestingModuleIsModuleInterface && 539a67e4d32SManman Ren LangOpts.isCompilingModule()) { 540a67e4d32SManman Ren // Do not diagnose when we are not compiling a module. 54171e1a64fSBen Langmuir diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ? 54271e1a64fSBen Langmuir diag::warn_non_modular_include_in_framework_module : 54371e1a64fSBen Langmuir diag::warn_non_modular_include_in_module; 54470a7738fSManman Ren Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName() 54570a7738fSManman Ren << File->getName(); 54671e1a64fSBen Langmuir } 54792669ee4SDaniel Jasper } 54892669ee4SDaniel Jasper 549ec87a50aSRichard Smith static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New, 550ec87a50aSRichard Smith const ModuleMap::KnownHeader &Old) { 5518b7c0398SSean Silva // Prefer available modules. 5526bc75023SRichard Smith // FIXME: Considering whether the module is available rather than merely 5536bc75023SRichard Smith // importable is non-hermetic and can result in surprising behavior for 5546bc75023SRichard Smith // prebuilt modules. Consider only checking for importability here. 5558b7c0398SSean Silva if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable()) 5568b7c0398SSean Silva return true; 5578b7c0398SSean Silva 558ec87a50aSRichard Smith // Prefer a public header over a private header. 559ec87a50aSRichard Smith if ((New.getRole() & ModuleMap::PrivateHeader) != 560ec87a50aSRichard Smith (Old.getRole() & ModuleMap::PrivateHeader)) 561ec87a50aSRichard Smith return !(New.getRole() & ModuleMap::PrivateHeader); 562ec87a50aSRichard Smith 563ec87a50aSRichard Smith // Prefer a non-textual header over a textual header. 564ec87a50aSRichard Smith if ((New.getRole() & ModuleMap::TextualHeader) != 565ec87a50aSRichard Smith (Old.getRole() & ModuleMap::TextualHeader)) 566ec87a50aSRichard Smith return !(New.getRole() & ModuleMap::TextualHeader); 567ec87a50aSRichard Smith 568ec87a50aSRichard Smith // Don't have a reason to choose between these. Just keep the first one. 569ec87a50aSRichard Smith return false; 570ec87a50aSRichard Smith } 571ec87a50aSRichard Smith 572ed84df00SBruno Cardoso Lopes ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File, 573ed84df00SBruno Cardoso Lopes bool AllowTextual) { 574306d8920SRichard Smith auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader { 575ed84df00SBruno Cardoso Lopes if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader) 576afd1b1c9SEugene Zelenko return {}; 577306d8920SRichard Smith return R; 578306d8920SRichard Smith }; 579306d8920SRichard Smith 5804881e8b2SSean Silva HeadersMap::iterator Known = findKnownHeader(File); 5811fb5c3a6SDouglas Gregor if (Known != Headers.end()) { 582202210b3SRichard Smith ModuleMap::KnownHeader Result; 58397da9178SDaniel Jasper // Iterate over all modules that 'File' is part of to find the best fit. 5844881e8b2SSean Silva for (KnownHeader &H : Known->second) { 5857e82e019SRichard Smith // Prefer a header from the source module over all others. 5867e82e019SRichard Smith if (H.getModule()->getTopLevelModule() == SourceModule) 5872f633e7cSRichard Smith return MakeResult(H); 5884881e8b2SSean Silva if (!Result || isBetterKnownHeader(H, Result)) 5894881e8b2SSean Silva Result = H; 59097da9178SDaniel Jasper } 591306d8920SRichard Smith return MakeResult(Result); 5921fb5c3a6SDouglas Gregor } 593ab0c8a84SDouglas Gregor 594386bb073SRichard Smith return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File)); 595386bb073SRichard Smith } 596386bb073SRichard Smith 597386bb073SRichard Smith ModuleMap::KnownHeader 598386bb073SRichard Smith ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) { 599386bb073SRichard Smith assert(!Headers.count(File) && "already have a module for this header"); 600386bb073SRichard Smith 601f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs; 6024469138eSBen Langmuir KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs); 6034469138eSBen Langmuir if (H) { 6044469138eSBen Langmuir Module *Result = H.getModule(); 605930a85ccSDouglas Gregor 606930a85ccSDouglas Gregor // Search up the module stack until we find a module with an umbrella 60773141fa9SDouglas Gregor // directory. 608930a85ccSDouglas Gregor Module *UmbrellaModule = Result; 60973141fa9SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 610930a85ccSDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 611930a85ccSDouglas Gregor 612930a85ccSDouglas Gregor if (UmbrellaModule->InferSubmodules) { 6139d6448b1SBen Langmuir const FileEntry *UmbrellaModuleMap = 6149d6448b1SBen Langmuir getModuleMapFileForUniquing(UmbrellaModule); 6159d6448b1SBen Langmuir 616a89c5ac4SDouglas Gregor // Infer submodules for each of the directories we found between 617a89c5ac4SDouglas Gregor // the directory of the umbrella header and the directory where 618a89c5ac4SDouglas Gregor // the actual header is located. 6199458f82dSDouglas Gregor bool Explicit = UmbrellaModule->InferExplicitSubmodules; 6209458f82dSDouglas Gregor 6218adb6d6dSBenjamin Kramer for (const DirectoryEntry *SkippedDir : llvm::reverse(SkippedDirs)) { 622a89c5ac4SDouglas Gregor // Find or create the module that corresponds to this directory name. 623056396aeSDouglas Gregor SmallString<32> NameBuf; 624056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 6258adb6d6dSBenjamin Kramer llvm::sys::path::stem(SkippedDir->getName()), NameBuf); 6269d6448b1SBen Langmuir Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 6279d6448b1SBen Langmuir Explicit).first; 6289d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = UmbrellaModuleMap; 629ffbafa2aSBen Langmuir Result->IsInferred = true; 630a89c5ac4SDouglas Gregor 631a89c5ac4SDouglas Gregor // Associate the module and the directory. 6328adb6d6dSBenjamin Kramer UmbrellaDirs[SkippedDir] = Result; 633a89c5ac4SDouglas Gregor 634a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 635a89c5ac4SDouglas Gregor // wildcard to the set of exports. 636930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 637d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 638a89c5ac4SDouglas Gregor } 639a89c5ac4SDouglas Gregor 640a89c5ac4SDouglas Gregor // Infer a submodule with the same name as this header file. 641056396aeSDouglas Gregor SmallString<32> NameBuf; 642056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 643056396aeSDouglas Gregor llvm::sys::path::stem(File->getName()), NameBuf); 6449d6448b1SBen Langmuir Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 6459d6448b1SBen Langmuir Explicit).first; 6469d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = UmbrellaModuleMap; 647ffbafa2aSBen Langmuir Result->IsInferred = true; 6483c5305c1SArgyrios Kyrtzidis Result->addTopHeader(File); 649a89c5ac4SDouglas Gregor 650a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 651a89c5ac4SDouglas Gregor // wildcard to the set of exports. 652930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 653d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 654a89c5ac4SDouglas Gregor } else { 655a89c5ac4SDouglas Gregor // Record each of the directories we stepped through as being part of 656a89c5ac4SDouglas Gregor // the module we found, since the umbrella header covers them all. 657a89c5ac4SDouglas Gregor for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I) 658a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I]] = Result; 659a89c5ac4SDouglas Gregor } 660a89c5ac4SDouglas Gregor 661386bb073SRichard Smith KnownHeader Header(Result, NormalHeader); 662386bb073SRichard Smith Headers[File].push_back(Header); 663386bb073SRichard Smith return Header; 664a89c5ac4SDouglas Gregor } 665a89c5ac4SDouglas Gregor 666afd1b1c9SEugene Zelenko return {}; 667ab0c8a84SDouglas Gregor } 668ab0c8a84SDouglas Gregor 669386bb073SRichard Smith ArrayRef<ModuleMap::KnownHeader> 6700a088eadSRichard Smith ModuleMap::findAllModulesForHeader(const FileEntry *File) { 6710a088eadSRichard Smith HeadersMap::iterator Known = findKnownHeader(File); 6720a088eadSRichard Smith if (Known != Headers.end()) 6730a088eadSRichard Smith return Known->second; 6740a088eadSRichard Smith 6750a088eadSRichard Smith if (findOrCreateModuleForHeaderInUmbrellaDir(File)) 6760a088eadSRichard Smith return Headers.find(File)->second; 6770a088eadSRichard Smith 6780a088eadSRichard Smith return None; 6790a088eadSRichard Smith } 6800a088eadSRichard Smith 6810a088eadSRichard Smith ArrayRef<ModuleMap::KnownHeader> 6820a088eadSRichard Smith ModuleMap::findResolvedModulesForHeader(const FileEntry *File) const { 6830a088eadSRichard Smith // FIXME: Is this necessary? 684040e1266SRichard Smith resolveHeaderDirectives(File); 685386bb073SRichard Smith auto It = Headers.find(File); 686386bb073SRichard Smith if (It == Headers.end()) 687386bb073SRichard Smith return None; 688386bb073SRichard Smith return It->second; 689386bb073SRichard Smith } 690386bb073SRichard Smith 691e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const { 692d2d442caSCraig Topper return isHeaderUnavailableInModule(Header, nullptr); 69350996ce1SRichard Smith } 69450996ce1SRichard Smith 69562bcd925SDmitri Gribenko bool 69662bcd925SDmitri Gribenko ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, 69762bcd925SDmitri Gribenko const Module *RequestingModule) const { 698040e1266SRichard Smith resolveHeaderDirectives(Header); 699e4412640SArgyrios Kyrtzidis HeadersMap::const_iterator Known = Headers.find(Header); 70097da9178SDaniel Jasper if (Known != Headers.end()) { 70197da9178SDaniel Jasper for (SmallVectorImpl<KnownHeader>::const_iterator 70297da9178SDaniel Jasper I = Known->second.begin(), 70397da9178SDaniel Jasper E = Known->second.end(); 70497da9178SDaniel Jasper I != E; ++I) { 705052d95a6SBruno Cardoso Lopes 706052d95a6SBruno Cardoso Lopes if (I->isAvailable() && 707052d95a6SBruno Cardoso Lopes (!RequestingModule || 708052d95a6SBruno Cardoso Lopes I->getModule()->isSubModuleOf(RequestingModule))) { 709052d95a6SBruno Cardoso Lopes // When no requesting module is available, the caller is looking if a 710052d95a6SBruno Cardoso Lopes // header is part a module by only looking into the module map. This is 711052d95a6SBruno Cardoso Lopes // done by warn_uncovered_module_header checks; don't consider textual 712052d95a6SBruno Cardoso Lopes // headers part of it in this mode, otherwise we get misleading warnings 713052d95a6SBruno Cardoso Lopes // that a umbrella header is not including a textual header. 714052d95a6SBruno Cardoso Lopes if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader) 715052d95a6SBruno Cardoso Lopes continue; 71697da9178SDaniel Jasper return false; 71797da9178SDaniel Jasper } 718052d95a6SBruno Cardoso Lopes } 71997da9178SDaniel Jasper return true; 72097da9178SDaniel Jasper } 7211fb5c3a6SDouglas Gregor 7221fb5c3a6SDouglas Gregor const DirectoryEntry *Dir = Header->getDir(); 723f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs; 7241fb5c3a6SDouglas Gregor StringRef DirName = Dir->getName(); 7251fb5c3a6SDouglas Gregor 72650996ce1SRichard Smith auto IsUnavailable = [&](const Module *M) { 72750996ce1SRichard Smith return !M->isAvailable() && (!RequestingModule || 72850996ce1SRichard Smith M->isSubModuleOf(RequestingModule)); 72950996ce1SRichard Smith }; 73050996ce1SRichard Smith 7311fb5c3a6SDouglas Gregor // Keep walking up the directory hierarchy, looking for a directory with 7321fb5c3a6SDouglas Gregor // an umbrella header. 7331fb5c3a6SDouglas Gregor do { 734e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir 7351fb5c3a6SDouglas Gregor = UmbrellaDirs.find(Dir); 7361fb5c3a6SDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 7371fb5c3a6SDouglas Gregor Module *Found = KnownDir->second; 73850996ce1SRichard Smith if (IsUnavailable(Found)) 7391fb5c3a6SDouglas Gregor return true; 7401fb5c3a6SDouglas Gregor 7411fb5c3a6SDouglas Gregor // Search up the module stack until we find a module with an umbrella 7421fb5c3a6SDouglas Gregor // directory. 7431fb5c3a6SDouglas Gregor Module *UmbrellaModule = Found; 7441fb5c3a6SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 7451fb5c3a6SDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 7461fb5c3a6SDouglas Gregor 7471fb5c3a6SDouglas Gregor if (UmbrellaModule->InferSubmodules) { 7488adb6d6dSBenjamin Kramer for (const DirectoryEntry *SkippedDir : llvm::reverse(SkippedDirs)) { 7491fb5c3a6SDouglas Gregor // Find or create the module that corresponds to this directory name. 750056396aeSDouglas Gregor SmallString<32> NameBuf; 751056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 7528adb6d6dSBenjamin Kramer llvm::sys::path::stem(SkippedDir->getName()), NameBuf); 7531fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 7541fb5c3a6SDouglas Gregor if (!Found) 7551fb5c3a6SDouglas Gregor return false; 75650996ce1SRichard Smith if (IsUnavailable(Found)) 7571fb5c3a6SDouglas Gregor return true; 7581fb5c3a6SDouglas Gregor } 7591fb5c3a6SDouglas Gregor 7601fb5c3a6SDouglas Gregor // Infer a submodule with the same name as this header file. 761056396aeSDouglas Gregor SmallString<32> NameBuf; 762056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 763056396aeSDouglas Gregor llvm::sys::path::stem(Header->getName()), 764056396aeSDouglas Gregor NameBuf); 7651fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 7661fb5c3a6SDouglas Gregor if (!Found) 7671fb5c3a6SDouglas Gregor return false; 7681fb5c3a6SDouglas Gregor } 7691fb5c3a6SDouglas Gregor 77050996ce1SRichard Smith return IsUnavailable(Found); 7711fb5c3a6SDouglas Gregor } 7721fb5c3a6SDouglas Gregor 7731fb5c3a6SDouglas Gregor SkippedDirs.push_back(Dir); 7741fb5c3a6SDouglas Gregor 7751fb5c3a6SDouglas Gregor // Retrieve our parent path. 7761fb5c3a6SDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 7771fb5c3a6SDouglas Gregor if (DirName.empty()) 7781fb5c3a6SDouglas Gregor break; 7791fb5c3a6SDouglas Gregor 7801fb5c3a6SDouglas Gregor // Resolve the parent path to a directory entry. 7818d323d15SHarlan Haskins if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName)) 7828d323d15SHarlan Haskins Dir = *DirEntry; 7838d323d15SHarlan Haskins else 7848d323d15SHarlan Haskins Dir = nullptr; 7851fb5c3a6SDouglas Gregor } while (Dir); 7861fb5c3a6SDouglas Gregor 7871fb5c3a6SDouglas Gregor return false; 7881fb5c3a6SDouglas Gregor } 7891fb5c3a6SDouglas Gregor 790e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const { 791e4412640SArgyrios Kyrtzidis llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name); 79288bdfb0eSDouglas Gregor if (Known != Modules.end()) 79388bdfb0eSDouglas Gregor return Known->getValue(); 79488bdfb0eSDouglas Gregor 795d2d442caSCraig Topper return nullptr; 79688bdfb0eSDouglas Gregor } 79788bdfb0eSDouglas Gregor 798e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name, 799e4412640SArgyrios Kyrtzidis Module *Context) const { 8002b82c2a5SDouglas Gregor for(; Context; Context = Context->Parent) { 8012b82c2a5SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Context)) 8022b82c2a5SDouglas Gregor return Sub; 8032b82c2a5SDouglas Gregor } 8042b82c2a5SDouglas Gregor 8052b82c2a5SDouglas Gregor return findModule(Name); 8062b82c2a5SDouglas Gregor } 8072b82c2a5SDouglas Gregor 808e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{ 8092b82c2a5SDouglas Gregor if (!Context) 8102b82c2a5SDouglas Gregor return findModule(Name); 8112b82c2a5SDouglas Gregor 812eb90e830SDouglas Gregor return Context->findSubmodule(Name); 8132b82c2a5SDouglas Gregor } 8142b82c2a5SDouglas Gregor 815c192d194SBruno Cardoso Lopes std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name, 816c192d194SBruno Cardoso Lopes Module *Parent, 817c192d194SBruno Cardoso Lopes bool IsFramework, 818c192d194SBruno Cardoso Lopes bool IsExplicit) { 81969021974SDouglas Gregor // Try to find an existing module with this name. 820eb90e830SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Parent)) 821eb90e830SDouglas Gregor return std::make_pair(Sub, false); 82269021974SDouglas Gregor 82369021974SDouglas Gregor // Create a new module with this name. 8249ffe5a35SDavid Blaikie Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, 8259ffe5a35SDavid Blaikie IsExplicit, NumCreatedModules++); 8266f722b4eSArgyrios Kyrtzidis if (!Parent) { 8277e82e019SRichard Smith if (LangOpts.CurrentModule == Name) 8287e82e019SRichard Smith SourceModule = Result; 82969021974SDouglas Gregor Modules[Name] = Result; 830c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID; 8316f722b4eSArgyrios Kyrtzidis } 83269021974SDouglas Gregor return std::make_pair(Result, true); 83369021974SDouglas Gregor } 83469021974SDouglas Gregor 835e587372fSChuanqi Xu Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc, 836e587372fSChuanqi Xu Module *Parent) { 837e587372fSChuanqi Xu auto *Result = new Module("<global>", Loc, Parent, /*IsFramework*/ false, 838e587372fSChuanqi Xu /*IsExplicit*/ true, NumCreatedModules++); 839e587372fSChuanqi Xu Result->Kind = Module::GlobalModuleFragment; 840e587372fSChuanqi Xu // If the created module isn't owned by a parent, send it to PendingSubmodules 841e587372fSChuanqi Xu // to wait for its parent. 842e587372fSChuanqi Xu if (!Result->Parent) 843e587372fSChuanqi Xu PendingSubmodules.emplace_back(Result); 844e587372fSChuanqi Xu return Result; 845dd8b5337SRichard Smith } 846dd8b5337SRichard Smith 847a5bbbfefSRichard Smith Module * 848a5bbbfefSRichard Smith ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent, 849a5bbbfefSRichard Smith SourceLocation Loc) { 850a5bbbfefSRichard Smith auto *Result = 851a5bbbfefSRichard Smith new Module("<private>", Loc, Parent, /*IsFramework*/ false, 852a5bbbfefSRichard Smith /*IsExplicit*/ true, NumCreatedModules++); 853a5bbbfefSRichard Smith Result->Kind = Module::PrivateModuleFragment; 854a5bbbfefSRichard Smith return Result; 855a5bbbfefSRichard Smith } 856a5bbbfefSRichard Smith 857bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc, 858dd8b5337SRichard Smith StringRef Name, 859dd8b5337SRichard Smith Module *GlobalModule) { 860bbcc9f04SRichard Smith assert(LangOpts.CurrentModule == Name && "module name mismatch"); 861bbcc9f04SRichard Smith assert(!Modules[Name] && "redefining existing module"); 862bbcc9f04SRichard Smith 863bbcc9f04SRichard Smith auto *Result = 864bbcc9f04SRichard Smith new Module(Name, Loc, nullptr, /*IsFramework*/ false, 865bbcc9f04SRichard Smith /*IsExplicit*/ false, NumCreatedModules++); 866145e15a3SRichard Smith Result->Kind = Module::ModuleInterfaceUnit; 867bbcc9f04SRichard Smith Modules[Name] = SourceModule = Result; 868bbcc9f04SRichard Smith 869dd8b5337SRichard Smith // Reparent the current global module fragment as a submodule of this module. 870d6509cf2SRichard Smith for (auto &Submodule : PendingSubmodules) { 871d6509cf2SRichard Smith Submodule->setParent(Result); 872d6509cf2SRichard Smith Submodule.release(); // now owned by parent 873d6509cf2SRichard Smith } 874d6509cf2SRichard Smith PendingSubmodules.clear(); 875dd8b5337SRichard Smith 876bbcc9f04SRichard Smith // Mark the main source file as being within the newly-created module so that 877bbcc9f04SRichard Smith // declarations and macros are properly visibility-restricted to it. 878bbcc9f04SRichard Smith auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()); 879bbcc9f04SRichard Smith assert(MainFile && "no input file for module interface"); 880bbcc9f04SRichard Smith Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader)); 881bbcc9f04SRichard Smith 882bbcc9f04SRichard Smith return Result; 883bbcc9f04SRichard Smith } 884bbcc9f04SRichard Smith 885d6509cf2SRichard Smith Module *ModuleMap::createHeaderModule(StringRef Name, 886d6509cf2SRichard Smith ArrayRef<Module::Header> Headers) { 887d6509cf2SRichard Smith assert(LangOpts.CurrentModule == Name && "module name mismatch"); 888d6509cf2SRichard Smith assert(!Modules[Name] && "redefining existing module"); 889d6509cf2SRichard Smith 890d6509cf2SRichard Smith auto *Result = 891d6509cf2SRichard Smith new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false, 892d6509cf2SRichard Smith /*IsExplicit*/ false, NumCreatedModules++); 893d6509cf2SRichard Smith Result->Kind = Module::ModuleInterfaceUnit; 894d6509cf2SRichard Smith Modules[Name] = SourceModule = Result; 895d6509cf2SRichard Smith 896d6509cf2SRichard Smith for (const Module::Header &H : Headers) { 897d6509cf2SRichard Smith auto *M = new Module(H.NameAsWritten, SourceLocation(), Result, 898d6509cf2SRichard Smith /*IsFramework*/ false, 899d6509cf2SRichard Smith /*IsExplicit*/ true, NumCreatedModules++); 900d6509cf2SRichard Smith // Header modules are implicitly 'export *'. 901d6509cf2SRichard Smith M->Exports.push_back(Module::ExportDecl(nullptr, true)); 902d6509cf2SRichard Smith addHeader(M, H, NormalHeader); 903d6509cf2SRichard Smith } 904d6509cf2SRichard Smith 905d6509cf2SRichard Smith return Result; 906d6509cf2SRichard Smith } 907d6509cf2SRichard Smith 9089fc8faf9SAdrian Prantl /// For a framework module, infer the framework against which we 90911dfe6feSDouglas Gregor /// should link. 91011dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir, 91111dfe6feSDouglas Gregor FileManager &FileMgr) { 91211dfe6feSDouglas Gregor assert(Mod->IsFramework && "Can only infer linking for framework modules"); 91311dfe6feSDouglas Gregor assert(!Mod->isSubFramework() && 91411dfe6feSDouglas Gregor "Can only infer linking for top-level frameworks"); 91511dfe6feSDouglas Gregor 91611dfe6feSDouglas Gregor SmallString<128> LibName; 91711dfe6feSDouglas Gregor LibName += FrameworkDir->getName(); 91811dfe6feSDouglas Gregor llvm::sys::path::append(LibName, Mod->Name); 9198aaae5a9SJuergen Ributzka 9208aaae5a9SJuergen Ributzka // The library name of a framework has more than one possible extension since 9218aaae5a9SJuergen Ributzka // the introduction of the text-based dynamic library format. We need to check 9228aaae5a9SJuergen Ributzka // for both before we give up. 9238013e81dSBenjamin Kramer for (const char *extension : {"", ".tbd"}) { 9248aaae5a9SJuergen Ributzka llvm::sys::path::replace_extension(LibName, extension); 92511dfe6feSDouglas Gregor if (FileMgr.getFile(LibName)) { 92611dfe6feSDouglas Gregor Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name, 92711dfe6feSDouglas Gregor /*IsFramework=*/true)); 9288aaae5a9SJuergen Ributzka return; 9298aaae5a9SJuergen Ributzka } 93011dfe6feSDouglas Gregor } 93111dfe6feSDouglas Gregor } 93211dfe6feSDouglas Gregor 933a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 934a525400dSBen Langmuir bool IsSystem, Module *Parent) { 935c1d88ea5SBen Langmuir Attributes Attrs; 936c1d88ea5SBen Langmuir Attrs.IsSystem = IsSystem; 937a525400dSBen Langmuir return inferFrameworkModule(FrameworkDir, Attrs, Parent); 938c1d88ea5SBen Langmuir } 939c1d88ea5SBen Langmuir 940a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 941c1d88ea5SBen Langmuir Attributes Attrs, Module *Parent) { 942a525400dSBen Langmuir // Note: as an egregious but useful hack we use the real path here, because 943a525400dSBen Langmuir // we might be looking at an embedded framework that symlinks out to a 944a525400dSBen Langmuir // top-level framework, and we need to infer as if we were naming the 945a525400dSBen Langmuir // top-level framework. 946a525400dSBen Langmuir StringRef FrameworkDirName = 947a525400dSBen Langmuir SourceMgr.getFileManager().getCanonicalName(FrameworkDir); 948a525400dSBen Langmuir 949a525400dSBen Langmuir // In case this is a case-insensitive filesystem, use the canonical 950a525400dSBen Langmuir // directory name as the ModuleName, since modules are case-sensitive. 951a525400dSBen Langmuir // FIXME: we should be able to give a fix-it hint for the correct spelling. 952a525400dSBen Langmuir SmallString<32> ModuleNameStorage; 953a525400dSBen Langmuir StringRef ModuleName = sanitizeFilenameAsIdentifier( 954a525400dSBen Langmuir llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage); 955c1d88ea5SBen Langmuir 95656c64013SDouglas Gregor // Check whether we've already found this module. 957e89dbc1dSDouglas Gregor if (Module *Mod = lookupModuleQualified(ModuleName, Parent)) 958e89dbc1dSDouglas Gregor return Mod; 959e89dbc1dSDouglas Gregor 9601f76c4e8SManuel Klimek FileManager &FileMgr = SourceMgr.getFileManager(); 96156c64013SDouglas Gregor 9629194a91dSDouglas Gregor // If the framework has a parent path from which we're allowed to infer 9639194a91dSDouglas Gregor // a framework module, do so. 964beee15e7SBen Langmuir const FileEntry *ModuleMapFile = nullptr; 9659194a91dSDouglas Gregor if (!Parent) { 9664ddf2221SDouglas Gregor // Determine whether we're allowed to infer a module map. 9679194a91dSDouglas Gregor bool canInfer = false; 9684ddf2221SDouglas Gregor if (llvm::sys::path::has_parent_path(FrameworkDirName)) { 9699194a91dSDouglas Gregor // Figure out the parent path. 9704ddf2221SDouglas Gregor StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName); 9718d323d15SHarlan Haskins if (auto ParentDir = FileMgr.getDirectory(Parent)) { 9729194a91dSDouglas Gregor // Check whether we have already looked into the parent directory 9739194a91dSDouglas Gregor // for a module map. 974e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator 9758d323d15SHarlan Haskins inferred = InferredDirectories.find(*ParentDir); 9769194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) { 9779194a91dSDouglas Gregor // We haven't looked here before. Load a module map, if there is 9789194a91dSDouglas Gregor // one. 979984e1df7SBen Langmuir bool IsFrameworkDir = Parent.endswith(".framework"); 9807799ef71SNico Weber if (const FileEntry *ModMapFile = 9818d323d15SHarlan Haskins HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) { 9827799ef71SNico Weber parseModuleMapFile(ModMapFile, Attrs.IsSystem, *ParentDir); 9838d323d15SHarlan Haskins inferred = InferredDirectories.find(*ParentDir); 9849194a91dSDouglas Gregor } 9859194a91dSDouglas Gregor 9869194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) 9879194a91dSDouglas Gregor inferred = InferredDirectories.insert( 9888d323d15SHarlan Haskins std::make_pair(*ParentDir, InferredDirectory())).first; 9899194a91dSDouglas Gregor } 9909194a91dSDouglas Gregor 9919194a91dSDouglas Gregor if (inferred->second.InferModules) { 9929194a91dSDouglas Gregor // We're allowed to infer for this directory, but make sure it's okay 9939194a91dSDouglas Gregor // to infer this particular module. 9944ddf2221SDouglas Gregor StringRef Name = llvm::sys::path::stem(FrameworkDirName); 995e567f37dSKazu Hirata canInfer = 996e567f37dSKazu Hirata !llvm::is_contained(inferred->second.ExcludedModules, Name); 9979194a91dSDouglas Gregor 998c1d88ea5SBen Langmuir Attrs.IsSystem |= inferred->second.Attrs.IsSystem; 999c1d88ea5SBen Langmuir Attrs.IsExternC |= inferred->second.Attrs.IsExternC; 1000c1d88ea5SBen Langmuir Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive; 1001ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes |= 1002ed84df00SBruno Cardoso Lopes inferred->second.Attrs.NoUndeclaredIncludes; 1003beee15e7SBen Langmuir ModuleMapFile = inferred->second.ModuleMapFile; 10049194a91dSDouglas Gregor } 10059194a91dSDouglas Gregor } 10069194a91dSDouglas Gregor } 10079194a91dSDouglas Gregor 10089194a91dSDouglas Gregor // If we're not allowed to infer a framework module, don't. 10099194a91dSDouglas Gregor if (!canInfer) 1010d2d442caSCraig Topper return nullptr; 1011beee15e7SBen Langmuir } else 10129d6448b1SBen Langmuir ModuleMapFile = getModuleMapFileForUniquing(Parent); 10139194a91dSDouglas Gregor 10149194a91dSDouglas Gregor 101556c64013SDouglas Gregor // Look for an umbrella header. 10162c1dd271SDylan Noblesmith SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 101717381a06SBenjamin Kramer llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h"); 101864d8c781SDuncan P. N. Exon Smith auto UmbrellaHeader = FileMgr.getFile(UmbrellaName); 101956c64013SDouglas Gregor 102056c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the 102156c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good 102256c64013SDouglas Gregor // idea. 102356c64013SDouglas Gregor if (!UmbrellaHeader) 1024d2d442caSCraig Topper return nullptr; 102556c64013SDouglas Gregor 10269d6448b1SBen Langmuir Module *Result = new Module(ModuleName, SourceLocation(), Parent, 1027a7e2cc68SRichard Smith /*IsFramework=*/true, /*IsExplicit=*/false, 1028a7e2cc68SRichard Smith NumCreatedModules++); 10299d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = ModuleMapFile; 10309d6448b1SBen Langmuir Result->IsInferred = true; 10317e82e019SRichard Smith if (!Parent) { 10327e82e019SRichard Smith if (LangOpts.CurrentModule == ModuleName) 1033ba7f2f71SDaniel Jasper SourceModule = Result; 10347e82e019SRichard Smith Modules[ModuleName] = Result; 1035c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID; 1036ba7f2f71SDaniel Jasper } 1037c1d88ea5SBen Langmuir 1038c1d88ea5SBen Langmuir Result->IsSystem |= Attrs.IsSystem; 1039c1d88ea5SBen Langmuir Result->IsExternC |= Attrs.IsExternC; 1040c1d88ea5SBen Langmuir Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive; 1041ed84df00SBruno Cardoso Lopes Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes; 10422b63d15fSRichard Smith Result->Directory = FrameworkDir; 1043a686e1b0SDouglas Gregor 1044d3676d4bSMichael Spencer // Chop off the first framework bit, as that is implied. 1045d3676d4bSMichael Spencer StringRef RelativePath = UmbrellaName.str().substr( 1046d3676d4bSMichael Spencer Result->getTopLevelModule()->Directory->getName().size()); 1047d3676d4bSMichael Spencer RelativePath = llvm::sys::path::relative_path(RelativePath); 1048d3676d4bSMichael Spencer 1049322f633cSDouglas Gregor // umbrella header "umbrella-header-name" 1050d3676d4bSMichael Spencer setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h", RelativePath); 1051d8bd7537SDouglas Gregor 1052d8bd7537SDouglas Gregor // export * 1053d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 1054d8bd7537SDouglas Gregor 1055a89c5ac4SDouglas Gregor // module * { export * } 1056a89c5ac4SDouglas Gregor Result->InferSubmodules = true; 1057a89c5ac4SDouglas Gregor Result->InferExportWildcard = true; 1058a89c5ac4SDouglas Gregor 1059e89dbc1dSDouglas Gregor // Look for subframeworks. 1060c080917eSRafael Espindola std::error_code EC; 10612c1dd271SDylan Noblesmith SmallString<128> SubframeworksDirName 1062ddaa69cbSDouglas Gregor = StringRef(FrameworkDir->getName()); 1063e89dbc1dSDouglas Gregor llvm::sys::path::append(SubframeworksDirName, "Frameworks"); 10642d4d8cb3SBenjamin Kramer llvm::sys::path::native(SubframeworksDirName); 1065db8a7422SDuncan P. N. Exon Smith llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); 1066fc51490bSJonas Devlieghere for (llvm::vfs::directory_iterator 1067fc51490bSJonas Devlieghere Dir = FS.dir_begin(SubframeworksDirName, EC), 1068b171a59bSBruno Cardoso Lopes DirEnd; 1069e89dbc1dSDouglas Gregor Dir != DirEnd && !EC; Dir.increment(EC)) { 10700ae00567SSam McCall if (!StringRef(Dir->path()).endswith(".framework")) 1071e89dbc1dSDouglas Gregor continue; 1072f2161a70SDouglas Gregor 10738d323d15SHarlan Haskins if (auto SubframeworkDir = 10740ae00567SSam McCall FileMgr.getDirectory(Dir->path())) { 107507c22b78SDouglas Gregor // Note: as an egregious but useful hack, we use the real path here and 107607c22b78SDouglas Gregor // check whether it is actually a subdirectory of the parent directory. 107707c22b78SDouglas Gregor // This will not be the case if the 'subframework' is actually a symlink 107807c22b78SDouglas Gregor // out to a top-level framework. 10798d323d15SHarlan Haskins StringRef SubframeworkDirName = 10808d323d15SHarlan Haskins FileMgr.getCanonicalName(*SubframeworkDir); 108107c22b78SDouglas Gregor bool FoundParent = false; 108207c22b78SDouglas Gregor do { 108307c22b78SDouglas Gregor // Get the parent directory name. 108407c22b78SDouglas Gregor SubframeworkDirName 108507c22b78SDouglas Gregor = llvm::sys::path::parent_path(SubframeworkDirName); 108607c22b78SDouglas Gregor if (SubframeworkDirName.empty()) 108707c22b78SDouglas Gregor break; 108807c22b78SDouglas Gregor 10898d323d15SHarlan Haskins if (auto SubDir = FileMgr.getDirectory(SubframeworkDirName)) { 10908d323d15SHarlan Haskins if (*SubDir == FrameworkDir) { 109107c22b78SDouglas Gregor FoundParent = true; 109207c22b78SDouglas Gregor break; 109307c22b78SDouglas Gregor } 10948d323d15SHarlan Haskins } 109507c22b78SDouglas Gregor } while (true); 109607c22b78SDouglas Gregor 109707c22b78SDouglas Gregor if (!FoundParent) 109807c22b78SDouglas Gregor continue; 109907c22b78SDouglas Gregor 1100e89dbc1dSDouglas Gregor // FIXME: Do we want to warn about subframeworks without umbrella headers? 11018d323d15SHarlan Haskins inferFrameworkModule(*SubframeworkDir, Attrs, Result); 1102e89dbc1dSDouglas Gregor } 1103e89dbc1dSDouglas Gregor } 1104e89dbc1dSDouglas Gregor 110511dfe6feSDouglas Gregor // If the module is a top-level framework, automatically link against the 110611dfe6feSDouglas Gregor // framework. 110711dfe6feSDouglas Gregor if (!Result->isSubFramework()) { 110811dfe6feSDouglas Gregor inferFrameworkLink(Result, FrameworkDir, FileMgr); 110911dfe6feSDouglas Gregor } 111011dfe6feSDouglas Gregor 111156c64013SDouglas Gregor return Result; 111256c64013SDouglas Gregor } 111356c64013SDouglas Gregor 11148587dfd9SBruno Cardoso Lopes Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework, 11158587dfd9SBruno Cardoso Lopes Module *ShadowingModule) { 11168587dfd9SBruno Cardoso Lopes 11178587dfd9SBruno Cardoso Lopes // Create a new module with this name. 11188587dfd9SBruno Cardoso Lopes Module *Result = 11198587dfd9SBruno Cardoso Lopes new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework, 11208587dfd9SBruno Cardoso Lopes /*IsExplicit=*/false, NumCreatedModules++); 11218587dfd9SBruno Cardoso Lopes Result->ShadowingModule = ShadowingModule; 1122fc76b4adSRichard Smith Result->markUnavailable(/*Unimportable*/true); 1123c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID; 11248587dfd9SBruno Cardoso Lopes ShadowModules.push_back(Result); 11258587dfd9SBruno Cardoso Lopes 11268587dfd9SBruno Cardoso Lopes return Result; 11278587dfd9SBruno Cardoso Lopes } 11288587dfd9SBruno Cardoso Lopes 1129d3676d4bSMichael Spencer void ModuleMap::setUmbrellaHeader( 1130d3676d4bSMichael Spencer Module *Mod, const FileEntry *UmbrellaHeader, const Twine &NameAsWritten, 1131d3676d4bSMichael Spencer const Twine &PathRelativeToRootModuleDirectory) { 113297da9178SDaniel Jasper Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader)); 113364d8c781SDuncan P. N. Exon Smith Mod->Umbrella = UmbrellaHeader; 11342b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 1135d3676d4bSMichael Spencer Mod->UmbrellaRelativeToRootModuleDirectory = 1136d3676d4bSMichael Spencer PathRelativeToRootModuleDirectory.str(); 113764d8c781SDuncan P. N. Exon Smith UmbrellaDirs[UmbrellaHeader->getDir()] = Mod; 1138b3a0fa48SBruno Cardoso Lopes 1139b3a0fa48SBruno Cardoso Lopes // Notify callbacks that we just added a new header. 1140b3a0fa48SBruno Cardoso Lopes for (const auto &Cb : Callbacks) 1141b3a0fa48SBruno Cardoso Lopes Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader); 1142a89c5ac4SDouglas Gregor } 1143a89c5ac4SDouglas Gregor 114464d8c781SDuncan P. N. Exon Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, 1145d3676d4bSMichael Spencer const Twine &NameAsWritten, 1146d3676d4bSMichael Spencer const Twine &PathRelativeToRootModuleDirectory) { 114764d8c781SDuncan P. N. Exon Smith Mod->Umbrella = UmbrellaDir; 11482b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 1149d3676d4bSMichael Spencer Mod->UmbrellaRelativeToRootModuleDirectory = 1150d3676d4bSMichael Spencer PathRelativeToRootModuleDirectory.str(); 1151524e33e1SDouglas Gregor UmbrellaDirs[UmbrellaDir] = Mod; 1152524e33e1SDouglas Gregor } 1153524e33e1SDouglas Gregor 1154040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod, 11559f6020bcSBruno Cardoso Lopes Module::UnresolvedHeaderDirective Header, 11569f6020bcSBruno Cardoso Lopes bool &NeedsFramework) { 1157040e1266SRichard Smith // If there is a builtin counterpart to this file, add it now so it can 1158040e1266SRichard Smith // wrap the system header. 1159040e1266SRichard Smith if (resolveAsBuiltinHeader(Mod, Header)) { 1160040e1266SRichard Smith // If we have both a builtin and system version of the file, the 1161040e1266SRichard Smith // builtin version may want to inject macros into the system header, so 1162040e1266SRichard Smith // force the system header to be treated as a textual header in this 1163040e1266SRichard Smith // case. 1164040e1266SRichard Smith Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole( 1165040e1266SRichard Smith headerKindToRole(Header.Kind) | ModuleMap::TextualHeader)); 1166040e1266SRichard Smith Header.HasBuiltinHeader = true; 11673c1a41adSRichard Smith } 1168040e1266SRichard Smith 1169040e1266SRichard Smith // If possible, don't stat the header until we need to. This requires the 1170040e1266SRichard Smith // user to have provided us with some stat information about the file. 1171040e1266SRichard Smith // FIXME: Add support for lazily stat'ing umbrella headers and excluded 1172040e1266SRichard Smith // headers. 1173040e1266SRichard Smith if ((Header.Size || Header.ModTime) && !Header.IsUmbrella && 1174040e1266SRichard Smith Header.Kind != Module::HK_Excluded) { 1175040e1266SRichard Smith // We expect more variation in mtime than size, so if we're given both, 1176040e1266SRichard Smith // use the mtime as the key. 1177040e1266SRichard Smith if (Header.ModTime) 1178040e1266SRichard Smith LazyHeadersByModTime[*Header.ModTime].push_back(Mod); 1179040e1266SRichard Smith else 1180040e1266SRichard Smith LazyHeadersBySize[*Header.Size].push_back(Mod); 1181040e1266SRichard Smith Mod->UnresolvedHeaders.push_back(Header); 1182040e1266SRichard Smith return; 1183040e1266SRichard Smith } 1184040e1266SRichard Smith 1185040e1266SRichard Smith // We don't have stat information or can't defer looking this file up. 1186040e1266SRichard Smith // Perform the lookup now. 11879f6020bcSBruno Cardoso Lopes resolveHeader(Mod, Header, NeedsFramework); 1188040e1266SRichard Smith } 1189040e1266SRichard Smith 1190040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const { 1191040e1266SRichard Smith auto BySize = LazyHeadersBySize.find(File->getSize()); 1192040e1266SRichard Smith if (BySize != LazyHeadersBySize.end()) { 1193040e1266SRichard Smith for (auto *M : BySize->second) 1194*8f4ea36bSAdam Czachorowski resolveHeaderDirectives(M, File); 1195040e1266SRichard Smith LazyHeadersBySize.erase(BySize); 1196040e1266SRichard Smith } 1197040e1266SRichard Smith 1198040e1266SRichard Smith auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime()); 1199040e1266SRichard Smith if (ByModTime != LazyHeadersByModTime.end()) { 1200040e1266SRichard Smith for (auto *M : ByModTime->second) 1201*8f4ea36bSAdam Czachorowski resolveHeaderDirectives(M, File); 1202040e1266SRichard Smith LazyHeadersByModTime.erase(ByModTime); 1203040e1266SRichard Smith } 1204040e1266SRichard Smith } 1205040e1266SRichard Smith 1206*8f4ea36bSAdam Czachorowski void ModuleMap::resolveHeaderDirectives( 1207*8f4ea36bSAdam Czachorowski Module *Mod, llvm::Optional<const FileEntry *> File) const { 12089f6020bcSBruno Cardoso Lopes bool NeedsFramework = false; 1209*8f4ea36bSAdam Czachorowski SmallVector<Module::UnresolvedHeaderDirective, 1> NewHeaders; 1210*8f4ea36bSAdam Czachorowski const auto Size = File ? File.getValue()->getSize() : 0; 1211*8f4ea36bSAdam Czachorowski const auto ModTime = File ? File.getValue()->getModificationTime() : 0; 1212*8f4ea36bSAdam Czachorowski 1213*8f4ea36bSAdam Czachorowski for (auto &Header : Mod->UnresolvedHeaders) { 1214*8f4ea36bSAdam Czachorowski if (File && ((Header.ModTime && Header.ModTime != ModTime) || 1215*8f4ea36bSAdam Czachorowski (Header.Size && Header.Size != Size))) 1216*8f4ea36bSAdam Czachorowski NewHeaders.push_back(Header); 1217*8f4ea36bSAdam Czachorowski else 1218040e1266SRichard Smith // This operation is logically const; we're just changing how we represent 1219040e1266SRichard Smith // the header information for this file. 12209f6020bcSBruno Cardoso Lopes const_cast<ModuleMap *>(this)->resolveHeader(Mod, Header, NeedsFramework); 1221*8f4ea36bSAdam Czachorowski } 1222*8f4ea36bSAdam Czachorowski Mod->UnresolvedHeaders.swap(NewHeaders); 12230e98d938SNAKAMURA Takumi } 1224202210b3SRichard Smith 12253c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header, 1226d8879c85SRichard Smith ModuleHeaderRole Role, bool Imported) { 1227386bb073SRichard Smith KnownHeader KH(Mod, Role); 12283c1a41adSRichard Smith 1229386bb073SRichard Smith // Only add each header to the headers list once. 1230386bb073SRichard Smith // FIXME: Should we diagnose if a header is listed twice in the 1231386bb073SRichard Smith // same module definition? 1232386bb073SRichard Smith auto &HeaderList = Headers[Header.Entry]; 12337cc8fa2dSKazu Hirata if (llvm::is_contained(HeaderList, KH)) 1234386bb073SRichard Smith return; 1235386bb073SRichard Smith 1236386bb073SRichard Smith HeaderList.push_back(KH); 12371ec383c7SPiotr Padlewski Mod->Headers[headerRoleToKind(Role)].push_back(Header); 1238386bb073SRichard Smith 12397e82e019SRichard Smith bool isCompilingModuleHeader = 1240bbcc9f04SRichard Smith LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule; 1241d8879c85SRichard Smith if (!Imported || isCompilingModuleHeader) { 1242d8879c85SRichard Smith // When we import HeaderFileInfo, the external source is expected to 1243d8879c85SRichard Smith // set the isModuleHeader flag itself. 1244d8879c85SRichard Smith HeaderInfo.MarkFileModuleHeader(Header.Entry, Role, 1245d8879c85SRichard Smith isCompilingModuleHeader); 1246d8879c85SRichard Smith } 1247e62cfd7cSBruno Cardoso Lopes 1248e62cfd7cSBruno Cardoso Lopes // Notify callbacks that we just added a new header. 1249e62cfd7cSBruno Cardoso Lopes for (const auto &Cb : Callbacks) 1250f0841790SBruno Cardoso Lopes Cb->moduleMapAddHeader(Header.Entry->getName()); 1251a89c5ac4SDouglas Gregor } 1252a89c5ac4SDouglas Gregor 12533c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) { 1254feb54b6dSRichard Smith // Add this as a known header so we won't implicitly add it to any 1255feb54b6dSRichard Smith // umbrella directory module. 1256feb54b6dSRichard Smith // FIXME: Should we only exclude it from umbrella modules within the 1257feb54b6dSRichard Smith // specified module? 12583c1a41adSRichard Smith (void) Headers[Header.Entry]; 12593c1a41adSRichard Smith 12603c1a41adSRichard Smith Mod->Headers[Module::HK_Excluded].push_back(std::move(Header)); 1261feb54b6dSRichard Smith } 1262feb54b6dSRichard Smith 1263514b636aSDouglas Gregor const FileEntry * 12644b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const { 12651f76c4e8SManuel Klimek if (Module->DefinitionLoc.isInvalid()) 1266d2d442caSCraig Topper return nullptr; 1267514b636aSDouglas Gregor 12681f76c4e8SManuel Klimek return SourceMgr.getFileEntryForID( 12691f76c4e8SManuel Klimek SourceMgr.getFileID(Module->DefinitionLoc)); 1270514b636aSDouglas Gregor } 1271514b636aSDouglas Gregor 12724b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const { 12739d6448b1SBen Langmuir if (M->IsInferred) { 12749d6448b1SBen Langmuir assert(InferredModuleAllowedBy.count(M) && "missing inferred module map"); 12759d6448b1SBen Langmuir return InferredModuleAllowedBy.find(M)->second; 12769d6448b1SBen Langmuir } 12779d6448b1SBen Langmuir return getContainingModuleMapFile(M); 12789d6448b1SBen Langmuir } 12799d6448b1SBen Langmuir 12809d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) { 12819d6448b1SBen Langmuir assert(M->IsInferred && "module not inferred"); 12829d6448b1SBen Langmuir InferredModuleAllowedBy[M] = ModMap; 12839d6448b1SBen Langmuir } 12849d6448b1SBen Langmuir 1285e08464fbSReid Kleckner void ModuleMap::addAdditionalModuleMapFile(const Module *M, 1286e08464fbSReid Kleckner const FileEntry *ModuleMap) { 1287e08464fbSReid Kleckner AdditionalModMaps[M].insert(ModuleMap); 1288e08464fbSReid Kleckner } 1289e08464fbSReid Kleckner 1290cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() { 1291718292f2SDouglas Gregor llvm::errs() << "Modules:"; 1292718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 1293718292f2SDouglas Gregor MEnd = Modules.end(); 1294718292f2SDouglas Gregor M != MEnd; ++M) 1295d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 1296718292f2SDouglas Gregor 1297718292f2SDouglas Gregor llvm::errs() << "Headers:"; 129859527666SDouglas Gregor for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end(); 1299718292f2SDouglas Gregor H != HEnd; ++H) { 130097da9178SDaniel Jasper llvm::errs() << " \"" << H->first->getName() << "\" -> "; 130197da9178SDaniel Jasper for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(), 130297da9178SDaniel Jasper E = H->second.end(); 130397da9178SDaniel Jasper I != E; ++I) { 130497da9178SDaniel Jasper if (I != H->second.begin()) 130597da9178SDaniel Jasper llvm::errs() << ","; 130697da9178SDaniel Jasper llvm::errs() << I->getModule()->getFullModuleName(); 130797da9178SDaniel Jasper } 130897da9178SDaniel Jasper llvm::errs() << "\n"; 1309718292f2SDouglas Gregor } 1310718292f2SDouglas Gregor } 1311718292f2SDouglas Gregor 13122b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) { 131342413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedExports); 131442413141SRichard Smith Mod->UnresolvedExports.clear(); 131542413141SRichard Smith for (auto &UE : Unresolved) { 131642413141SRichard Smith Module::ExportDecl Export = resolveExport(Mod, UE, Complain); 1317f5eedd05SDouglas Gregor if (Export.getPointer() || Export.getInt()) 13182b82c2a5SDouglas Gregor Mod->Exports.push_back(Export); 13192b82c2a5SDouglas Gregor else 132042413141SRichard Smith Mod->UnresolvedExports.push_back(UE); 13212b82c2a5SDouglas Gregor } 132242413141SRichard Smith return !Mod->UnresolvedExports.empty(); 13232b82c2a5SDouglas Gregor } 13242b82c2a5SDouglas Gregor 1325ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) { 132642413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedDirectUses); 132742413141SRichard Smith Mod->UnresolvedDirectUses.clear(); 132842413141SRichard Smith for (auto &UDU : Unresolved) { 132942413141SRichard Smith Module *DirectUse = resolveModuleId(UDU, Mod, Complain); 1330ba7f2f71SDaniel Jasper if (DirectUse) 1331ba7f2f71SDaniel Jasper Mod->DirectUses.push_back(DirectUse); 1332ba7f2f71SDaniel Jasper else 133342413141SRichard Smith Mod->UnresolvedDirectUses.push_back(UDU); 1334ba7f2f71SDaniel Jasper } 133542413141SRichard Smith return !Mod->UnresolvedDirectUses.empty(); 1336ba7f2f71SDaniel Jasper } 1337ba7f2f71SDaniel Jasper 1338fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) { 133942413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedConflicts); 134042413141SRichard Smith Mod->UnresolvedConflicts.clear(); 134142413141SRichard Smith for (auto &UC : Unresolved) { 134242413141SRichard Smith if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) { 1343fb912657SDouglas Gregor Module::Conflict Conflict; 1344fb912657SDouglas Gregor Conflict.Other = OtherMod; 134542413141SRichard Smith Conflict.Message = UC.Message; 1346fb912657SDouglas Gregor Mod->Conflicts.push_back(Conflict); 134742413141SRichard Smith } else 134842413141SRichard Smith Mod->UnresolvedConflicts.push_back(UC); 1349fb912657SDouglas Gregor } 135042413141SRichard Smith return !Mod->UnresolvedConflicts.empty(); 1351fb912657SDouglas Gregor } 1352fb912657SDouglas Gregor 1353718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1354718292f2SDouglas Gregor // Module map file parser 1355718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1356718292f2SDouglas Gregor 1357718292f2SDouglas Gregor namespace clang { 1358afd1b1c9SEugene Zelenko 13599fc8faf9SAdrian Prantl /// A token in a module map file. 1360718292f2SDouglas Gregor struct MMToken { 1361718292f2SDouglas Gregor enum TokenKind { 13621fb5c3a6SDouglas Gregor Comma, 136335b13eceSDouglas Gregor ConfigMacros, 1364fb912657SDouglas Gregor Conflict, 1365718292f2SDouglas Gregor EndOfFile, 1366718292f2SDouglas Gregor HeaderKeyword, 1367718292f2SDouglas Gregor Identifier, 1368a3feee2aSRichard Smith Exclaim, 136959527666SDouglas Gregor ExcludeKeyword, 1370718292f2SDouglas Gregor ExplicitKeyword, 13712b82c2a5SDouglas Gregor ExportKeyword, 1372f0b11de2SDouglas Gregor ExportAsKeyword, 137397292843SDaniel Jasper ExternKeyword, 1374755b2055SDouglas Gregor FrameworkKeyword, 13756ddfca91SDouglas Gregor LinkKeyword, 1376718292f2SDouglas Gregor ModuleKeyword, 13772b82c2a5SDouglas Gregor Period, 1378b53e5483SLawrence Crowl PrivateKeyword, 1379718292f2SDouglas Gregor UmbrellaKeyword, 1380ba7f2f71SDaniel Jasper UseKeyword, 13811fb5c3a6SDouglas Gregor RequiresKeyword, 13822b82c2a5SDouglas Gregor Star, 1383718292f2SDouglas Gregor StringLiteral, 1384040e1266SRichard Smith IntegerLiteral, 1385306d8920SRichard Smith TextualKeyword, 1386718292f2SDouglas Gregor LBrace, 1387a686e1b0SDouglas Gregor RBrace, 1388a686e1b0SDouglas Gregor LSquare, 1389a686e1b0SDouglas Gregor RSquare 1390718292f2SDouglas Gregor } Kind; 1391718292f2SDouglas Gregor 139221401a72SSimon Tatham SourceLocation::UIntTy Location; 1393718292f2SDouglas Gregor unsigned StringLength; 1394040e1266SRichard Smith union { 1395040e1266SRichard Smith // If Kind != IntegerLiteral. 1396718292f2SDouglas Gregor const char *StringData; 1397afd1b1c9SEugene Zelenko 1398040e1266SRichard Smith // If Kind == IntegerLiteral. 1399040e1266SRichard Smith uint64_t IntegerValue; 1400040e1266SRichard Smith }; 1401718292f2SDouglas Gregor 1402718292f2SDouglas Gregor void clear() { 1403718292f2SDouglas Gregor Kind = EndOfFile; 1404718292f2SDouglas Gregor Location = 0; 1405718292f2SDouglas Gregor StringLength = 0; 1406d2d442caSCraig Topper StringData = nullptr; 1407718292f2SDouglas Gregor } 1408718292f2SDouglas Gregor 1409718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 1410718292f2SDouglas Gregor 1411718292f2SDouglas Gregor SourceLocation getLocation() const { 1412718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 1413718292f2SDouglas Gregor } 1414718292f2SDouglas Gregor 1415040e1266SRichard Smith uint64_t getInteger() const { 1416040e1266SRichard Smith return Kind == IntegerLiteral ? IntegerValue : 0; 1417040e1266SRichard Smith } 1418040e1266SRichard Smith 1419718292f2SDouglas Gregor StringRef getString() const { 1420040e1266SRichard Smith return Kind == IntegerLiteral ? StringRef() 1421040e1266SRichard Smith : StringRef(StringData, StringLength); 1422718292f2SDouglas Gregor } 1423718292f2SDouglas Gregor }; 1424718292f2SDouglas Gregor 1425718292f2SDouglas Gregor class ModuleMapParser { 1426718292f2SDouglas Gregor Lexer &L; 1427718292f2SDouglas Gregor SourceManager &SourceMgr; 1428bc10b9fbSDouglas Gregor 14299fc8faf9SAdrian Prantl /// Default target information, used only for string literal 1430bc10b9fbSDouglas Gregor /// parsing. 1431bc10b9fbSDouglas Gregor const TargetInfo *Target; 1432bc10b9fbSDouglas Gregor 1433718292f2SDouglas Gregor DiagnosticsEngine &Diags; 1434718292f2SDouglas Gregor ModuleMap ⤅ 1435718292f2SDouglas Gregor 14369fc8faf9SAdrian Prantl /// The current module map file. 1437beee15e7SBen Langmuir const FileEntry *ModuleMapFile; 1438beee15e7SBen Langmuir 14399f6020bcSBruno Cardoso Lopes /// Source location of most recent parsed module declaration 14409f6020bcSBruno Cardoso Lopes SourceLocation CurrModuleDeclLoc; 14419f6020bcSBruno Cardoso Lopes 14429fc8faf9SAdrian Prantl /// The directory that file names in this module map file should 14439acb99e3SRichard Smith /// be resolved relative to. 14445257fc63SDouglas Gregor const DirectoryEntry *Directory; 14455257fc63SDouglas Gregor 14469fc8faf9SAdrian Prantl /// Whether this module map is in a system header directory. 1447963c5535SDouglas Gregor bool IsSystem; 1448963c5535SDouglas Gregor 14499fc8faf9SAdrian Prantl /// Whether an error occurred. 1450afd1b1c9SEugene Zelenko bool HadError = false; 1451718292f2SDouglas Gregor 14529fc8faf9SAdrian Prantl /// Stores string data for the various string literals referenced 1453718292f2SDouglas Gregor /// during parsing. 1454718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 1455718292f2SDouglas Gregor 14569fc8faf9SAdrian Prantl /// The current token. 1457718292f2SDouglas Gregor MMToken Tok; 1458718292f2SDouglas Gregor 14599fc8faf9SAdrian Prantl /// The active module. 1460afd1b1c9SEugene Zelenko Module *ActiveModule = nullptr; 1461718292f2SDouglas Gregor 14629fc8faf9SAdrian Prantl /// Whether a module uses the 'requires excluded' hack to mark its 14637ff29148SBen Langmuir /// contents as 'textual'. 14647ff29148SBen Langmuir /// 14657ff29148SBen Langmuir /// On older Darwin SDK versions, 'requires excluded' is used to mark the 14667ff29148SBen Langmuir /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as 14677ff29148SBen Langmuir /// non-modular headers. For backwards compatibility, we continue to 14687ff29148SBen Langmuir /// support this idiom for just these modules, and map the headers to 14697ff29148SBen Langmuir /// 'textual' to match the original intent. 14707ff29148SBen Langmuir llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack; 14717ff29148SBen Langmuir 14729fc8faf9SAdrian Prantl /// Consume the current token and return its location. 1473718292f2SDouglas Gregor SourceLocation consumeToken(); 1474718292f2SDouglas Gregor 14759fc8faf9SAdrian Prantl /// Skip tokens until we reach the a token with the given kind 1476718292f2SDouglas Gregor /// (or the end of the file). 1477718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 1478718292f2SDouglas Gregor 1479afd1b1c9SEugene Zelenko using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>; 1480afd1b1c9SEugene Zelenko 1481e7ab3669SDouglas Gregor bool parseModuleId(ModuleId &Id); 1482718292f2SDouglas Gregor void parseModuleDecl(); 148397292843SDaniel Jasper void parseExternModuleDecl(); 14841fb5c3a6SDouglas Gregor void parseRequiresDecl(); 1485afd1b1c9SEugene Zelenko void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc); 1486524e33e1SDouglas Gregor void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc); 14872b82c2a5SDouglas Gregor void parseExportDecl(); 1488f0b11de2SDouglas Gregor void parseExportAsDecl(); 1489ba7f2f71SDaniel Jasper void parseUseDecl(); 14906ddfca91SDouglas Gregor void parseLinkDecl(); 149135b13eceSDouglas Gregor void parseConfigMacros(); 1492fb912657SDouglas Gregor void parseConflict(); 14939194a91dSDouglas Gregor void parseInferredModuleDecl(bool Framework, bool Explicit); 1494c1d88ea5SBen Langmuir 14955f11e128SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra 14965f11e128SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH 14975f11e128SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written 14985f11e128SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits. 14995f11e128SBruno Cardoso Lopes void diagnosePrivateModules(SourceLocation ExplicitLoc, 15005f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc); 15015f11e128SBruno Cardoso Lopes 1502afd1b1c9SEugene Zelenko using Attributes = ModuleMap::Attributes; 1503afd1b1c9SEugene Zelenko 15044442605fSBill Wendling bool parseOptionalAttributes(Attributes &Attrs); 1505718292f2SDouglas Gregor 1506718292f2SDouglas Gregor public: 1507718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 15088587dfd9SBruno Cardoso Lopes const TargetInfo *Target, DiagnosticsEngine &Diags, 15098587dfd9SBruno Cardoso Lopes ModuleMap &Map, const FileEntry *ModuleMapFile, 1510c192d194SBruno Cardoso Lopes const DirectoryEntry *Directory, bool IsSystem) 1511bc10b9fbSDouglas Gregor : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map), 1512beee15e7SBen Langmuir ModuleMapFile(ModuleMapFile), Directory(Directory), 1513c192d194SBruno Cardoso Lopes IsSystem(IsSystem) { 1514718292f2SDouglas Gregor Tok.clear(); 1515718292f2SDouglas Gregor consumeToken(); 1516718292f2SDouglas Gregor } 1517718292f2SDouglas Gregor 1518718292f2SDouglas Gregor bool parseModuleMapFile(); 15198128f332SRichard Smith 15208128f332SRichard Smith bool terminatedByDirective() { return false; } 15218128f332SRichard Smith SourceLocation getLocation() { return Tok.getLocation(); } 1522718292f2SDouglas Gregor }; 1523afd1b1c9SEugene Zelenko 1524afd1b1c9SEugene Zelenko } // namespace clang 1525718292f2SDouglas Gregor 1526718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 1527718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 1528718292f2SDouglas Gregor 15298128f332SRichard Smith retry: 15308128f332SRichard Smith Tok.clear(); 1531718292f2SDouglas Gregor Token LToken; 1532718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 1533718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 1534718292f2SDouglas Gregor switch (LToken.getKind()) { 15352d57cea2SAlp Toker case tok::raw_identifier: { 15362d57cea2SAlp Toker StringRef RI = LToken.getRawIdentifier(); 15372d57cea2SAlp Toker Tok.StringData = RI.data(); 15382d57cea2SAlp Toker Tok.StringLength = RI.size(); 15392d57cea2SAlp Toker Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI) 154035b13eceSDouglas Gregor .Case("config_macros", MMToken::ConfigMacros) 1541fb912657SDouglas Gregor .Case("conflict", MMToken::Conflict) 154259527666SDouglas Gregor .Case("exclude", MMToken::ExcludeKeyword) 1543718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 15442b82c2a5SDouglas Gregor .Case("export", MMToken::ExportKeyword) 1545f0b11de2SDouglas Gregor .Case("export_as", MMToken::ExportAsKeyword) 154697292843SDaniel Jasper .Case("extern", MMToken::ExternKeyword) 1547755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 154835b13eceSDouglas Gregor .Case("header", MMToken::HeaderKeyword) 15496ddfca91SDouglas Gregor .Case("link", MMToken::LinkKeyword) 1550718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 1551b53e5483SLawrence Crowl .Case("private", MMToken::PrivateKeyword) 15521fb5c3a6SDouglas Gregor .Case("requires", MMToken::RequiresKeyword) 1553306d8920SRichard Smith .Case("textual", MMToken::TextualKeyword) 1554718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 1555ba7f2f71SDaniel Jasper .Case("use", MMToken::UseKeyword) 1556718292f2SDouglas Gregor .Default(MMToken::Identifier); 1557718292f2SDouglas Gregor break; 15582d57cea2SAlp Toker } 1559718292f2SDouglas Gregor 15601fb5c3a6SDouglas Gregor case tok::comma: 15611fb5c3a6SDouglas Gregor Tok.Kind = MMToken::Comma; 15621fb5c3a6SDouglas Gregor break; 15631fb5c3a6SDouglas Gregor 1564718292f2SDouglas Gregor case tok::eof: 1565718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 1566718292f2SDouglas Gregor break; 1567718292f2SDouglas Gregor 1568718292f2SDouglas Gregor case tok::l_brace: 1569718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 1570718292f2SDouglas Gregor break; 1571718292f2SDouglas Gregor 1572a686e1b0SDouglas Gregor case tok::l_square: 1573a686e1b0SDouglas Gregor Tok.Kind = MMToken::LSquare; 1574a686e1b0SDouglas Gregor break; 1575a686e1b0SDouglas Gregor 15762b82c2a5SDouglas Gregor case tok::period: 15772b82c2a5SDouglas Gregor Tok.Kind = MMToken::Period; 15782b82c2a5SDouglas Gregor break; 15792b82c2a5SDouglas Gregor 1580718292f2SDouglas Gregor case tok::r_brace: 1581718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 1582718292f2SDouglas Gregor break; 1583718292f2SDouglas Gregor 1584a686e1b0SDouglas Gregor case tok::r_square: 1585a686e1b0SDouglas Gregor Tok.Kind = MMToken::RSquare; 1586a686e1b0SDouglas Gregor break; 1587a686e1b0SDouglas Gregor 15882b82c2a5SDouglas Gregor case tok::star: 15892b82c2a5SDouglas Gregor Tok.Kind = MMToken::Star; 15902b82c2a5SDouglas Gregor break; 15912b82c2a5SDouglas Gregor 1592a3feee2aSRichard Smith case tok::exclaim: 1593a3feee2aSRichard Smith Tok.Kind = MMToken::Exclaim; 1594a3feee2aSRichard Smith break; 1595a3feee2aSRichard Smith 1596718292f2SDouglas Gregor case tok::string_literal: { 1597d67aea28SRichard Smith if (LToken.hasUDSuffix()) { 1598d67aea28SRichard Smith Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl); 1599d67aea28SRichard Smith HadError = true; 1600d67aea28SRichard Smith goto retry; 1601d67aea28SRichard Smith } 1602d67aea28SRichard Smith 1603718292f2SDouglas Gregor // Parse the string literal. 1604718292f2SDouglas Gregor LangOptions LangOpts; 16059d5583efSCraig Topper StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target); 1606718292f2SDouglas Gregor if (StringLiteral.hadError) 1607718292f2SDouglas Gregor goto retry; 1608718292f2SDouglas Gregor 1609718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 1610718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 1611718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 1612718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 1613718292f2SDouglas Gregor Saved[Length] = 0; 1614718292f2SDouglas Gregor 1615718292f2SDouglas Gregor // Form the token. 1616718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 1617718292f2SDouglas Gregor Tok.StringData = Saved; 1618718292f2SDouglas Gregor Tok.StringLength = Length; 1619718292f2SDouglas Gregor break; 1620718292f2SDouglas Gregor } 1621718292f2SDouglas Gregor 1622040e1266SRichard Smith case tok::numeric_constant: { 1623040e1266SRichard Smith // We don't support any suffixes or other complications. 1624040e1266SRichard Smith SmallString<32> SpellingBuffer; 1625040e1266SRichard Smith SpellingBuffer.resize(LToken.getLength() + 1); 1626040e1266SRichard Smith const char *Start = SpellingBuffer.data(); 1627040e1266SRichard Smith unsigned Length = 1628040e1266SRichard Smith Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts()); 1629040e1266SRichard Smith uint64_t Value; 1630040e1266SRichard Smith if (StringRef(Start, Length).getAsInteger(0, Value)) { 1631040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1632040e1266SRichard Smith HadError = true; 1633040e1266SRichard Smith goto retry; 1634040e1266SRichard Smith } 1635040e1266SRichard Smith 1636040e1266SRichard Smith Tok.Kind = MMToken::IntegerLiteral; 1637040e1266SRichard Smith Tok.IntegerValue = Value; 1638040e1266SRichard Smith break; 1639040e1266SRichard Smith } 1640040e1266SRichard Smith 1641718292f2SDouglas Gregor case tok::comment: 1642718292f2SDouglas Gregor goto retry; 1643718292f2SDouglas Gregor 16448128f332SRichard Smith case tok::hash: 16458128f332SRichard Smith // A module map can be terminated prematurely by 16468128f332SRichard Smith // #pragma clang module contents 16478128f332SRichard Smith // When building the module, we'll treat the rest of the file as the 16488128f332SRichard Smith // contents of the module. 16498128f332SRichard Smith { 16508128f332SRichard Smith auto NextIsIdent = [&](StringRef Str) -> bool { 16518128f332SRichard Smith L.LexFromRawLexer(LToken); 16528128f332SRichard Smith return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) && 16538128f332SRichard Smith LToken.getRawIdentifier() == Str; 16548128f332SRichard Smith }; 16558128f332SRichard Smith if (NextIsIdent("pragma") && NextIsIdent("clang") && 16568128f332SRichard Smith NextIsIdent("module") && NextIsIdent("contents")) { 16578128f332SRichard Smith Tok.Kind = MMToken::EndOfFile; 16588128f332SRichard Smith break; 16598128f332SRichard Smith } 16608128f332SRichard Smith } 16618128f332SRichard Smith LLVM_FALLTHROUGH; 16628128f332SRichard Smith 1663718292f2SDouglas Gregor default: 16648128f332SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1665718292f2SDouglas Gregor HadError = true; 1666718292f2SDouglas Gregor goto retry; 1667718292f2SDouglas Gregor } 1668718292f2SDouglas Gregor 1669718292f2SDouglas Gregor return Result; 1670718292f2SDouglas Gregor } 1671718292f2SDouglas Gregor 1672718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 1673718292f2SDouglas Gregor unsigned braceDepth = 0; 1674a686e1b0SDouglas Gregor unsigned squareDepth = 0; 1675718292f2SDouglas Gregor do { 1676718292f2SDouglas Gregor switch (Tok.Kind) { 1677718292f2SDouglas Gregor case MMToken::EndOfFile: 1678718292f2SDouglas Gregor return; 1679718292f2SDouglas Gregor 1680718292f2SDouglas Gregor case MMToken::LBrace: 1681a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1682718292f2SDouglas Gregor return; 1683718292f2SDouglas Gregor 1684718292f2SDouglas Gregor ++braceDepth; 1685718292f2SDouglas Gregor break; 1686718292f2SDouglas Gregor 1687a686e1b0SDouglas Gregor case MMToken::LSquare: 1688a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1689a686e1b0SDouglas Gregor return; 1690a686e1b0SDouglas Gregor 1691a686e1b0SDouglas Gregor ++squareDepth; 1692a686e1b0SDouglas Gregor break; 1693a686e1b0SDouglas Gregor 1694718292f2SDouglas Gregor case MMToken::RBrace: 1695718292f2SDouglas Gregor if (braceDepth > 0) 1696718292f2SDouglas Gregor --braceDepth; 1697718292f2SDouglas Gregor else if (Tok.is(K)) 1698718292f2SDouglas Gregor return; 1699718292f2SDouglas Gregor break; 1700718292f2SDouglas Gregor 1701a686e1b0SDouglas Gregor case MMToken::RSquare: 1702a686e1b0SDouglas Gregor if (squareDepth > 0) 1703a686e1b0SDouglas Gregor --squareDepth; 1704a686e1b0SDouglas Gregor else if (Tok.is(K)) 1705a686e1b0SDouglas Gregor return; 1706a686e1b0SDouglas Gregor break; 1707a686e1b0SDouglas Gregor 1708718292f2SDouglas Gregor default: 1709a686e1b0SDouglas Gregor if (braceDepth == 0 && squareDepth == 0 && Tok.is(K)) 1710718292f2SDouglas Gregor return; 1711718292f2SDouglas Gregor break; 1712718292f2SDouglas Gregor } 1713718292f2SDouglas Gregor 1714718292f2SDouglas Gregor consumeToken(); 1715718292f2SDouglas Gregor } while (true); 1716718292f2SDouglas Gregor } 1717718292f2SDouglas Gregor 17189fc8faf9SAdrian Prantl /// Parse a module-id. 1719e7ab3669SDouglas Gregor /// 1720e7ab3669SDouglas Gregor /// module-id: 1721e7ab3669SDouglas Gregor /// identifier 1722e7ab3669SDouglas Gregor /// identifier '.' module-id 1723e7ab3669SDouglas Gregor /// 1724e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise. 1725e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) { 1726e7ab3669SDouglas Gregor Id.clear(); 1727e7ab3669SDouglas Gregor do { 17283cd34c76SDaniel Jasper if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) { 1729adcd0268SBenjamin Kramer Id.push_back( 1730adcd0268SBenjamin Kramer std::make_pair(std::string(Tok.getString()), Tok.getLocation())); 1731e7ab3669SDouglas Gregor consumeToken(); 1732e7ab3669SDouglas Gregor } else { 1733e7ab3669SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 1734e7ab3669SDouglas Gregor return true; 1735e7ab3669SDouglas Gregor } 1736e7ab3669SDouglas Gregor 1737e7ab3669SDouglas Gregor if (!Tok.is(MMToken::Period)) 1738e7ab3669SDouglas Gregor break; 1739e7ab3669SDouglas Gregor 1740e7ab3669SDouglas Gregor consumeToken(); 1741e7ab3669SDouglas Gregor } while (true); 1742e7ab3669SDouglas Gregor 1743e7ab3669SDouglas Gregor return false; 1744e7ab3669SDouglas Gregor } 1745e7ab3669SDouglas Gregor 1746a686e1b0SDouglas Gregor namespace { 1747afd1b1c9SEugene Zelenko 17489fc8faf9SAdrian Prantl /// Enumerates the known attributes. 1749a686e1b0SDouglas Gregor enum AttributeKind { 17509fc8faf9SAdrian Prantl /// An unknown attribute. 1751a686e1b0SDouglas Gregor AT_unknown, 1752afd1b1c9SEugene Zelenko 17539fc8faf9SAdrian Prantl /// The 'system' attribute. 175435b13eceSDouglas Gregor AT_system, 1755afd1b1c9SEugene Zelenko 17569fc8faf9SAdrian Prantl /// The 'extern_c' attribute. 175777944868SRichard Smith AT_extern_c, 1758afd1b1c9SEugene Zelenko 17599fc8faf9SAdrian Prantl /// The 'exhaustive' attribute. 1760ed84df00SBruno Cardoso Lopes AT_exhaustive, 1761afd1b1c9SEugene Zelenko 17629fc8faf9SAdrian Prantl /// The 'no_undeclared_includes' attribute. 1763ed84df00SBruno Cardoso Lopes AT_no_undeclared_includes 1764a686e1b0SDouglas Gregor }; 1765afd1b1c9SEugene Zelenko 1766afd1b1c9SEugene Zelenko } // namespace 1767a686e1b0SDouglas Gregor 176829729919SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra 176929729919SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH 177029729919SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written 177129729919SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits. 17725f11e128SBruno Cardoso Lopes void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc, 17735f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc) { 177429729919SBruno Cardoso Lopes auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical, 17757d29486dSBruno Cardoso Lopes const Module *M, SourceRange ReplLoc) { 177629729919SBruno Cardoso Lopes auto D = Diags.Report(ActiveModule->DefinitionLoc, 177729729919SBruno Cardoso Lopes diag::note_mmap_rename_top_level_private_module); 177829729919SBruno Cardoso Lopes D << BadName << M->Name; 17797d29486dSBruno Cardoso Lopes D << FixItHint::CreateReplacement(ReplLoc, Canonical); 178029729919SBruno Cardoso Lopes }; 178129729919SBruno Cardoso Lopes 178229729919SBruno Cardoso Lopes for (auto E = Map.module_begin(); E != Map.module_end(); ++E) { 178329729919SBruno Cardoso Lopes auto const *M = E->getValue(); 178429729919SBruno Cardoso Lopes if (M->Directory != ActiveModule->Directory) 178529729919SBruno Cardoso Lopes continue; 178629729919SBruno Cardoso Lopes 178729729919SBruno Cardoso Lopes SmallString<128> FullName(ActiveModule->getFullModuleName()); 178829729919SBruno Cardoso Lopes if (!FullName.startswith(M->Name) && !FullName.endswith("Private")) 178929729919SBruno Cardoso Lopes continue; 17905f11e128SBruno Cardoso Lopes SmallString<128> FixedPrivModDecl; 179129729919SBruno Cardoso Lopes SmallString<128> Canonical(M->Name); 179229729919SBruno Cardoso Lopes Canonical.append("_Private"); 179329729919SBruno Cardoso Lopes 179429729919SBruno Cardoso Lopes // Foo.Private -> Foo_Private 179529729919SBruno Cardoso Lopes if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent && 179629729919SBruno Cardoso Lopes M->Name == ActiveModule->Parent->Name) { 179729729919SBruno Cardoso Lopes Diags.Report(ActiveModule->DefinitionLoc, 179829729919SBruno Cardoso Lopes diag::warn_mmap_mismatched_private_submodule) 179929729919SBruno Cardoso Lopes << FullName; 18005f11e128SBruno Cardoso Lopes 18015f11e128SBruno Cardoso Lopes SourceLocation FixItInitBegin = CurrModuleDeclLoc; 18025f11e128SBruno Cardoso Lopes if (FrameworkLoc.isValid()) 18035f11e128SBruno Cardoso Lopes FixItInitBegin = FrameworkLoc; 18045f11e128SBruno Cardoso Lopes if (ExplicitLoc.isValid()) 18055f11e128SBruno Cardoso Lopes FixItInitBegin = ExplicitLoc; 18065f11e128SBruno Cardoso Lopes 18075f11e128SBruno Cardoso Lopes if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework) 18085f11e128SBruno Cardoso Lopes FixedPrivModDecl.append("framework "); 18095f11e128SBruno Cardoso Lopes FixedPrivModDecl.append("module "); 18105f11e128SBruno Cardoso Lopes FixedPrivModDecl.append(Canonical); 18115f11e128SBruno Cardoso Lopes 18125f11e128SBruno Cardoso Lopes GenNoteAndFixIt(FullName, FixedPrivModDecl, M, 18135f11e128SBruno Cardoso Lopes SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc)); 181429729919SBruno Cardoso Lopes continue; 181529729919SBruno Cardoso Lopes } 181629729919SBruno Cardoso Lopes 181729729919SBruno Cardoso Lopes // FooPrivate and whatnots -> Foo_Private 181829729919SBruno Cardoso Lopes if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name && 181929729919SBruno Cardoso Lopes ActiveModule->Name != Canonical) { 182029729919SBruno Cardoso Lopes Diags.Report(ActiveModule->DefinitionLoc, 182129729919SBruno Cardoso Lopes diag::warn_mmap_mismatched_private_module_name) 182229729919SBruno Cardoso Lopes << ActiveModule->Name; 18237d29486dSBruno Cardoso Lopes GenNoteAndFixIt(ActiveModule->Name, Canonical, M, 18247d29486dSBruno Cardoso Lopes SourceRange(ActiveModule->DefinitionLoc)); 182529729919SBruno Cardoso Lopes } 182629729919SBruno Cardoso Lopes } 182729729919SBruno Cardoso Lopes } 182829729919SBruno Cardoso Lopes 18299fc8faf9SAdrian Prantl /// Parse a module declaration. 1830718292f2SDouglas Gregor /// 1831718292f2SDouglas Gregor /// module-declaration: 183297292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 1833a686e1b0SDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt] 1834a686e1b0SDouglas Gregor /// { module-member* } 1835a686e1b0SDouglas Gregor /// 1836718292f2SDouglas Gregor /// module-member: 18371fb5c3a6SDouglas Gregor /// requires-declaration 1838718292f2SDouglas Gregor /// header-declaration 1839e7ab3669SDouglas Gregor /// submodule-declaration 18402b82c2a5SDouglas Gregor /// export-declaration 1841f0b11de2SDouglas Gregor /// export-as-declaration 18426ddfca91SDouglas Gregor /// link-declaration 184373441091SDouglas Gregor /// 184473441091SDouglas Gregor /// submodule-declaration: 184573441091SDouglas Gregor /// module-declaration 184673441091SDouglas Gregor /// inferred-submodule-declaration 1847718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 1848755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 184997292843SDaniel Jasper Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword)); 185097292843SDaniel Jasper if (Tok.is(MMToken::ExternKeyword)) { 185197292843SDaniel Jasper parseExternModuleDecl(); 185297292843SDaniel Jasper return; 185397292843SDaniel Jasper } 185497292843SDaniel Jasper 1855f2161a70SDouglas Gregor // Parse 'explicit' or 'framework' keyword, if present. 1856e7ab3669SDouglas Gregor SourceLocation ExplicitLoc; 18575f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc; 1858718292f2SDouglas Gregor bool Explicit = false; 1859f2161a70SDouglas Gregor bool Framework = false; 1860755b2055SDouglas Gregor 1861f2161a70SDouglas Gregor // Parse 'explicit' keyword, if present. 1862f2161a70SDouglas Gregor if (Tok.is(MMToken::ExplicitKeyword)) { 1863e7ab3669SDouglas Gregor ExplicitLoc = consumeToken(); 1864f2161a70SDouglas Gregor Explicit = true; 1865f2161a70SDouglas Gregor } 1866f2161a70SDouglas Gregor 1867f2161a70SDouglas Gregor // Parse 'framework' keyword, if present. 1868755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 18695f11e128SBruno Cardoso Lopes FrameworkLoc = consumeToken(); 1870755b2055SDouglas Gregor Framework = true; 1871755b2055SDouglas Gregor } 1872718292f2SDouglas Gregor 1873718292f2SDouglas Gregor // Parse 'module' keyword. 1874718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 1875d6343c99SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 1876718292f2SDouglas Gregor consumeToken(); 1877718292f2SDouglas Gregor HadError = true; 1878718292f2SDouglas Gregor return; 1879718292f2SDouglas Gregor } 18809f6020bcSBruno Cardoso Lopes CurrModuleDeclLoc = consumeToken(); // 'module' keyword 1881718292f2SDouglas Gregor 188273441091SDouglas Gregor // If we have a wildcard for the module name, this is an inferred submodule. 188373441091SDouglas Gregor // Parse it. 188473441091SDouglas Gregor if (Tok.is(MMToken::Star)) 18859194a91dSDouglas Gregor return parseInferredModuleDecl(Framework, Explicit); 188673441091SDouglas Gregor 1887718292f2SDouglas Gregor // Parse the module name. 1888e7ab3669SDouglas Gregor ModuleId Id; 1889e7ab3669SDouglas Gregor if (parseModuleId(Id)) { 1890718292f2SDouglas Gregor HadError = true; 1891718292f2SDouglas Gregor return; 1892718292f2SDouglas Gregor } 1893e7ab3669SDouglas Gregor 1894e7ab3669SDouglas Gregor if (ActiveModule) { 1895e7ab3669SDouglas Gregor if (Id.size() > 1) { 1896e7ab3669SDouglas Gregor Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id) 1897e7ab3669SDouglas Gregor << SourceRange(Id.front().second, Id.back().second); 1898e7ab3669SDouglas Gregor 1899e7ab3669SDouglas Gregor HadError = true; 1900e7ab3669SDouglas Gregor return; 1901e7ab3669SDouglas Gregor } 1902e7ab3669SDouglas Gregor } else if (Id.size() == 1 && Explicit) { 1903e7ab3669SDouglas Gregor // Top-level modules can't be explicit. 1904e7ab3669SDouglas Gregor Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level); 1905e7ab3669SDouglas Gregor Explicit = false; 1906e7ab3669SDouglas Gregor ExplicitLoc = SourceLocation(); 1907e7ab3669SDouglas Gregor HadError = true; 1908e7ab3669SDouglas Gregor } 1909e7ab3669SDouglas Gregor 1910e7ab3669SDouglas Gregor Module *PreviousActiveModule = ActiveModule; 1911e7ab3669SDouglas Gregor if (Id.size() > 1) { 1912e7ab3669SDouglas Gregor // This module map defines a submodule. Go find the module of which it 1913e7ab3669SDouglas Gregor // is a submodule. 1914d2d442caSCraig Topper ActiveModule = nullptr; 19154b8a9e95SBen Langmuir const Module *TopLevelModule = nullptr; 1916e7ab3669SDouglas Gregor for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) { 1917e7ab3669SDouglas Gregor if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) { 19184b8a9e95SBen Langmuir if (I == 0) 19194b8a9e95SBen Langmuir TopLevelModule = Next; 1920e7ab3669SDouglas Gregor ActiveModule = Next; 1921e7ab3669SDouglas Gregor continue; 1922e7ab3669SDouglas Gregor } 1923e7ab3669SDouglas Gregor 19248839e278SVolodymyr Sapsai Diags.Report(Id[I].second, diag::err_mmap_missing_parent_module) 19258839e278SVolodymyr Sapsai << Id[I].first << (ActiveModule != nullptr) 19268839e278SVolodymyr Sapsai << (ActiveModule 19278839e278SVolodymyr Sapsai ? ActiveModule->getTopLevelModule()->getFullModuleName() 19288839e278SVolodymyr Sapsai : ""); 1929e7ab3669SDouglas Gregor HadError = true; 1930e7ab3669SDouglas Gregor } 19314b8a9e95SBen Langmuir 19328839e278SVolodymyr Sapsai if (TopLevelModule && 19338839e278SVolodymyr Sapsai ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) { 19344b8a9e95SBen Langmuir assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) && 19354b8a9e95SBen Langmuir "submodule defined in same file as 'module *' that allowed its " 19364b8a9e95SBen Langmuir "top-level module"); 19374b8a9e95SBen Langmuir Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile); 19384b8a9e95SBen Langmuir } 1939e7ab3669SDouglas Gregor } 1940e7ab3669SDouglas Gregor 1941e7ab3669SDouglas Gregor StringRef ModuleName = Id.back().first; 1942e7ab3669SDouglas Gregor SourceLocation ModuleNameLoc = Id.back().second; 1943718292f2SDouglas Gregor 1944a686e1b0SDouglas Gregor // Parse the optional attribute list. 19454442605fSBill Wendling Attributes Attrs; 19465d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 19475d29dee0SDavide Italiano return; 19485d29dee0SDavide Italiano 1949718292f2SDouglas Gregor // Parse the opening brace. 1950718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 1951718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 1952718292f2SDouglas Gregor << ModuleName; 1953718292f2SDouglas Gregor HadError = true; 1954718292f2SDouglas Gregor return; 1955718292f2SDouglas Gregor } 1956718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 1957718292f2SDouglas Gregor 1958718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 19598587dfd9SBruno Cardoso Lopes Module *ShadowingModule = nullptr; 1960eb90e830SDouglas Gregor if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { 19614a3751ffSRichard Smith // We might see a (re)definition of a module that we already have a 19624a3751ffSRichard Smith // definition for in two cases: 19634a3751ffSRichard Smith // - If we loaded one definition from an AST file and we've just found a 19644a3751ffSRichard Smith // corresponding definition in a module map file, or 19654a3751ffSRichard Smith bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid(); 19664a3751ffSRichard Smith // - If we're building a (preprocessed) module and we've just loaded the 19674a3751ffSRichard Smith // module map file from which it was created. 19684a3751ffSRichard Smith bool ParsedAsMainInput = 19694a3751ffSRichard Smith Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap && 19704a3751ffSRichard Smith Map.LangOpts.CurrentModule == ModuleName && 19714a3751ffSRichard Smith SourceMgr.getDecomposedLoc(ModuleNameLoc).first != 19724a3751ffSRichard Smith SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first; 19734a3751ffSRichard Smith if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) { 1974fcc54a3bSDouglas Gregor // Skip the module definition. 1975fcc54a3bSDouglas Gregor skipUntil(MMToken::RBrace); 1976fcc54a3bSDouglas Gregor if (Tok.is(MMToken::RBrace)) 1977fcc54a3bSDouglas Gregor consumeToken(); 1978fcc54a3bSDouglas Gregor else { 1979fcc54a3bSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 1980fcc54a3bSDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 1981fcc54a3bSDouglas Gregor HadError = true; 1982fcc54a3bSDouglas Gregor } 1983fcc54a3bSDouglas Gregor return; 1984fcc54a3bSDouglas Gregor } 1985fcc54a3bSDouglas Gregor 1986c192d194SBruno Cardoso Lopes if (!Existing->Parent && Map.mayShadowNewModule(Existing)) { 19878587dfd9SBruno Cardoso Lopes ShadowingModule = Existing; 19888587dfd9SBruno Cardoso Lopes } else { 19898587dfd9SBruno Cardoso Lopes // This is not a shawdowed module decl, it is an illegal redefinition. 1990718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 1991718292f2SDouglas Gregor << ModuleName; 1992eb90e830SDouglas Gregor Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition); 1993718292f2SDouglas Gregor 1994718292f2SDouglas Gregor // Skip the module definition. 1995718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 1996718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 1997718292f2SDouglas Gregor consumeToken(); 1998718292f2SDouglas Gregor 1999718292f2SDouglas Gregor HadError = true; 2000718292f2SDouglas Gregor return; 2001718292f2SDouglas Gregor } 20028587dfd9SBruno Cardoso Lopes } 2003718292f2SDouglas Gregor 2004718292f2SDouglas Gregor // Start defining this module. 20058587dfd9SBruno Cardoso Lopes if (ShadowingModule) { 20068587dfd9SBruno Cardoso Lopes ActiveModule = 20078587dfd9SBruno Cardoso Lopes Map.createShadowedModule(ModuleName, Framework, ShadowingModule); 20088587dfd9SBruno Cardoso Lopes } else { 2009c192d194SBruno Cardoso Lopes ActiveModule = 2010c192d194SBruno Cardoso Lopes Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit) 20118587dfd9SBruno Cardoso Lopes .first; 20128587dfd9SBruno Cardoso Lopes } 20138587dfd9SBruno Cardoso Lopes 2014eb90e830SDouglas Gregor ActiveModule->DefinitionLoc = ModuleNameLoc; 2015963c5535SDouglas Gregor if (Attrs.IsSystem || IsSystem) 2016a686e1b0SDouglas Gregor ActiveModule->IsSystem = true; 201777944868SRichard Smith if (Attrs.IsExternC) 201877944868SRichard Smith ActiveModule->IsExternC = true; 2019ed84df00SBruno Cardoso Lopes if (Attrs.NoUndeclaredIncludes || 2020ed84df00SBruno Cardoso Lopes (!ActiveModule->Parent && ModuleName == "Darwin")) 2021ed84df00SBruno Cardoso Lopes ActiveModule->NoUndeclaredIncludes = true; 20223c1a41adSRichard Smith ActiveModule->Directory = Directory; 2023718292f2SDouglas Gregor 202490b0a1fcSJordan Rose StringRef MapFileName(ModuleMapFile->getName()); 202590b0a1fcSJordan Rose if (MapFileName.endswith("module.private.modulemap") || 202690b0a1fcSJordan Rose MapFileName.endswith("module_private.map")) { 202790b0a1fcSJordan Rose ActiveModule->ModuleMapIsPrivate = true; 202890b0a1fcSJordan Rose } 202929729919SBruno Cardoso Lopes 203029729919SBruno Cardoso Lopes // Private modules named as FooPrivate, Foo.Private or similar are likely a 203129729919SBruno Cardoso Lopes // user error; provide warnings, notes and fixits to direct users to use 203229729919SBruno Cardoso Lopes // Foo_Private instead. 203329729919SBruno Cardoso Lopes SourceLocation StartLoc = 203429729919SBruno Cardoso Lopes SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()); 203529729919SBruno Cardoso Lopes if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && 203629729919SBruno Cardoso Lopes !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule, 203729729919SBruno Cardoso Lopes StartLoc) && 203829729919SBruno Cardoso Lopes !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name, 203929729919SBruno Cardoso Lopes StartLoc) && 204090b0a1fcSJordan Rose ActiveModule->ModuleMapIsPrivate) 20415f11e128SBruno Cardoso Lopes diagnosePrivateModules(ExplicitLoc, FrameworkLoc); 20424d867640SGraydon Hoare 2043718292f2SDouglas Gregor bool Done = false; 2044718292f2SDouglas Gregor do { 2045718292f2SDouglas Gregor switch (Tok.Kind) { 2046718292f2SDouglas Gregor case MMToken::EndOfFile: 2047718292f2SDouglas Gregor case MMToken::RBrace: 2048718292f2SDouglas Gregor Done = true; 2049718292f2SDouglas Gregor break; 2050718292f2SDouglas Gregor 205135b13eceSDouglas Gregor case MMToken::ConfigMacros: 205235b13eceSDouglas Gregor parseConfigMacros(); 205335b13eceSDouglas Gregor break; 205435b13eceSDouglas Gregor 2055fb912657SDouglas Gregor case MMToken::Conflict: 2056fb912657SDouglas Gregor parseConflict(); 2057fb912657SDouglas Gregor break; 2058fb912657SDouglas Gregor 2059718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 206097292843SDaniel Jasper case MMToken::ExternKeyword: 2061f2161a70SDouglas Gregor case MMToken::FrameworkKeyword: 2062718292f2SDouglas Gregor case MMToken::ModuleKeyword: 2063718292f2SDouglas Gregor parseModuleDecl(); 2064718292f2SDouglas Gregor break; 2065718292f2SDouglas Gregor 20662b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 20672b82c2a5SDouglas Gregor parseExportDecl(); 20682b82c2a5SDouglas Gregor break; 20692b82c2a5SDouglas Gregor 2070f0b11de2SDouglas Gregor case MMToken::ExportAsKeyword: 2071f0b11de2SDouglas Gregor parseExportAsDecl(); 2072f0b11de2SDouglas Gregor break; 2073f0b11de2SDouglas Gregor 2074ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 2075ba7f2f71SDaniel Jasper parseUseDecl(); 2076ba7f2f71SDaniel Jasper break; 2077ba7f2f71SDaniel Jasper 20781fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 20791fb5c3a6SDouglas Gregor parseRequiresDecl(); 20801fb5c3a6SDouglas Gregor break; 20811fb5c3a6SDouglas Gregor 2082202210b3SRichard Smith case MMToken::TextualKeyword: 2083202210b3SRichard Smith parseHeaderDecl(MMToken::TextualKeyword, consumeToken()); 2084306d8920SRichard Smith break; 2085306d8920SRichard Smith 2086524e33e1SDouglas Gregor case MMToken::UmbrellaKeyword: { 2087524e33e1SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 2088524e33e1SDouglas Gregor if (Tok.is(MMToken::HeaderKeyword)) 2089b53e5483SLawrence Crowl parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc); 2090524e33e1SDouglas Gregor else 2091524e33e1SDouglas Gregor parseUmbrellaDirDecl(UmbrellaLoc); 2092718292f2SDouglas Gregor break; 2093524e33e1SDouglas Gregor } 2094718292f2SDouglas Gregor 2095202210b3SRichard Smith case MMToken::ExcludeKeyword: 2096202210b3SRichard Smith parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken()); 209759527666SDouglas Gregor break; 209859527666SDouglas Gregor 2099202210b3SRichard Smith case MMToken::PrivateKeyword: 2100202210b3SRichard Smith parseHeaderDecl(MMToken::PrivateKeyword, consumeToken()); 2101b53e5483SLawrence Crowl break; 2102b53e5483SLawrence Crowl 2103322f633cSDouglas Gregor case MMToken::HeaderKeyword: 2104202210b3SRichard Smith parseHeaderDecl(MMToken::HeaderKeyword, consumeToken()); 2105718292f2SDouglas Gregor break; 2106718292f2SDouglas Gregor 21076ddfca91SDouglas Gregor case MMToken::LinkKeyword: 21086ddfca91SDouglas Gregor parseLinkDecl(); 21096ddfca91SDouglas Gregor break; 21106ddfca91SDouglas Gregor 2111718292f2SDouglas Gregor default: 2112718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 2113718292f2SDouglas Gregor consumeToken(); 2114718292f2SDouglas Gregor break; 2115718292f2SDouglas Gregor } 2116718292f2SDouglas Gregor } while (!Done); 2117718292f2SDouglas Gregor 2118718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 2119718292f2SDouglas Gregor consumeToken(); 2120718292f2SDouglas Gregor else { 2121718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 2122718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 2123718292f2SDouglas Gregor HadError = true; 2124718292f2SDouglas Gregor } 2125718292f2SDouglas Gregor 212611dfe6feSDouglas Gregor // If the active module is a top-level framework, and there are no link 212711dfe6feSDouglas Gregor // libraries, automatically link against the framework. 212811dfe6feSDouglas Gregor if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() && 212911dfe6feSDouglas Gregor ActiveModule->LinkLibraries.empty()) { 213011dfe6feSDouglas Gregor inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager()); 213111dfe6feSDouglas Gregor } 213211dfe6feSDouglas Gregor 2133ec8c9752SBen Langmuir // If the module meets all requirements but is still unavailable, mark the 2134ec8c9752SBen Langmuir // whole tree as unavailable to prevent it from building. 2135fc76b4adSRichard Smith if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable && 2136ec8c9752SBen Langmuir ActiveModule->Parent) { 2137fc76b4adSRichard Smith ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false); 2138ec8c9752SBen Langmuir ActiveModule->getTopLevelModule()->MissingHeaders.append( 2139ec8c9752SBen Langmuir ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end()); 2140ec8c9752SBen Langmuir } 2141ec8c9752SBen Langmuir 2142e7ab3669SDouglas Gregor // We're done parsing this module. Pop back to the previous module. 2143e7ab3669SDouglas Gregor ActiveModule = PreviousActiveModule; 2144718292f2SDouglas Gregor } 2145718292f2SDouglas Gregor 21469fc8faf9SAdrian Prantl /// Parse an extern module declaration. 214797292843SDaniel Jasper /// 214897292843SDaniel Jasper /// extern module-declaration: 214997292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 215097292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() { 215197292843SDaniel Jasper assert(Tok.is(MMToken::ExternKeyword)); 2152ae6df27eSRichard Smith SourceLocation ExternLoc = consumeToken(); // 'extern' keyword 215397292843SDaniel Jasper 215497292843SDaniel Jasper // Parse 'module' keyword. 215597292843SDaniel Jasper if (!Tok.is(MMToken::ModuleKeyword)) { 215697292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 215797292843SDaniel Jasper consumeToken(); 215897292843SDaniel Jasper HadError = true; 215997292843SDaniel Jasper return; 216097292843SDaniel Jasper } 216197292843SDaniel Jasper consumeToken(); // 'module' keyword 216297292843SDaniel Jasper 216397292843SDaniel Jasper // Parse the module name. 216497292843SDaniel Jasper ModuleId Id; 216597292843SDaniel Jasper if (parseModuleId(Id)) { 216697292843SDaniel Jasper HadError = true; 216797292843SDaniel Jasper return; 216897292843SDaniel Jasper } 216997292843SDaniel Jasper 217097292843SDaniel Jasper // Parse the referenced module map file name. 217197292843SDaniel Jasper if (!Tok.is(MMToken::StringLiteral)) { 217297292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file); 217397292843SDaniel Jasper HadError = true; 217497292843SDaniel Jasper return; 217597292843SDaniel Jasper } 2176adcd0268SBenjamin Kramer std::string FileName = std::string(Tok.getString()); 217797292843SDaniel Jasper consumeToken(); // filename 217897292843SDaniel Jasper 217997292843SDaniel Jasper StringRef FileNameRef = FileName; 218097292843SDaniel Jasper SmallString<128> ModuleMapFileName; 218197292843SDaniel Jasper if (llvm::sys::path::is_relative(FileNameRef)) { 218297292843SDaniel Jasper ModuleMapFileName += Directory->getName(); 218397292843SDaniel Jasper llvm::sys::path::append(ModuleMapFileName, FileName); 218492e1b62dSYaron Keren FileNameRef = ModuleMapFileName; 218597292843SDaniel Jasper } 21867799ef71SNico Weber if (auto File = SourceMgr.getFileManager().getFile(FileNameRef)) 21879acb99e3SRichard Smith Map.parseModuleMapFile( 2188d0e7bdc2SVolodymyr Sapsai *File, IsSystem, 21899acb99e3SRichard Smith Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd 21909acb99e3SRichard Smith ? Directory 21917799ef71SNico Weber : (*File)->getDir(), 2192c192d194SBruno Cardoso Lopes FileID(), nullptr, ExternLoc); 219397292843SDaniel Jasper } 219497292843SDaniel Jasper 21957ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M. 21967ff29148SBen Langmuir /// 21977ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system 21987ff29148SBen Langmuir /// module map files: 21997ff29148SBen Langmuir /// 22007ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which 22017ff29148SBen Langmuir /// should really be mapped to 'textual' now that we have this feature. We 22027ff29148SBen Langmuir /// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to 22037ff29148SBen Langmuir /// true. Later, this bit will be used to map all the headers inside this 22047ff29148SBen Langmuir /// module to 'textual'. 22057ff29148SBen Langmuir /// 22067ff29148SBen Langmuir /// This affects Darwin.C.excluded (for assert.h) and Tcl.Private. 22077ff29148SBen Langmuir /// 22087ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement 22097ff29148SBen Langmuir /// was never correct and causes issues now that we check it, so drop it. 22107ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature, 22117ff29148SBen Langmuir bool &IsRequiresExcludedHack) { 22128013e81dSBenjamin Kramer if (Feature == "excluded" && 22138013e81dSBenjamin Kramer (M->fullModuleNameIs({"Darwin", "C", "excluded"}) || 22148013e81dSBenjamin Kramer M->fullModuleNameIs({"Tcl", "Private"}))) { 22157ff29148SBen Langmuir IsRequiresExcludedHack = true; 22167ff29148SBen Langmuir return false; 22178013e81dSBenjamin Kramer } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) { 22187ff29148SBen Langmuir return false; 22197ff29148SBen Langmuir } 22207ff29148SBen Langmuir 22217ff29148SBen Langmuir return true; 22227ff29148SBen Langmuir } 22237ff29148SBen Langmuir 22249fc8faf9SAdrian Prantl /// Parse a requires declaration. 22251fb5c3a6SDouglas Gregor /// 22261fb5c3a6SDouglas Gregor /// requires-declaration: 22271fb5c3a6SDouglas Gregor /// 'requires' feature-list 22281fb5c3a6SDouglas Gregor /// 22291fb5c3a6SDouglas Gregor /// feature-list: 2230a3feee2aSRichard Smith /// feature ',' feature-list 2231a3feee2aSRichard Smith /// feature 2232a3feee2aSRichard Smith /// 2233a3feee2aSRichard Smith /// feature: 2234a3feee2aSRichard Smith /// '!'[opt] identifier 22351fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() { 22361fb5c3a6SDouglas Gregor assert(Tok.is(MMToken::RequiresKeyword)); 22371fb5c3a6SDouglas Gregor 22381fb5c3a6SDouglas Gregor // Parse 'requires' keyword. 22391fb5c3a6SDouglas Gregor consumeToken(); 22401fb5c3a6SDouglas Gregor 22411fb5c3a6SDouglas Gregor // Parse the feature-list. 22421fb5c3a6SDouglas Gregor do { 2243a3feee2aSRichard Smith bool RequiredState = true; 2244a3feee2aSRichard Smith if (Tok.is(MMToken::Exclaim)) { 2245a3feee2aSRichard Smith RequiredState = false; 2246a3feee2aSRichard Smith consumeToken(); 2247a3feee2aSRichard Smith } 2248a3feee2aSRichard Smith 22491fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 22501fb5c3a6SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature); 22511fb5c3a6SDouglas Gregor HadError = true; 22521fb5c3a6SDouglas Gregor return; 22531fb5c3a6SDouglas Gregor } 22541fb5c3a6SDouglas Gregor 22551fb5c3a6SDouglas Gregor // Consume the feature name. 2256adcd0268SBenjamin Kramer std::string Feature = std::string(Tok.getString()); 22571fb5c3a6SDouglas Gregor consumeToken(); 22581fb5c3a6SDouglas Gregor 22597ff29148SBen Langmuir bool IsRequiresExcludedHack = false; 22607ff29148SBen Langmuir bool ShouldAddRequirement = 22617ff29148SBen Langmuir shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack); 22627ff29148SBen Langmuir 22637ff29148SBen Langmuir if (IsRequiresExcludedHack) 22647ff29148SBen Langmuir UsesRequiresExcludedHack.insert(ActiveModule); 22657ff29148SBen Langmuir 22667ff29148SBen Langmuir if (ShouldAddRequirement) { 22671fb5c3a6SDouglas Gregor // Add this feature. 22687ff29148SBen Langmuir ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts, 22697ff29148SBen Langmuir *Map.Target); 22707ff29148SBen Langmuir } 22711fb5c3a6SDouglas Gregor 22721fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Comma)) 22731fb5c3a6SDouglas Gregor break; 22741fb5c3a6SDouglas Gregor 22751fb5c3a6SDouglas Gregor // Consume the comma. 22761fb5c3a6SDouglas Gregor consumeToken(); 22771fb5c3a6SDouglas Gregor } while (true); 22781fb5c3a6SDouglas Gregor } 22791fb5c3a6SDouglas Gregor 22809fc8faf9SAdrian Prantl /// Parse a header declaration. 2281718292f2SDouglas Gregor /// 2282718292f2SDouglas Gregor /// header-declaration: 2283306d8920SRichard Smith /// 'textual'[opt] 'header' string-literal 2284202210b3SRichard Smith /// 'private' 'textual'[opt] 'header' string-literal 2285202210b3SRichard Smith /// 'exclude' 'header' string-literal 2286202210b3SRichard Smith /// 'umbrella' 'header' string-literal 2287306d8920SRichard Smith /// 2288306d8920SRichard Smith /// FIXME: Support 'private textual header'. 2289b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, 2290b53e5483SLawrence Crowl SourceLocation LeadingLoc) { 2291202210b3SRichard Smith // We've already consumed the first token. 2292202210b3SRichard Smith ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader; 2293202210b3SRichard Smith if (LeadingToken == MMToken::PrivateKeyword) { 2294202210b3SRichard Smith Role = ModuleMap::PrivateHeader; 2295202210b3SRichard Smith // 'private' may optionally be followed by 'textual'. 2296202210b3SRichard Smith if (Tok.is(MMToken::TextualKeyword)) { 2297202210b3SRichard Smith LeadingToken = Tok.Kind; 22981871ed3dSBenjamin Kramer consumeToken(); 2299202210b3SRichard Smith } 2300202210b3SRichard Smith } 23017ff29148SBen Langmuir 2302202210b3SRichard Smith if (LeadingToken == MMToken::TextualKeyword) 2303202210b3SRichard Smith Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 2304202210b3SRichard Smith 23057ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 23067ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 23077ff29148SBen Langmuir // Module::UsesRequiresExcludedHack). 23087ff29148SBen Langmuir Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 23097ff29148SBen Langmuir } 23107ff29148SBen Langmuir 2311202210b3SRichard Smith if (LeadingToken != MMToken::HeaderKeyword) { 2312202210b3SRichard Smith if (!Tok.is(MMToken::HeaderKeyword)) { 2313202210b3SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2314202210b3SRichard Smith << (LeadingToken == MMToken::PrivateKeyword ? "private" : 2315202210b3SRichard Smith LeadingToken == MMToken::ExcludeKeyword ? "exclude" : 2316202210b3SRichard Smith LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella"); 2317202210b3SRichard Smith return; 2318202210b3SRichard Smith } 2319202210b3SRichard Smith consumeToken(); 2320202210b3SRichard Smith } 2321718292f2SDouglas Gregor 2322718292f2SDouglas Gregor // Parse the header name. 2323718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2324718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2325718292f2SDouglas Gregor << "header"; 2326718292f2SDouglas Gregor HadError = true; 2327718292f2SDouglas Gregor return; 2328718292f2SDouglas Gregor } 23293c1a41adSRichard Smith Module::UnresolvedHeaderDirective Header; 2330adcd0268SBenjamin Kramer Header.FileName = std::string(Tok.getString()); 23310761a8a0SDaniel Jasper Header.FileNameLoc = consumeToken(); 23321d60987fSRichard Smith Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword; 2333040e1266SRichard Smith Header.Kind = 2334040e1266SRichard Smith (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded 2335040e1266SRichard Smith : Map.headerRoleToKind(Role)); 2336718292f2SDouglas Gregor 2337524e33e1SDouglas Gregor // Check whether we already have an umbrella. 23381d60987fSRichard Smith if (Header.IsUmbrella && ActiveModule->Umbrella) { 23390761a8a0SDaniel Jasper Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) 2340524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2341322f633cSDouglas Gregor HadError = true; 2342322f633cSDouglas Gregor return; 2343322f633cSDouglas Gregor } 2344322f633cSDouglas Gregor 2345040e1266SRichard Smith // If we were given stat information, parse it so we can skip looking for 2346040e1266SRichard Smith // the file. 2347040e1266SRichard Smith if (Tok.is(MMToken::LBrace)) { 2348040e1266SRichard Smith SourceLocation LBraceLoc = consumeToken(); 23493ec6663bSDouglas Gregor 2350040e1266SRichard Smith while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) { 2351040e1266SRichard Smith enum Attribute { Size, ModTime, Unknown }; 2352040e1266SRichard Smith StringRef Str = Tok.getString(); 2353040e1266SRichard Smith SourceLocation Loc = consumeToken(); 2354040e1266SRichard Smith switch (llvm::StringSwitch<Attribute>(Str) 2355040e1266SRichard Smith .Case("size", Size) 2356040e1266SRichard Smith .Case("mtime", ModTime) 2357040e1266SRichard Smith .Default(Unknown)) { 2358040e1266SRichard Smith case Size: 2359040e1266SRichard Smith if (Header.Size) 2360040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2361040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2362040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2363040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2364040e1266SRichard Smith skipUntil(MMToken::RBrace); 2365040e1266SRichard Smith break; 2366040e1266SRichard Smith } 2367040e1266SRichard Smith Header.Size = Tok.getInteger(); 2368040e1266SRichard Smith consumeToken(); 2369040e1266SRichard Smith break; 2370040e1266SRichard Smith 2371040e1266SRichard Smith case ModTime: 2372040e1266SRichard Smith if (Header.ModTime) 2373040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2374040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2375040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2376040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2377040e1266SRichard Smith skipUntil(MMToken::RBrace); 2378040e1266SRichard Smith break; 2379040e1266SRichard Smith } 2380040e1266SRichard Smith Header.ModTime = Tok.getInteger(); 2381040e1266SRichard Smith consumeToken(); 2382040e1266SRichard Smith break; 2383040e1266SRichard Smith 2384040e1266SRichard Smith case Unknown: 2385040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_expected_header_attribute); 2386040e1266SRichard Smith skipUntil(MMToken::RBrace); 2387040e1266SRichard Smith break; 2388040e1266SRichard Smith } 23893ec6663bSDouglas Gregor } 23905257fc63SDouglas Gregor 2391040e1266SRichard Smith if (Tok.is(MMToken::RBrace)) 2392040e1266SRichard Smith consumeToken(); 2393040e1266SRichard Smith else { 2394040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 2395040e1266SRichard Smith Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 2396322f633cSDouglas Gregor HadError = true; 2397322f633cSDouglas Gregor } 23980101b540SHans Wennborg } 239925d50758SRichard Smith 24009f6020bcSBruno Cardoso Lopes bool NeedsFramework = false; 24019f6020bcSBruno Cardoso Lopes Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework); 24029f6020bcSBruno Cardoso Lopes 24039f6020bcSBruno Cardoso Lopes if (NeedsFramework && ActiveModule) 24049f6020bcSBruno Cardoso Lopes Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword) 24059f6020bcSBruno Cardoso Lopes << ActiveModule->getFullModuleName() 24069f6020bcSBruno Cardoso Lopes << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module"); 2407718292f2SDouglas Gregor } 2408718292f2SDouglas Gregor 240941f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A, 241041f81994SBen Langmuir const Module::Header *B) { 241141f81994SBen Langmuir return A->NameAsWritten.compare(B->NameAsWritten); 241241f81994SBen Langmuir } 241341f81994SBen Langmuir 24149fc8faf9SAdrian Prantl /// Parse an umbrella directory declaration. 2415524e33e1SDouglas Gregor /// 2416524e33e1SDouglas Gregor /// umbrella-dir-declaration: 2417524e33e1SDouglas Gregor /// umbrella string-literal 2418524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { 2419524e33e1SDouglas Gregor // Parse the directory name. 2420524e33e1SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2421524e33e1SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2422524e33e1SDouglas Gregor << "umbrella"; 2423524e33e1SDouglas Gregor HadError = true; 2424524e33e1SDouglas Gregor return; 2425524e33e1SDouglas Gregor } 2426524e33e1SDouglas Gregor 2427adcd0268SBenjamin Kramer std::string DirName = std::string(Tok.getString()); 2428d3676d4bSMichael Spencer std::string DirNameAsWritten = DirName; 2429524e33e1SDouglas Gregor SourceLocation DirNameLoc = consumeToken(); 2430524e33e1SDouglas Gregor 2431524e33e1SDouglas Gregor // Check whether we already have an umbrella. 2432524e33e1SDouglas Gregor if (ActiveModule->Umbrella) { 2433524e33e1SDouglas Gregor Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash) 2434524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2435524e33e1SDouglas Gregor HadError = true; 2436524e33e1SDouglas Gregor return; 2437524e33e1SDouglas Gregor } 2438524e33e1SDouglas Gregor 2439524e33e1SDouglas Gregor // Look for this file. 244064d8c781SDuncan P. N. Exon Smith const DirectoryEntry *Dir = nullptr; 24418d323d15SHarlan Haskins if (llvm::sys::path::is_absolute(DirName)) { 244264d8c781SDuncan P. N. Exon Smith if (auto D = SourceMgr.getFileManager().getDirectory(DirName)) 24438d323d15SHarlan Haskins Dir = *D; 24448d323d15SHarlan Haskins } else { 24452c1dd271SDylan Noblesmith SmallString<128> PathName; 2446524e33e1SDouglas Gregor PathName = Directory->getName(); 2447524e33e1SDouglas Gregor llvm::sys::path::append(PathName, DirName); 244864d8c781SDuncan P. N. Exon Smith if (auto D = SourceMgr.getFileManager().getDirectory(PathName)) 24498d323d15SHarlan Haskins Dir = *D; 2450524e33e1SDouglas Gregor } 2451524e33e1SDouglas Gregor 2452524e33e1SDouglas Gregor if (!Dir) { 2453a0320b97SVassil Vassilev Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found) 2454524e33e1SDouglas Gregor << DirName; 2455524e33e1SDouglas Gregor return; 2456524e33e1SDouglas Gregor } 2457524e33e1SDouglas Gregor 24587ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 24597ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 24607ff29148SBen Langmuir // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the 24617ff29148SBen Langmuir // directory is relatively expensive, in practice this only applies to the 24627ff29148SBen Langmuir // uncommonly used Tcl module on Darwin platforms. 24637ff29148SBen Langmuir std::error_code EC; 24647ff29148SBen Langmuir SmallVector<Module::Header, 6> Headers; 2465fc51490bSJonas Devlieghere llvm::vfs::FileSystem &FS = 2466db8a7422SDuncan P. N. Exon Smith SourceMgr.getFileManager().getVirtualFileSystem(); 2467fc51490bSJonas Devlieghere for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E; 24687ff29148SBen Langmuir I != E && !EC; I.increment(EC)) { 246964d8c781SDuncan P. N. Exon Smith if (auto FE = SourceMgr.getFileManager().getFile(I->path())) { 2470d3676d4bSMichael Spencer Module::Header Header = {"", std::string(I->path()), *FE}; 24717ff29148SBen Langmuir Headers.push_back(std::move(Header)); 24727ff29148SBen Langmuir } 24737ff29148SBen Langmuir } 24747ff29148SBen Langmuir 24757ff29148SBen Langmuir // Sort header paths so that the pcm doesn't depend on iteration order. 247641f81994SBen Langmuir llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders); 247741f81994SBen Langmuir 24787ff29148SBen Langmuir for (auto &Header : Headers) 24797ff29148SBen Langmuir Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader); 24807ff29148SBen Langmuir return; 24817ff29148SBen Langmuir } 24827ff29148SBen Langmuir 248364d8c781SDuncan P. N. Exon Smith if (Module *OwningModule = Map.UmbrellaDirs[Dir]) { 2484524e33e1SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 2485524e33e1SDouglas Gregor << OwningModule->getFullModuleName(); 2486524e33e1SDouglas Gregor HadError = true; 2487524e33e1SDouglas Gregor return; 2488524e33e1SDouglas Gregor } 2489524e33e1SDouglas Gregor 2490524e33e1SDouglas Gregor // Record this umbrella directory. 2491d3676d4bSMichael Spencer Map.setUmbrellaDir(ActiveModule, Dir, DirNameAsWritten, DirName); 2492524e33e1SDouglas Gregor } 2493524e33e1SDouglas Gregor 24949fc8faf9SAdrian Prantl /// Parse a module export declaration. 24952b82c2a5SDouglas Gregor /// 24962b82c2a5SDouglas Gregor /// export-declaration: 24972b82c2a5SDouglas Gregor /// 'export' wildcard-module-id 24982b82c2a5SDouglas Gregor /// 24992b82c2a5SDouglas Gregor /// wildcard-module-id: 25002b82c2a5SDouglas Gregor /// identifier 25012b82c2a5SDouglas Gregor /// '*' 25022b82c2a5SDouglas Gregor /// identifier '.' wildcard-module-id 25032b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() { 25042b82c2a5SDouglas Gregor assert(Tok.is(MMToken::ExportKeyword)); 25052b82c2a5SDouglas Gregor SourceLocation ExportLoc = consumeToken(); 25062b82c2a5SDouglas Gregor 25072b82c2a5SDouglas Gregor // Parse the module-id with an optional wildcard at the end. 25082b82c2a5SDouglas Gregor ModuleId ParsedModuleId; 25092b82c2a5SDouglas Gregor bool Wildcard = false; 25102b82c2a5SDouglas Gregor do { 2511306d8920SRichard Smith // FIXME: Support string-literal module names here. 25122b82c2a5SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 2513adcd0268SBenjamin Kramer ParsedModuleId.push_back( 2514adcd0268SBenjamin Kramer std::make_pair(std::string(Tok.getString()), Tok.getLocation())); 25152b82c2a5SDouglas Gregor consumeToken(); 25162b82c2a5SDouglas Gregor 25172b82c2a5SDouglas Gregor if (Tok.is(MMToken::Period)) { 25182b82c2a5SDouglas Gregor consumeToken(); 25192b82c2a5SDouglas Gregor continue; 25202b82c2a5SDouglas Gregor } 25212b82c2a5SDouglas Gregor 25222b82c2a5SDouglas Gregor break; 25232b82c2a5SDouglas Gregor } 25242b82c2a5SDouglas Gregor 25252b82c2a5SDouglas Gregor if(Tok.is(MMToken::Star)) { 25262b82c2a5SDouglas Gregor Wildcard = true; 2527f5eedd05SDouglas Gregor consumeToken(); 25282b82c2a5SDouglas Gregor break; 25292b82c2a5SDouglas Gregor } 25302b82c2a5SDouglas Gregor 2531ba7f2f71SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_module_id); 25322b82c2a5SDouglas Gregor HadError = true; 25332b82c2a5SDouglas Gregor return; 25342b82c2a5SDouglas Gregor } while (true); 25352b82c2a5SDouglas Gregor 25362b82c2a5SDouglas Gregor Module::UnresolvedExportDecl Unresolved = { 25372b82c2a5SDouglas Gregor ExportLoc, ParsedModuleId, Wildcard 25382b82c2a5SDouglas Gregor }; 25392b82c2a5SDouglas Gregor ActiveModule->UnresolvedExports.push_back(Unresolved); 25402b82c2a5SDouglas Gregor } 25412b82c2a5SDouglas Gregor 25429fc8faf9SAdrian Prantl /// Parse a module export_as declaration. 2543f0b11de2SDouglas Gregor /// 2544f0b11de2SDouglas Gregor /// export-as-declaration: 2545f0b11de2SDouglas Gregor /// 'export_as' identifier 2546f0b11de2SDouglas Gregor void ModuleMapParser::parseExportAsDecl() { 2547f0b11de2SDouglas Gregor assert(Tok.is(MMToken::ExportAsKeyword)); 2548f0b11de2SDouglas Gregor consumeToken(); 2549f0b11de2SDouglas Gregor 2550f0b11de2SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 2551f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_module_id); 2552f0b11de2SDouglas Gregor HadError = true; 2553f0b11de2SDouglas Gregor return; 2554f0b11de2SDouglas Gregor } 2555f0b11de2SDouglas Gregor 2556f0b11de2SDouglas Gregor if (ActiveModule->Parent) { 2557f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as); 2558f0b11de2SDouglas Gregor consumeToken(); 2559f0b11de2SDouglas Gregor return; 2560f0b11de2SDouglas Gregor } 2561f0b11de2SDouglas Gregor 2562f0b11de2SDouglas Gregor if (!ActiveModule->ExportAsModule.empty()) { 2563f0b11de2SDouglas Gregor if (ActiveModule->ExportAsModule == Tok.getString()) { 2564f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as) 2565f0b11de2SDouglas Gregor << ActiveModule->Name << Tok.getString(); 2566f0b11de2SDouglas Gregor } else { 2567f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as) 2568f0b11de2SDouglas Gregor << ActiveModule->Name << ActiveModule->ExportAsModule 2569f0b11de2SDouglas Gregor << Tok.getString(); 2570f0b11de2SDouglas Gregor } 2571f0b11de2SDouglas Gregor } 2572f0b11de2SDouglas Gregor 2573adcd0268SBenjamin Kramer ActiveModule->ExportAsModule = std::string(Tok.getString()); 2574a3b5f71eSBruno Cardoso Lopes Map.addLinkAsDependency(ActiveModule); 2575a3b5f71eSBruno Cardoso Lopes 2576f0b11de2SDouglas Gregor consumeToken(); 2577f0b11de2SDouglas Gregor } 2578f0b11de2SDouglas Gregor 25799fc8faf9SAdrian Prantl /// Parse a module use declaration. 2580ba7f2f71SDaniel Jasper /// 25818f4d3ff1SRichard Smith /// use-declaration: 25828f4d3ff1SRichard Smith /// 'use' wildcard-module-id 2583ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() { 2584ba7f2f71SDaniel Jasper assert(Tok.is(MMToken::UseKeyword)); 25858f4d3ff1SRichard Smith auto KWLoc = consumeToken(); 2586ba7f2f71SDaniel Jasper // Parse the module-id. 2587ba7f2f71SDaniel Jasper ModuleId ParsedModuleId; 25883cd34c76SDaniel Jasper parseModuleId(ParsedModuleId); 2589ba7f2f71SDaniel Jasper 25908f4d3ff1SRichard Smith if (ActiveModule->Parent) 25918f4d3ff1SRichard Smith Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule); 25928f4d3ff1SRichard Smith else 2593ba7f2f71SDaniel Jasper ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId); 2594ba7f2f71SDaniel Jasper } 2595ba7f2f71SDaniel Jasper 25969fc8faf9SAdrian Prantl /// Parse a link declaration. 25976ddfca91SDouglas Gregor /// 25986ddfca91SDouglas Gregor /// module-declaration: 25996ddfca91SDouglas Gregor /// 'link' 'framework'[opt] string-literal 26006ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() { 26016ddfca91SDouglas Gregor assert(Tok.is(MMToken::LinkKeyword)); 26026ddfca91SDouglas Gregor SourceLocation LinkLoc = consumeToken(); 26036ddfca91SDouglas Gregor 26046ddfca91SDouglas Gregor // Parse the optional 'framework' keyword. 26056ddfca91SDouglas Gregor bool IsFramework = false; 26066ddfca91SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 26076ddfca91SDouglas Gregor consumeToken(); 26086ddfca91SDouglas Gregor IsFramework = true; 26096ddfca91SDouglas Gregor } 26106ddfca91SDouglas Gregor 26116ddfca91SDouglas Gregor // Parse the library name 26126ddfca91SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 26136ddfca91SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name) 26146ddfca91SDouglas Gregor << IsFramework << SourceRange(LinkLoc); 26156ddfca91SDouglas Gregor HadError = true; 26166ddfca91SDouglas Gregor return; 26176ddfca91SDouglas Gregor } 26186ddfca91SDouglas Gregor 2619adcd0268SBenjamin Kramer std::string LibraryName = std::string(Tok.getString()); 26206ddfca91SDouglas Gregor consumeToken(); 26216ddfca91SDouglas Gregor ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName, 26226ddfca91SDouglas Gregor IsFramework)); 26236ddfca91SDouglas Gregor } 26246ddfca91SDouglas Gregor 26259fc8faf9SAdrian Prantl /// Parse a configuration macro declaration. 262635b13eceSDouglas Gregor /// 262735b13eceSDouglas Gregor /// module-declaration: 262835b13eceSDouglas Gregor /// 'config_macros' attributes[opt] config-macro-list? 262935b13eceSDouglas Gregor /// 263035b13eceSDouglas Gregor /// config-macro-list: 263135b13eceSDouglas Gregor /// identifier (',' identifier)? 263235b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() { 263335b13eceSDouglas Gregor assert(Tok.is(MMToken::ConfigMacros)); 263435b13eceSDouglas Gregor SourceLocation ConfigMacrosLoc = consumeToken(); 263535b13eceSDouglas Gregor 263635b13eceSDouglas Gregor // Only top-level modules can have configuration macros. 263735b13eceSDouglas Gregor if (ActiveModule->Parent) { 263835b13eceSDouglas Gregor Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule); 263935b13eceSDouglas Gregor } 264035b13eceSDouglas Gregor 264135b13eceSDouglas Gregor // Parse the optional attributes. 264235b13eceSDouglas Gregor Attributes Attrs; 26435d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 26445d29dee0SDavide Italiano return; 26455d29dee0SDavide Italiano 264635b13eceSDouglas Gregor if (Attrs.IsExhaustive && !ActiveModule->Parent) { 264735b13eceSDouglas Gregor ActiveModule->ConfigMacrosExhaustive = true; 264835b13eceSDouglas Gregor } 264935b13eceSDouglas Gregor 265035b13eceSDouglas Gregor // If we don't have an identifier, we're done. 2651306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 265235b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) 265335b13eceSDouglas Gregor return; 265435b13eceSDouglas Gregor 265535b13eceSDouglas Gregor // Consume the first identifier. 265635b13eceSDouglas Gregor if (!ActiveModule->Parent) { 265735b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 265835b13eceSDouglas Gregor } 265935b13eceSDouglas Gregor consumeToken(); 266035b13eceSDouglas Gregor 266135b13eceSDouglas Gregor do { 266235b13eceSDouglas Gregor // If there's a comma, consume it. 266335b13eceSDouglas Gregor if (!Tok.is(MMToken::Comma)) 266435b13eceSDouglas Gregor break; 266535b13eceSDouglas Gregor consumeToken(); 266635b13eceSDouglas Gregor 266735b13eceSDouglas Gregor // We expect to see a macro name here. 2668306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 266935b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 267035b13eceSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro); 267135b13eceSDouglas Gregor break; 267235b13eceSDouglas Gregor } 267335b13eceSDouglas Gregor 267435b13eceSDouglas Gregor // Consume the macro name. 267535b13eceSDouglas Gregor if (!ActiveModule->Parent) { 267635b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 267735b13eceSDouglas Gregor } 267835b13eceSDouglas Gregor consumeToken(); 267935b13eceSDouglas Gregor } while (true); 268035b13eceSDouglas Gregor } 268135b13eceSDouglas Gregor 26829fc8faf9SAdrian Prantl /// Format a module-id into a string. 2683fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) { 2684fb912657SDouglas Gregor std::string result; 2685fb912657SDouglas Gregor { 2686fb912657SDouglas Gregor llvm::raw_string_ostream OS(result); 2687fb912657SDouglas Gregor 2688fb912657SDouglas Gregor for (unsigned I = 0, N = Id.size(); I != N; ++I) { 2689fb912657SDouglas Gregor if (I) 2690fb912657SDouglas Gregor OS << "."; 2691fb912657SDouglas Gregor OS << Id[I].first; 2692fb912657SDouglas Gregor } 2693fb912657SDouglas Gregor } 2694fb912657SDouglas Gregor 2695fb912657SDouglas Gregor return result; 2696fb912657SDouglas Gregor } 2697fb912657SDouglas Gregor 26989fc8faf9SAdrian Prantl /// Parse a conflict declaration. 2699fb912657SDouglas Gregor /// 2700fb912657SDouglas Gregor /// module-declaration: 2701fb912657SDouglas Gregor /// 'conflict' module-id ',' string-literal 2702fb912657SDouglas Gregor void ModuleMapParser::parseConflict() { 2703fb912657SDouglas Gregor assert(Tok.is(MMToken::Conflict)); 2704fb912657SDouglas Gregor SourceLocation ConflictLoc = consumeToken(); 2705fb912657SDouglas Gregor Module::UnresolvedConflict Conflict; 2706fb912657SDouglas Gregor 2707fb912657SDouglas Gregor // Parse the module-id. 2708fb912657SDouglas Gregor if (parseModuleId(Conflict.Id)) 2709fb912657SDouglas Gregor return; 2710fb912657SDouglas Gregor 2711fb912657SDouglas Gregor // Parse the ','. 2712fb912657SDouglas Gregor if (!Tok.is(MMToken::Comma)) { 2713fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma) 2714fb912657SDouglas Gregor << SourceRange(ConflictLoc); 2715fb912657SDouglas Gregor return; 2716fb912657SDouglas Gregor } 2717fb912657SDouglas Gregor consumeToken(); 2718fb912657SDouglas Gregor 2719fb912657SDouglas Gregor // Parse the message. 2720fb912657SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2721fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message) 2722fb912657SDouglas Gregor << formatModuleId(Conflict.Id); 2723fb912657SDouglas Gregor return; 2724fb912657SDouglas Gregor } 2725fb912657SDouglas Gregor Conflict.Message = Tok.getString().str(); 2726fb912657SDouglas Gregor consumeToken(); 2727fb912657SDouglas Gregor 2728fb912657SDouglas Gregor // Add this unresolved conflict. 2729fb912657SDouglas Gregor ActiveModule->UnresolvedConflicts.push_back(Conflict); 2730fb912657SDouglas Gregor } 2731fb912657SDouglas Gregor 27329fc8faf9SAdrian Prantl /// Parse an inferred module declaration (wildcard modules). 27339194a91dSDouglas Gregor /// 27349194a91dSDouglas Gregor /// module-declaration: 27359194a91dSDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt] 27369194a91dSDouglas Gregor /// { inferred-module-member* } 27379194a91dSDouglas Gregor /// 27389194a91dSDouglas Gregor /// inferred-module-member: 27399194a91dSDouglas Gregor /// 'export' '*' 27409194a91dSDouglas Gregor /// 'exclude' identifier 27419194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { 274273441091SDouglas Gregor assert(Tok.is(MMToken::Star)); 274373441091SDouglas Gregor SourceLocation StarLoc = consumeToken(); 274473441091SDouglas Gregor bool Failed = false; 274573441091SDouglas Gregor 274673441091SDouglas Gregor // Inferred modules must be submodules. 27479194a91dSDouglas Gregor if (!ActiveModule && !Framework) { 274873441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule); 274973441091SDouglas Gregor Failed = true; 275073441091SDouglas Gregor } 275173441091SDouglas Gregor 27529194a91dSDouglas Gregor if (ActiveModule) { 2753524e33e1SDouglas Gregor // Inferred modules must have umbrella directories. 27544898cde4SBen Langmuir if (!Failed && ActiveModule->IsAvailable && 27554898cde4SBen Langmuir !ActiveModule->getUmbrellaDir()) { 275673441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); 275773441091SDouglas Gregor Failed = true; 275873441091SDouglas Gregor } 275973441091SDouglas Gregor 276073441091SDouglas Gregor // Check for redefinition of an inferred module. 2761dd005f69SDouglas Gregor if (!Failed && ActiveModule->InferSubmodules) { 276273441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_redef); 2763dd005f69SDouglas Gregor if (ActiveModule->InferredSubmoduleLoc.isValid()) 2764dd005f69SDouglas Gregor Diags.Report(ActiveModule->InferredSubmoduleLoc, 276573441091SDouglas Gregor diag::note_mmap_prev_definition); 276673441091SDouglas Gregor Failed = true; 276773441091SDouglas Gregor } 276873441091SDouglas Gregor 27699194a91dSDouglas Gregor // Check for the 'framework' keyword, which is not permitted here. 27709194a91dSDouglas Gregor if (Framework) { 27719194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule); 27729194a91dSDouglas Gregor Framework = false; 27739194a91dSDouglas Gregor } 27749194a91dSDouglas Gregor } else if (Explicit) { 27759194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework); 27769194a91dSDouglas Gregor Explicit = false; 27779194a91dSDouglas Gregor } 27789194a91dSDouglas Gregor 277973441091SDouglas Gregor // If there were any problems with this inferred submodule, skip its body. 278073441091SDouglas Gregor if (Failed) { 278173441091SDouglas Gregor if (Tok.is(MMToken::LBrace)) { 278273441091SDouglas Gregor consumeToken(); 278373441091SDouglas Gregor skipUntil(MMToken::RBrace); 278473441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 278573441091SDouglas Gregor consumeToken(); 278673441091SDouglas Gregor } 278773441091SDouglas Gregor HadError = true; 278873441091SDouglas Gregor return; 278973441091SDouglas Gregor } 279073441091SDouglas Gregor 27919194a91dSDouglas Gregor // Parse optional attributes. 27924442605fSBill Wendling Attributes Attrs; 27935d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 27945d29dee0SDavide Italiano return; 27959194a91dSDouglas Gregor 27969194a91dSDouglas Gregor if (ActiveModule) { 279773441091SDouglas Gregor // Note that we have an inferred submodule. 2798dd005f69SDouglas Gregor ActiveModule->InferSubmodules = true; 2799dd005f69SDouglas Gregor ActiveModule->InferredSubmoduleLoc = StarLoc; 2800dd005f69SDouglas Gregor ActiveModule->InferExplicitSubmodules = Explicit; 28019194a91dSDouglas Gregor } else { 28029194a91dSDouglas Gregor // We'll be inferring framework modules for this directory. 28039194a91dSDouglas Gregor Map.InferredDirectories[Directory].InferModules = true; 2804c1d88ea5SBen Langmuir Map.InferredDirectories[Directory].Attrs = Attrs; 2805beee15e7SBen Langmuir Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile; 2806131daca0SRichard Smith // FIXME: Handle the 'framework' keyword. 28079194a91dSDouglas Gregor } 280873441091SDouglas Gregor 280973441091SDouglas Gregor // Parse the opening brace. 281073441091SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 281173441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard); 281273441091SDouglas Gregor HadError = true; 281373441091SDouglas Gregor return; 281473441091SDouglas Gregor } 281573441091SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 281673441091SDouglas Gregor 281773441091SDouglas Gregor // Parse the body of the inferred submodule. 281873441091SDouglas Gregor bool Done = false; 281973441091SDouglas Gregor do { 282073441091SDouglas Gregor switch (Tok.Kind) { 282173441091SDouglas Gregor case MMToken::EndOfFile: 282273441091SDouglas Gregor case MMToken::RBrace: 282373441091SDouglas Gregor Done = true; 282473441091SDouglas Gregor break; 282573441091SDouglas Gregor 2826afd1b1c9SEugene Zelenko case MMToken::ExcludeKeyword: 28279194a91dSDouglas Gregor if (ActiveModule) { 28289194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2829d2d442caSCraig Topper << (ActiveModule != nullptr); 28309194a91dSDouglas Gregor consumeToken(); 28319194a91dSDouglas Gregor break; 28329194a91dSDouglas Gregor } 28339194a91dSDouglas Gregor 28349194a91dSDouglas Gregor consumeToken(); 2835306d8920SRichard Smith // FIXME: Support string-literal module names here. 28369194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 28379194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name); 28389194a91dSDouglas Gregor break; 28399194a91dSDouglas Gregor } 28409194a91dSDouglas Gregor 2841adcd0268SBenjamin Kramer Map.InferredDirectories[Directory].ExcludedModules.push_back( 2842adcd0268SBenjamin Kramer std::string(Tok.getString())); 28439194a91dSDouglas Gregor consumeToken(); 28449194a91dSDouglas Gregor break; 28459194a91dSDouglas Gregor 28469194a91dSDouglas Gregor case MMToken::ExportKeyword: 28479194a91dSDouglas Gregor if (!ActiveModule) { 28489194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2849d2d442caSCraig Topper << (ActiveModule != nullptr); 28509194a91dSDouglas Gregor consumeToken(); 28519194a91dSDouglas Gregor break; 28529194a91dSDouglas Gregor } 28539194a91dSDouglas Gregor 285473441091SDouglas Gregor consumeToken(); 285573441091SDouglas Gregor if (Tok.is(MMToken::Star)) 2856dd005f69SDouglas Gregor ActiveModule->InferExportWildcard = true; 285773441091SDouglas Gregor else 285873441091SDouglas Gregor Diags.Report(Tok.getLocation(), 285973441091SDouglas Gregor diag::err_mmap_expected_export_wildcard); 286073441091SDouglas Gregor consumeToken(); 286173441091SDouglas Gregor break; 286273441091SDouglas Gregor 286373441091SDouglas Gregor case MMToken::ExplicitKeyword: 286473441091SDouglas Gregor case MMToken::ModuleKeyword: 286573441091SDouglas Gregor case MMToken::HeaderKeyword: 2866b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 286773441091SDouglas Gregor case MMToken::UmbrellaKeyword: 286873441091SDouglas Gregor default: 28699194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2870d2d442caSCraig Topper << (ActiveModule != nullptr); 287173441091SDouglas Gregor consumeToken(); 287273441091SDouglas Gregor break; 287373441091SDouglas Gregor } 287473441091SDouglas Gregor } while (!Done); 287573441091SDouglas Gregor 287673441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 287773441091SDouglas Gregor consumeToken(); 287873441091SDouglas Gregor else { 287973441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 288073441091SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 288173441091SDouglas Gregor HadError = true; 288273441091SDouglas Gregor } 288373441091SDouglas Gregor } 288473441091SDouglas Gregor 28859fc8faf9SAdrian Prantl /// Parse optional attributes. 28869194a91dSDouglas Gregor /// 28879194a91dSDouglas Gregor /// attributes: 28889194a91dSDouglas Gregor /// attribute attributes 28899194a91dSDouglas Gregor /// attribute 28909194a91dSDouglas Gregor /// 28919194a91dSDouglas Gregor /// attribute: 28929194a91dSDouglas Gregor /// [ identifier ] 28939194a91dSDouglas Gregor /// 28949194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes. 28959194a91dSDouglas Gregor /// 28969194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise. 28974442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { 28989194a91dSDouglas Gregor bool HadError = false; 28999194a91dSDouglas Gregor 29009194a91dSDouglas Gregor while (Tok.is(MMToken::LSquare)) { 29019194a91dSDouglas Gregor // Consume the '['. 29029194a91dSDouglas Gregor SourceLocation LSquareLoc = consumeToken(); 29039194a91dSDouglas Gregor 29049194a91dSDouglas Gregor // Check whether we have an attribute name here. 29059194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 29069194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute); 29079194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 29089194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 29099194a91dSDouglas Gregor consumeToken(); 29109194a91dSDouglas Gregor HadError = true; 29119194a91dSDouglas Gregor } 29129194a91dSDouglas Gregor 29139194a91dSDouglas Gregor // Decode the attribute name. 29149194a91dSDouglas Gregor AttributeKind Attribute 29159194a91dSDouglas Gregor = llvm::StringSwitch<AttributeKind>(Tok.getString()) 291635b13eceSDouglas Gregor .Case("exhaustive", AT_exhaustive) 291777944868SRichard Smith .Case("extern_c", AT_extern_c) 2918ed84df00SBruno Cardoso Lopes .Case("no_undeclared_includes", AT_no_undeclared_includes) 29199194a91dSDouglas Gregor .Case("system", AT_system) 29209194a91dSDouglas Gregor .Default(AT_unknown); 29219194a91dSDouglas Gregor switch (Attribute) { 29229194a91dSDouglas Gregor case AT_unknown: 29239194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute) 29249194a91dSDouglas Gregor << Tok.getString(); 29259194a91dSDouglas Gregor break; 29269194a91dSDouglas Gregor 29279194a91dSDouglas Gregor case AT_system: 29289194a91dSDouglas Gregor Attrs.IsSystem = true; 29299194a91dSDouglas Gregor break; 293035b13eceSDouglas Gregor 293177944868SRichard Smith case AT_extern_c: 293277944868SRichard Smith Attrs.IsExternC = true; 293377944868SRichard Smith break; 293477944868SRichard Smith 293535b13eceSDouglas Gregor case AT_exhaustive: 293635b13eceSDouglas Gregor Attrs.IsExhaustive = true; 293735b13eceSDouglas Gregor break; 2938ed84df00SBruno Cardoso Lopes 2939ed84df00SBruno Cardoso Lopes case AT_no_undeclared_includes: 2940ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes = true; 2941ed84df00SBruno Cardoso Lopes break; 29429194a91dSDouglas Gregor } 29439194a91dSDouglas Gregor consumeToken(); 29449194a91dSDouglas Gregor 29459194a91dSDouglas Gregor // Consume the ']'. 29469194a91dSDouglas Gregor if (!Tok.is(MMToken::RSquare)) { 29479194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare); 29489194a91dSDouglas Gregor Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match); 29499194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 29509194a91dSDouglas Gregor HadError = true; 29519194a91dSDouglas Gregor } 29529194a91dSDouglas Gregor 29539194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 29549194a91dSDouglas Gregor consumeToken(); 29559194a91dSDouglas Gregor } 29569194a91dSDouglas Gregor 29579194a91dSDouglas Gregor return HadError; 29589194a91dSDouglas Gregor } 29599194a91dSDouglas Gregor 29609fc8faf9SAdrian Prantl /// Parse a module map file. 2961718292f2SDouglas Gregor /// 2962718292f2SDouglas Gregor /// module-map-file: 2963718292f2SDouglas Gregor /// module-declaration* 2964718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 2965718292f2SDouglas Gregor do { 2966718292f2SDouglas Gregor switch (Tok.Kind) { 2967718292f2SDouglas Gregor case MMToken::EndOfFile: 2968718292f2SDouglas Gregor return HadError; 2969718292f2SDouglas Gregor 2970e7ab3669SDouglas Gregor case MMToken::ExplicitKeyword: 297197292843SDaniel Jasper case MMToken::ExternKeyword: 2972718292f2SDouglas Gregor case MMToken::ModuleKeyword: 2973755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 2974718292f2SDouglas Gregor parseModuleDecl(); 2975718292f2SDouglas Gregor break; 2976718292f2SDouglas Gregor 29771fb5c3a6SDouglas Gregor case MMToken::Comma: 297835b13eceSDouglas Gregor case MMToken::ConfigMacros: 2979fb912657SDouglas Gregor case MMToken::Conflict: 2980a3feee2aSRichard Smith case MMToken::Exclaim: 298159527666SDouglas Gregor case MMToken::ExcludeKeyword: 29822b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 2983f0b11de2SDouglas Gregor case MMToken::ExportAsKeyword: 2984718292f2SDouglas Gregor case MMToken::HeaderKeyword: 2985718292f2SDouglas Gregor case MMToken::Identifier: 2986718292f2SDouglas Gregor case MMToken::LBrace: 29876ddfca91SDouglas Gregor case MMToken::LinkKeyword: 2988a686e1b0SDouglas Gregor case MMToken::LSquare: 29892b82c2a5SDouglas Gregor case MMToken::Period: 2990b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 2991718292f2SDouglas Gregor case MMToken::RBrace: 2992a686e1b0SDouglas Gregor case MMToken::RSquare: 29931fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 29942b82c2a5SDouglas Gregor case MMToken::Star: 2995718292f2SDouglas Gregor case MMToken::StringLiteral: 2996040e1266SRichard Smith case MMToken::IntegerLiteral: 2997b8afebe2SRichard Smith case MMToken::TextualKeyword: 2998718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 2999ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 3000718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 3001718292f2SDouglas Gregor HadError = true; 3002718292f2SDouglas Gregor consumeToken(); 3003718292f2SDouglas Gregor break; 3004718292f2SDouglas Gregor } 3005718292f2SDouglas Gregor } while (true); 3006718292f2SDouglas Gregor } 3007718292f2SDouglas Gregor 30087799ef71SNico Weber bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem, 3009c192d194SBruno Cardoso Lopes const DirectoryEntry *Dir, FileID ID, 30108128f332SRichard Smith unsigned *Offset, 3011ae6df27eSRichard Smith SourceLocation ExternModuleLoc) { 30128128f332SRichard Smith assert(Target && "Missing target information"); 30134ddf2221SDouglas Gregor llvm::DenseMap<const FileEntry *, bool>::iterator Known 30144ddf2221SDouglas Gregor = ParsedModuleMap.find(File); 30154ddf2221SDouglas Gregor if (Known != ParsedModuleMap.end()) 30164ddf2221SDouglas Gregor return Known->second; 30174ddf2221SDouglas Gregor 30188128f332SRichard Smith // If the module map file wasn't already entered, do so now. 30198128f332SRichard Smith if (ID.isInvalid()) { 3020f3f84616SRichard Smith auto FileCharacter = 3021f3f84616SRichard Smith IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap; 30228128f332SRichard Smith ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter); 30238128f332SRichard Smith } 30248128f332SRichard Smith 30258128f332SRichard Smith assert(Target && "Missing target information"); 3026b03ae743SDuncan P. N. Exon Smith llvm::Optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID); 3027718292f2SDouglas Gregor if (!Buffer) 30284ddf2221SDouglas Gregor return ParsedModuleMap[File] = true; 30298128f332SRichard Smith assert((!Offset || *Offset <= Buffer->getBufferSize()) && 30308128f332SRichard Smith "invalid buffer offset"); 3031718292f2SDouglas Gregor 3032718292f2SDouglas Gregor // Parse this module map file. 30338128f332SRichard Smith Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts, 30348128f332SRichard Smith Buffer->getBufferStart(), 30358128f332SRichard Smith Buffer->getBufferStart() + (Offset ? *Offset : 0), 30368128f332SRichard Smith Buffer->getBufferEnd()); 30372a6edb30SRichard Smith SourceLocation Start = L.getSourceLocation(); 3038beee15e7SBen Langmuir ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir, 3039c192d194SBruno Cardoso Lopes IsSystem); 3040718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 30414ddf2221SDouglas Gregor ParsedModuleMap[File] = Result; 30422a6edb30SRichard Smith 30438128f332SRichard Smith if (Offset) { 30448128f332SRichard Smith auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation()); 30458128f332SRichard Smith assert(Loc.first == ID && "stopped in a different file?"); 30468128f332SRichard Smith *Offset = Loc.second; 30478128f332SRichard Smith } 30488128f332SRichard Smith 30492a6edb30SRichard Smith // Notify callbacks that we parsed it. 30502a6edb30SRichard Smith for (const auto &Cb : Callbacks) 30512a6edb30SRichard Smith Cb->moduleMapFileRead(Start, *File, IsSystem); 30528587dfd9SBruno Cardoso Lopes 3053718292f2SDouglas Gregor return Result; 3054718292f2SDouglas Gregor } 3055