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, 47699cfccdcSJan Svoboda StringRef Filename, FileEntryRef File) { 47792669ee4SDaniel Jasper // No errors for indirect modules. This may be a bit of a problem for modules 47892669ee4SDaniel Jasper // with no source files. 47971e1a64fSBen Langmuir if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule)) 48092669ee4SDaniel Jasper return; 48192669ee4SDaniel Jasper 482040e1266SRichard Smith if (RequestingModule) { 48392669ee4SDaniel Jasper resolveUses(RequestingModule, /*Complain=*/false); 4848f4ea36bSAdam Czachorowski resolveHeaderDirectives(RequestingModule, /*File=*/llvm::None); 485040e1266SRichard Smith } 48692669ee4SDaniel Jasper 48771e1a64fSBen Langmuir bool Excluded = false; 488d2d442caSCraig Topper Module *Private = nullptr; 489d2d442caSCraig Topper Module *NotUsed = nullptr; 49071e1a64fSBen Langmuir 49171e1a64fSBen Langmuir HeadersMap::iterator Known = findKnownHeader(File); 49271e1a64fSBen Langmuir if (Known != Headers.end()) { 49371e1a64fSBen Langmuir for (const KnownHeader &Header : Known->second) { 49492669ee4SDaniel Jasper // Remember private headers for later printing of a diagnostic. 4954eb8393cSRichard Smith if (violatesPrivateInclude(RequestingModule, File, Header)) { 49671e1a64fSBen Langmuir Private = Header.getModule(); 49792669ee4SDaniel Jasper continue; 49892669ee4SDaniel Jasper } 49992669ee4SDaniel Jasper 50092669ee4SDaniel Jasper // If uses need to be specified explicitly, we are only allowed to return 50192669ee4SDaniel Jasper // modules that are explicitly used by the requesting module. 50292669ee4SDaniel Jasper if (RequestingModule && LangOpts.ModulesDeclUse && 5038f4d3ff1SRichard Smith !RequestingModule->directlyUses(Header.getModule())) { 50471e1a64fSBen Langmuir NotUsed = Header.getModule(); 50592669ee4SDaniel Jasper continue; 50692669ee4SDaniel Jasper } 50792669ee4SDaniel Jasper 50892669ee4SDaniel Jasper // We have found a module that we can happily use. 50992669ee4SDaniel Jasper return; 51092669ee4SDaniel Jasper } 511feb54b6dSRichard Smith 512feb54b6dSRichard Smith Excluded = true; 51371e1a64fSBen Langmuir } 51492669ee4SDaniel Jasper 51592669ee4SDaniel Jasper // We have found a header, but it is private. 516d2d442caSCraig Topper if (Private) { 51711152dd5SRichard Smith Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module) 51892669ee4SDaniel Jasper << Filename; 51992669ee4SDaniel Jasper return; 52092669ee4SDaniel Jasper } 52192669ee4SDaniel Jasper 52292669ee4SDaniel Jasper // We have found a module, but we don't use it. 523d2d442caSCraig Topper if (NotUsed) { 52411152dd5SRichard Smith Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) 5254ea330c8SDaniel Jasper << RequestingModule->getTopLevelModule()->Name << Filename; 52692669ee4SDaniel Jasper return; 52792669ee4SDaniel Jasper } 52892669ee4SDaniel Jasper 52971e1a64fSBen Langmuir if (Excluded || isHeaderInUmbrellaDirs(File)) 53071e1a64fSBen Langmuir return; 53171e1a64fSBen Langmuir 53271e1a64fSBen Langmuir // At this point, only non-modular includes remain. 53371e1a64fSBen Langmuir 5345904c41eSBenjamin Kramer if (RequestingModule && LangOpts.ModulesStrictDeclUse) { 53511152dd5SRichard Smith Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) 5364ea330c8SDaniel Jasper << RequestingModule->getTopLevelModule()->Name << Filename; 537a67e4d32SManman Ren } else if (RequestingModule && RequestingModuleIsModuleInterface && 538a67e4d32SManman Ren LangOpts.isCompilingModule()) { 539a67e4d32SManman Ren // Do not diagnose when we are not compiling a module. 54071e1a64fSBen Langmuir diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ? 54171e1a64fSBen Langmuir diag::warn_non_modular_include_in_framework_module : 54271e1a64fSBen Langmuir diag::warn_non_modular_include_in_module; 54370a7738fSManman Ren Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName() 54499cfccdcSJan Svoboda << File.getName(); 54571e1a64fSBen Langmuir } 54692669ee4SDaniel Jasper } 54792669ee4SDaniel Jasper 548ec87a50aSRichard Smith static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New, 549ec87a50aSRichard Smith const ModuleMap::KnownHeader &Old) { 5508b7c0398SSean Silva // Prefer available modules. 5516bc75023SRichard Smith // FIXME: Considering whether the module is available rather than merely 5526bc75023SRichard Smith // importable is non-hermetic and can result in surprising behavior for 5536bc75023SRichard Smith // prebuilt modules. Consider only checking for importability here. 5548b7c0398SSean Silva if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable()) 5558b7c0398SSean Silva return true; 5568b7c0398SSean Silva 557ec87a50aSRichard Smith // Prefer a public header over a private header. 558ec87a50aSRichard Smith if ((New.getRole() & ModuleMap::PrivateHeader) != 559ec87a50aSRichard Smith (Old.getRole() & ModuleMap::PrivateHeader)) 560ec87a50aSRichard Smith return !(New.getRole() & ModuleMap::PrivateHeader); 561ec87a50aSRichard Smith 562ec87a50aSRichard Smith // Prefer a non-textual header over a textual header. 563ec87a50aSRichard Smith if ((New.getRole() & ModuleMap::TextualHeader) != 564ec87a50aSRichard Smith (Old.getRole() & ModuleMap::TextualHeader)) 565ec87a50aSRichard Smith return !(New.getRole() & ModuleMap::TextualHeader); 566ec87a50aSRichard Smith 567ec87a50aSRichard Smith // Don't have a reason to choose between these. Just keep the first one. 568ec87a50aSRichard Smith return false; 569ec87a50aSRichard Smith } 570ec87a50aSRichard Smith 571ed84df00SBruno Cardoso Lopes ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File, 572ed84df00SBruno Cardoso Lopes bool AllowTextual) { 573306d8920SRichard Smith auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader { 574ed84df00SBruno Cardoso Lopes if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader) 575afd1b1c9SEugene Zelenko return {}; 576306d8920SRichard Smith return R; 577306d8920SRichard Smith }; 578306d8920SRichard Smith 5794881e8b2SSean Silva HeadersMap::iterator Known = findKnownHeader(File); 5801fb5c3a6SDouglas Gregor if (Known != Headers.end()) { 581202210b3SRichard Smith ModuleMap::KnownHeader Result; 58297da9178SDaniel Jasper // Iterate over all modules that 'File' is part of to find the best fit. 5834881e8b2SSean Silva for (KnownHeader &H : Known->second) { 5847e82e019SRichard Smith // Prefer a header from the source module over all others. 5857e82e019SRichard Smith if (H.getModule()->getTopLevelModule() == SourceModule) 5862f633e7cSRichard Smith return MakeResult(H); 5874881e8b2SSean Silva if (!Result || isBetterKnownHeader(H, Result)) 5884881e8b2SSean Silva Result = H; 58997da9178SDaniel Jasper } 590306d8920SRichard Smith return MakeResult(Result); 5911fb5c3a6SDouglas Gregor } 592ab0c8a84SDouglas Gregor 593386bb073SRichard Smith return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File)); 594386bb073SRichard Smith } 595386bb073SRichard Smith 596386bb073SRichard Smith ModuleMap::KnownHeader 597386bb073SRichard Smith ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) { 598386bb073SRichard Smith assert(!Headers.count(File) && "already have a module for this header"); 599386bb073SRichard Smith 600f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs; 6014469138eSBen Langmuir KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs); 6024469138eSBen Langmuir if (H) { 6034469138eSBen Langmuir Module *Result = H.getModule(); 604930a85ccSDouglas Gregor 605930a85ccSDouglas Gregor // Search up the module stack until we find a module with an umbrella 60673141fa9SDouglas Gregor // directory. 607930a85ccSDouglas Gregor Module *UmbrellaModule = Result; 60873141fa9SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 609930a85ccSDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 610930a85ccSDouglas Gregor 611930a85ccSDouglas Gregor if (UmbrellaModule->InferSubmodules) { 6129d6448b1SBen Langmuir const FileEntry *UmbrellaModuleMap = 6139d6448b1SBen Langmuir getModuleMapFileForUniquing(UmbrellaModule); 6149d6448b1SBen Langmuir 615a89c5ac4SDouglas Gregor // Infer submodules for each of the directories we found between 616a89c5ac4SDouglas Gregor // the directory of the umbrella header and the directory where 617a89c5ac4SDouglas Gregor // the actual header is located. 6189458f82dSDouglas Gregor bool Explicit = UmbrellaModule->InferExplicitSubmodules; 6199458f82dSDouglas Gregor 6208adb6d6dSBenjamin Kramer for (const DirectoryEntry *SkippedDir : llvm::reverse(SkippedDirs)) { 621a89c5ac4SDouglas Gregor // Find or create the module that corresponds to this directory name. 622056396aeSDouglas Gregor SmallString<32> NameBuf; 623056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 6248adb6d6dSBenjamin Kramer llvm::sys::path::stem(SkippedDir->getName()), NameBuf); 6259d6448b1SBen Langmuir Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 6269d6448b1SBen Langmuir Explicit).first; 6279d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = UmbrellaModuleMap; 628ffbafa2aSBen Langmuir Result->IsInferred = true; 629a89c5ac4SDouglas Gregor 630a89c5ac4SDouglas Gregor // Associate the module and the directory. 6318adb6d6dSBenjamin Kramer UmbrellaDirs[SkippedDir] = Result; 632a89c5ac4SDouglas Gregor 633a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 634a89c5ac4SDouglas Gregor // wildcard to the set of exports. 635930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 636d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 637a89c5ac4SDouglas Gregor } 638a89c5ac4SDouglas Gregor 639a89c5ac4SDouglas Gregor // Infer a submodule with the same name as this header file. 640056396aeSDouglas Gregor SmallString<32> NameBuf; 641056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 642056396aeSDouglas Gregor llvm::sys::path::stem(File->getName()), NameBuf); 6439d6448b1SBen Langmuir Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 6449d6448b1SBen Langmuir Explicit).first; 6459d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = UmbrellaModuleMap; 646ffbafa2aSBen Langmuir Result->IsInferred = true; 6473c5305c1SArgyrios Kyrtzidis Result->addTopHeader(File); 648a89c5ac4SDouglas Gregor 649a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 650a89c5ac4SDouglas Gregor // wildcard to the set of exports. 651930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 652d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 653a89c5ac4SDouglas Gregor } else { 654a89c5ac4SDouglas Gregor // Record each of the directories we stepped through as being part of 655a89c5ac4SDouglas Gregor // the module we found, since the umbrella header covers them all. 656a89c5ac4SDouglas Gregor for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I) 657a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I]] = Result; 658a89c5ac4SDouglas Gregor } 659a89c5ac4SDouglas Gregor 660386bb073SRichard Smith KnownHeader Header(Result, NormalHeader); 661386bb073SRichard Smith Headers[File].push_back(Header); 662386bb073SRichard Smith return Header; 663a89c5ac4SDouglas Gregor } 664a89c5ac4SDouglas Gregor 665afd1b1c9SEugene Zelenko return {}; 666ab0c8a84SDouglas Gregor } 667ab0c8a84SDouglas Gregor 668386bb073SRichard Smith ArrayRef<ModuleMap::KnownHeader> 6690a088eadSRichard Smith ModuleMap::findAllModulesForHeader(const FileEntry *File) { 6700a088eadSRichard Smith HeadersMap::iterator Known = findKnownHeader(File); 6710a088eadSRichard Smith if (Known != Headers.end()) 6720a088eadSRichard Smith return Known->second; 6730a088eadSRichard Smith 6740a088eadSRichard Smith if (findOrCreateModuleForHeaderInUmbrellaDir(File)) 6750a088eadSRichard Smith return Headers.find(File)->second; 6760a088eadSRichard Smith 6770a088eadSRichard Smith return None; 6780a088eadSRichard Smith } 6790a088eadSRichard Smith 6800a088eadSRichard Smith ArrayRef<ModuleMap::KnownHeader> 6810a088eadSRichard Smith ModuleMap::findResolvedModulesForHeader(const FileEntry *File) const { 6820a088eadSRichard Smith // FIXME: Is this necessary? 683040e1266SRichard Smith resolveHeaderDirectives(File); 684386bb073SRichard Smith auto It = Headers.find(File); 685386bb073SRichard Smith if (It == Headers.end()) 686386bb073SRichard Smith return None; 687386bb073SRichard Smith return It->second; 688386bb073SRichard Smith } 689386bb073SRichard Smith 690e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const { 691d2d442caSCraig Topper return isHeaderUnavailableInModule(Header, nullptr); 69250996ce1SRichard Smith } 69350996ce1SRichard Smith 69462bcd925SDmitri Gribenko bool 69562bcd925SDmitri Gribenko ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, 69662bcd925SDmitri Gribenko const Module *RequestingModule) const { 697040e1266SRichard Smith resolveHeaderDirectives(Header); 698e4412640SArgyrios Kyrtzidis HeadersMap::const_iterator Known = Headers.find(Header); 69997da9178SDaniel Jasper if (Known != Headers.end()) { 70097da9178SDaniel Jasper for (SmallVectorImpl<KnownHeader>::const_iterator 70197da9178SDaniel Jasper I = Known->second.begin(), 70297da9178SDaniel Jasper E = Known->second.end(); 70397da9178SDaniel Jasper I != E; ++I) { 704052d95a6SBruno Cardoso Lopes 705052d95a6SBruno Cardoso Lopes if (I->isAvailable() && 706052d95a6SBruno Cardoso Lopes (!RequestingModule || 707052d95a6SBruno Cardoso Lopes I->getModule()->isSubModuleOf(RequestingModule))) { 708052d95a6SBruno Cardoso Lopes // When no requesting module is available, the caller is looking if a 709052d95a6SBruno Cardoso Lopes // header is part a module by only looking into the module map. This is 710052d95a6SBruno Cardoso Lopes // done by warn_uncovered_module_header checks; don't consider textual 711052d95a6SBruno Cardoso Lopes // headers part of it in this mode, otherwise we get misleading warnings 712052d95a6SBruno Cardoso Lopes // that a umbrella header is not including a textual header. 713052d95a6SBruno Cardoso Lopes if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader) 714052d95a6SBruno Cardoso Lopes continue; 71597da9178SDaniel Jasper return false; 71697da9178SDaniel Jasper } 717052d95a6SBruno Cardoso Lopes } 71897da9178SDaniel Jasper return true; 71997da9178SDaniel Jasper } 7201fb5c3a6SDouglas Gregor 7211fb5c3a6SDouglas Gregor const DirectoryEntry *Dir = Header->getDir(); 722f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs; 7231fb5c3a6SDouglas Gregor StringRef DirName = Dir->getName(); 7241fb5c3a6SDouglas Gregor 72550996ce1SRichard Smith auto IsUnavailable = [&](const Module *M) { 72650996ce1SRichard Smith return !M->isAvailable() && (!RequestingModule || 72750996ce1SRichard Smith M->isSubModuleOf(RequestingModule)); 72850996ce1SRichard Smith }; 72950996ce1SRichard Smith 7301fb5c3a6SDouglas Gregor // Keep walking up the directory hierarchy, looking for a directory with 7311fb5c3a6SDouglas Gregor // an umbrella header. 7321fb5c3a6SDouglas Gregor do { 733e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir 7341fb5c3a6SDouglas Gregor = UmbrellaDirs.find(Dir); 7351fb5c3a6SDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 7361fb5c3a6SDouglas Gregor Module *Found = KnownDir->second; 73750996ce1SRichard Smith if (IsUnavailable(Found)) 7381fb5c3a6SDouglas Gregor return true; 7391fb5c3a6SDouglas Gregor 7401fb5c3a6SDouglas Gregor // Search up the module stack until we find a module with an umbrella 7411fb5c3a6SDouglas Gregor // directory. 7421fb5c3a6SDouglas Gregor Module *UmbrellaModule = Found; 7431fb5c3a6SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 7441fb5c3a6SDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 7451fb5c3a6SDouglas Gregor 7461fb5c3a6SDouglas Gregor if (UmbrellaModule->InferSubmodules) { 7478adb6d6dSBenjamin Kramer for (const DirectoryEntry *SkippedDir : llvm::reverse(SkippedDirs)) { 7481fb5c3a6SDouglas Gregor // Find or create the module that corresponds to this directory name. 749056396aeSDouglas Gregor SmallString<32> NameBuf; 750056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 7518adb6d6dSBenjamin Kramer llvm::sys::path::stem(SkippedDir->getName()), NameBuf); 7521fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 7531fb5c3a6SDouglas Gregor if (!Found) 7541fb5c3a6SDouglas Gregor return false; 75550996ce1SRichard Smith if (IsUnavailable(Found)) 7561fb5c3a6SDouglas Gregor return true; 7571fb5c3a6SDouglas Gregor } 7581fb5c3a6SDouglas Gregor 7591fb5c3a6SDouglas Gregor // Infer a submodule with the same name as this header file. 760056396aeSDouglas Gregor SmallString<32> NameBuf; 761056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 762056396aeSDouglas Gregor llvm::sys::path::stem(Header->getName()), 763056396aeSDouglas Gregor NameBuf); 7641fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 7651fb5c3a6SDouglas Gregor if (!Found) 7661fb5c3a6SDouglas Gregor return false; 7671fb5c3a6SDouglas Gregor } 7681fb5c3a6SDouglas Gregor 76950996ce1SRichard Smith return IsUnavailable(Found); 7701fb5c3a6SDouglas Gregor } 7711fb5c3a6SDouglas Gregor 7721fb5c3a6SDouglas Gregor SkippedDirs.push_back(Dir); 7731fb5c3a6SDouglas Gregor 7741fb5c3a6SDouglas Gregor // Retrieve our parent path. 7751fb5c3a6SDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 7761fb5c3a6SDouglas Gregor if (DirName.empty()) 7771fb5c3a6SDouglas Gregor break; 7781fb5c3a6SDouglas Gregor 7791fb5c3a6SDouglas Gregor // Resolve the parent path to a directory entry. 7808d323d15SHarlan Haskins if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName)) 7818d323d15SHarlan Haskins Dir = *DirEntry; 7828d323d15SHarlan Haskins else 7838d323d15SHarlan Haskins Dir = nullptr; 7841fb5c3a6SDouglas Gregor } while (Dir); 7851fb5c3a6SDouglas Gregor 7861fb5c3a6SDouglas Gregor return false; 7871fb5c3a6SDouglas Gregor } 7881fb5c3a6SDouglas Gregor 789e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const { 790e4412640SArgyrios Kyrtzidis llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name); 79188bdfb0eSDouglas Gregor if (Known != Modules.end()) 79288bdfb0eSDouglas Gregor return Known->getValue(); 79388bdfb0eSDouglas Gregor 794d2d442caSCraig Topper return nullptr; 79588bdfb0eSDouglas Gregor } 79688bdfb0eSDouglas Gregor 797e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name, 798e4412640SArgyrios Kyrtzidis Module *Context) const { 7992b82c2a5SDouglas Gregor for(; Context; Context = Context->Parent) { 8002b82c2a5SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Context)) 8012b82c2a5SDouglas Gregor return Sub; 8022b82c2a5SDouglas Gregor } 8032b82c2a5SDouglas Gregor 8042b82c2a5SDouglas Gregor return findModule(Name); 8052b82c2a5SDouglas Gregor } 8062b82c2a5SDouglas Gregor 807e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{ 8082b82c2a5SDouglas Gregor if (!Context) 8092b82c2a5SDouglas Gregor return findModule(Name); 8102b82c2a5SDouglas Gregor 811eb90e830SDouglas Gregor return Context->findSubmodule(Name); 8122b82c2a5SDouglas Gregor } 8132b82c2a5SDouglas Gregor 814c192d194SBruno Cardoso Lopes std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name, 815c192d194SBruno Cardoso Lopes Module *Parent, 816c192d194SBruno Cardoso Lopes bool IsFramework, 817c192d194SBruno Cardoso Lopes bool IsExplicit) { 81869021974SDouglas Gregor // Try to find an existing module with this name. 819eb90e830SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Parent)) 820eb90e830SDouglas Gregor return std::make_pair(Sub, false); 82169021974SDouglas Gregor 82269021974SDouglas Gregor // Create a new module with this name. 8239ffe5a35SDavid Blaikie Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, 8249ffe5a35SDavid Blaikie IsExplicit, NumCreatedModules++); 8256f722b4eSArgyrios Kyrtzidis if (!Parent) { 8267e82e019SRichard Smith if (LangOpts.CurrentModule == Name) 8277e82e019SRichard Smith SourceModule = Result; 82869021974SDouglas Gregor Modules[Name] = Result; 829c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID; 8306f722b4eSArgyrios Kyrtzidis } 83169021974SDouglas Gregor return std::make_pair(Result, true); 83269021974SDouglas Gregor } 83369021974SDouglas Gregor 834e587372fSChuanqi Xu Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc, 835e587372fSChuanqi Xu Module *Parent) { 836e587372fSChuanqi Xu auto *Result = new Module("<global>", Loc, Parent, /*IsFramework*/ false, 837e587372fSChuanqi Xu /*IsExplicit*/ true, NumCreatedModules++); 838e587372fSChuanqi Xu Result->Kind = Module::GlobalModuleFragment; 839e587372fSChuanqi Xu // If the created module isn't owned by a parent, send it to PendingSubmodules 840e587372fSChuanqi Xu // to wait for its parent. 841e587372fSChuanqi Xu if (!Result->Parent) 842e587372fSChuanqi Xu PendingSubmodules.emplace_back(Result); 843e587372fSChuanqi Xu return Result; 844dd8b5337SRichard Smith } 845dd8b5337SRichard Smith 846a5bbbfefSRichard Smith Module * 847a5bbbfefSRichard Smith ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent, 848a5bbbfefSRichard Smith SourceLocation Loc) { 849a5bbbfefSRichard Smith auto *Result = 850a5bbbfefSRichard Smith new Module("<private>", Loc, Parent, /*IsFramework*/ false, 851a5bbbfefSRichard Smith /*IsExplicit*/ true, NumCreatedModules++); 852a5bbbfefSRichard Smith Result->Kind = Module::PrivateModuleFragment; 853a5bbbfefSRichard Smith return Result; 854a5bbbfefSRichard Smith } 855a5bbbfefSRichard Smith 856bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc, 857dd8b5337SRichard Smith StringRef Name, 858dd8b5337SRichard Smith Module *GlobalModule) { 859bbcc9f04SRichard Smith assert(LangOpts.CurrentModule == Name && "module name mismatch"); 860bbcc9f04SRichard Smith assert(!Modules[Name] && "redefining existing module"); 861bbcc9f04SRichard Smith 862bbcc9f04SRichard Smith auto *Result = 863bbcc9f04SRichard Smith new Module(Name, Loc, nullptr, /*IsFramework*/ false, 864bbcc9f04SRichard Smith /*IsExplicit*/ false, NumCreatedModules++); 865145e15a3SRichard Smith Result->Kind = Module::ModuleInterfaceUnit; 866bbcc9f04SRichard Smith Modules[Name] = SourceModule = Result; 867bbcc9f04SRichard Smith 868dd8b5337SRichard Smith // Reparent the current global module fragment as a submodule of this module. 869d6509cf2SRichard Smith for (auto &Submodule : PendingSubmodules) { 870d6509cf2SRichard Smith Submodule->setParent(Result); 871d6509cf2SRichard Smith Submodule.release(); // now owned by parent 872d6509cf2SRichard Smith } 873d6509cf2SRichard Smith PendingSubmodules.clear(); 874dd8b5337SRichard Smith 875bbcc9f04SRichard Smith // Mark the main source file as being within the newly-created module so that 876bbcc9f04SRichard Smith // declarations and macros are properly visibility-restricted to it. 877bbcc9f04SRichard Smith auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()); 878bbcc9f04SRichard Smith assert(MainFile && "no input file for module interface"); 879bbcc9f04SRichard Smith Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader)); 880bbcc9f04SRichard Smith 881bbcc9f04SRichard Smith return Result; 882bbcc9f04SRichard Smith } 883bbcc9f04SRichard Smith 884d6509cf2SRichard Smith Module *ModuleMap::createHeaderModule(StringRef Name, 885d6509cf2SRichard Smith ArrayRef<Module::Header> Headers) { 886d6509cf2SRichard Smith assert(LangOpts.CurrentModule == Name && "module name mismatch"); 887d6509cf2SRichard Smith assert(!Modules[Name] && "redefining existing module"); 888d6509cf2SRichard Smith 889d6509cf2SRichard Smith auto *Result = 890d6509cf2SRichard Smith new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false, 891d6509cf2SRichard Smith /*IsExplicit*/ false, NumCreatedModules++); 892d6509cf2SRichard Smith Result->Kind = Module::ModuleInterfaceUnit; 893d6509cf2SRichard Smith Modules[Name] = SourceModule = Result; 894d6509cf2SRichard Smith 895d6509cf2SRichard Smith for (const Module::Header &H : Headers) { 896d6509cf2SRichard Smith auto *M = new Module(H.NameAsWritten, SourceLocation(), Result, 897d6509cf2SRichard Smith /*IsFramework*/ false, 898d6509cf2SRichard Smith /*IsExplicit*/ true, NumCreatedModules++); 899d6509cf2SRichard Smith // Header modules are implicitly 'export *'. 900d6509cf2SRichard Smith M->Exports.push_back(Module::ExportDecl(nullptr, true)); 901d6509cf2SRichard Smith addHeader(M, H, NormalHeader); 902d6509cf2SRichard Smith } 903d6509cf2SRichard Smith 904d6509cf2SRichard Smith return Result; 905d6509cf2SRichard Smith } 906d6509cf2SRichard Smith 9076c0e60e8SIain Sandoe Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name, 9086c0e60e8SIain Sandoe Module::Header H) { 9096c0e60e8SIain Sandoe assert(LangOpts.CurrentModule == Name && "module name mismatch"); 9106c0e60e8SIain Sandoe assert(!Modules[Name] && "redefining existing module"); 9116c0e60e8SIain Sandoe 9126c0e60e8SIain Sandoe auto *Result = new Module(Name, Loc, nullptr, /*IsFramework*/ false, 9136c0e60e8SIain Sandoe /*IsExplicit*/ false, NumCreatedModules++); 9146c0e60e8SIain Sandoe Result->Kind = Module::ModuleHeaderUnit; 9156c0e60e8SIain Sandoe Modules[Name] = SourceModule = Result; 9166c0e60e8SIain Sandoe addHeader(Result, H, NormalHeader); 9176c0e60e8SIain Sandoe return Result; 9186c0e60e8SIain Sandoe } 9196c0e60e8SIain Sandoe 9209fc8faf9SAdrian Prantl /// For a framework module, infer the framework against which we 92111dfe6feSDouglas Gregor /// should link. 92211dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir, 92311dfe6feSDouglas Gregor FileManager &FileMgr) { 92411dfe6feSDouglas Gregor assert(Mod->IsFramework && "Can only infer linking for framework modules"); 92511dfe6feSDouglas Gregor assert(!Mod->isSubFramework() && 92611dfe6feSDouglas Gregor "Can only infer linking for top-level frameworks"); 92711dfe6feSDouglas Gregor 92811dfe6feSDouglas Gregor SmallString<128> LibName; 92911dfe6feSDouglas Gregor LibName += FrameworkDir->getName(); 93011dfe6feSDouglas Gregor llvm::sys::path::append(LibName, Mod->Name); 9318aaae5a9SJuergen Ributzka 9328aaae5a9SJuergen Ributzka // The library name of a framework has more than one possible extension since 9338aaae5a9SJuergen Ributzka // the introduction of the text-based dynamic library format. We need to check 9348aaae5a9SJuergen Ributzka // for both before we give up. 9358013e81dSBenjamin Kramer for (const char *extension : {"", ".tbd"}) { 9368aaae5a9SJuergen Ributzka llvm::sys::path::replace_extension(LibName, extension); 93711dfe6feSDouglas Gregor if (FileMgr.getFile(LibName)) { 93811dfe6feSDouglas Gregor Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name, 93911dfe6feSDouglas Gregor /*IsFramework=*/true)); 9408aaae5a9SJuergen Ributzka return; 9418aaae5a9SJuergen Ributzka } 94211dfe6feSDouglas Gregor } 94311dfe6feSDouglas Gregor } 94411dfe6feSDouglas Gregor 945a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 946a525400dSBen Langmuir bool IsSystem, Module *Parent) { 947c1d88ea5SBen Langmuir Attributes Attrs; 948c1d88ea5SBen Langmuir Attrs.IsSystem = IsSystem; 949a525400dSBen Langmuir return inferFrameworkModule(FrameworkDir, Attrs, Parent); 950c1d88ea5SBen Langmuir } 951c1d88ea5SBen Langmuir 952a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 953c1d88ea5SBen Langmuir Attributes Attrs, Module *Parent) { 954a525400dSBen Langmuir // Note: as an egregious but useful hack we use the real path here, because 955a525400dSBen Langmuir // we might be looking at an embedded framework that symlinks out to a 956a525400dSBen Langmuir // top-level framework, and we need to infer as if we were naming the 957a525400dSBen Langmuir // top-level framework. 958a525400dSBen Langmuir StringRef FrameworkDirName = 959a525400dSBen Langmuir SourceMgr.getFileManager().getCanonicalName(FrameworkDir); 960a525400dSBen Langmuir 961a525400dSBen Langmuir // In case this is a case-insensitive filesystem, use the canonical 962a525400dSBen Langmuir // directory name as the ModuleName, since modules are case-sensitive. 963a525400dSBen Langmuir // FIXME: we should be able to give a fix-it hint for the correct spelling. 964a525400dSBen Langmuir SmallString<32> ModuleNameStorage; 965a525400dSBen Langmuir StringRef ModuleName = sanitizeFilenameAsIdentifier( 966a525400dSBen Langmuir llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage); 967c1d88ea5SBen Langmuir 96856c64013SDouglas Gregor // Check whether we've already found this module. 969e89dbc1dSDouglas Gregor if (Module *Mod = lookupModuleQualified(ModuleName, Parent)) 970e89dbc1dSDouglas Gregor return Mod; 971e89dbc1dSDouglas Gregor 9721f76c4e8SManuel Klimek FileManager &FileMgr = SourceMgr.getFileManager(); 97356c64013SDouglas Gregor 9749194a91dSDouglas Gregor // If the framework has a parent path from which we're allowed to infer 9759194a91dSDouglas Gregor // a framework module, do so. 976beee15e7SBen Langmuir const FileEntry *ModuleMapFile = nullptr; 9779194a91dSDouglas Gregor if (!Parent) { 9784ddf2221SDouglas Gregor // Determine whether we're allowed to infer a module map. 9799194a91dSDouglas Gregor bool canInfer = false; 9804ddf2221SDouglas Gregor if (llvm::sys::path::has_parent_path(FrameworkDirName)) { 9819194a91dSDouglas Gregor // Figure out the parent path. 9824ddf2221SDouglas Gregor StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName); 9838d323d15SHarlan Haskins if (auto ParentDir = FileMgr.getDirectory(Parent)) { 9849194a91dSDouglas Gregor // Check whether we have already looked into the parent directory 9859194a91dSDouglas Gregor // for a module map. 986e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator 9878d323d15SHarlan Haskins inferred = InferredDirectories.find(*ParentDir); 9889194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) { 9899194a91dSDouglas Gregor // We haven't looked here before. Load a module map, if there is 9909194a91dSDouglas Gregor // one. 991984e1df7SBen Langmuir bool IsFrameworkDir = Parent.endswith(".framework"); 9927799ef71SNico Weber if (const FileEntry *ModMapFile = 9938d323d15SHarlan Haskins HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) { 9947799ef71SNico Weber parseModuleMapFile(ModMapFile, Attrs.IsSystem, *ParentDir); 9958d323d15SHarlan Haskins inferred = InferredDirectories.find(*ParentDir); 9969194a91dSDouglas Gregor } 9979194a91dSDouglas Gregor 9989194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) 9999194a91dSDouglas Gregor inferred = InferredDirectories.insert( 10008d323d15SHarlan Haskins std::make_pair(*ParentDir, InferredDirectory())).first; 10019194a91dSDouglas Gregor } 10029194a91dSDouglas Gregor 10039194a91dSDouglas Gregor if (inferred->second.InferModules) { 10049194a91dSDouglas Gregor // We're allowed to infer for this directory, but make sure it's okay 10059194a91dSDouglas Gregor // to infer this particular module. 10064ddf2221SDouglas Gregor StringRef Name = llvm::sys::path::stem(FrameworkDirName); 1007e567f37dSKazu Hirata canInfer = 1008e567f37dSKazu Hirata !llvm::is_contained(inferred->second.ExcludedModules, Name); 10099194a91dSDouglas Gregor 1010c1d88ea5SBen Langmuir Attrs.IsSystem |= inferred->second.Attrs.IsSystem; 1011c1d88ea5SBen Langmuir Attrs.IsExternC |= inferred->second.Attrs.IsExternC; 1012c1d88ea5SBen Langmuir Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive; 1013ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes |= 1014ed84df00SBruno Cardoso Lopes inferred->second.Attrs.NoUndeclaredIncludes; 1015beee15e7SBen Langmuir ModuleMapFile = inferred->second.ModuleMapFile; 10169194a91dSDouglas Gregor } 10179194a91dSDouglas Gregor } 10189194a91dSDouglas Gregor } 10199194a91dSDouglas Gregor 10209194a91dSDouglas Gregor // If we're not allowed to infer a framework module, don't. 10219194a91dSDouglas Gregor if (!canInfer) 1022d2d442caSCraig Topper return nullptr; 1023beee15e7SBen Langmuir } else 10249d6448b1SBen Langmuir ModuleMapFile = getModuleMapFileForUniquing(Parent); 10259194a91dSDouglas Gregor 10269194a91dSDouglas Gregor 102756c64013SDouglas Gregor // Look for an umbrella header. 10282c1dd271SDylan Noblesmith SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 102917381a06SBenjamin Kramer llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h"); 103064d8c781SDuncan P. N. Exon Smith auto UmbrellaHeader = FileMgr.getFile(UmbrellaName); 103156c64013SDouglas Gregor 103256c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the 103356c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good 103456c64013SDouglas Gregor // idea. 103556c64013SDouglas Gregor if (!UmbrellaHeader) 1036d2d442caSCraig Topper return nullptr; 103756c64013SDouglas Gregor 10389d6448b1SBen Langmuir Module *Result = new Module(ModuleName, SourceLocation(), Parent, 1039a7e2cc68SRichard Smith /*IsFramework=*/true, /*IsExplicit=*/false, 1040a7e2cc68SRichard Smith NumCreatedModules++); 10419d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = ModuleMapFile; 10429d6448b1SBen Langmuir Result->IsInferred = true; 10437e82e019SRichard Smith if (!Parent) { 10447e82e019SRichard Smith if (LangOpts.CurrentModule == ModuleName) 1045ba7f2f71SDaniel Jasper SourceModule = Result; 10467e82e019SRichard Smith Modules[ModuleName] = Result; 1047c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID; 1048ba7f2f71SDaniel Jasper } 1049c1d88ea5SBen Langmuir 1050c1d88ea5SBen Langmuir Result->IsSystem |= Attrs.IsSystem; 1051c1d88ea5SBen Langmuir Result->IsExternC |= Attrs.IsExternC; 1052c1d88ea5SBen Langmuir Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive; 1053ed84df00SBruno Cardoso Lopes Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes; 10542b63d15fSRichard Smith Result->Directory = FrameworkDir; 1055a686e1b0SDouglas Gregor 1056d3676d4bSMichael Spencer // Chop off the first framework bit, as that is implied. 1057d3676d4bSMichael Spencer StringRef RelativePath = UmbrellaName.str().substr( 1058d3676d4bSMichael Spencer Result->getTopLevelModule()->Directory->getName().size()); 1059d3676d4bSMichael Spencer RelativePath = llvm::sys::path::relative_path(RelativePath); 1060d3676d4bSMichael Spencer 1061322f633cSDouglas Gregor // umbrella header "umbrella-header-name" 1062d3676d4bSMichael Spencer setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h", RelativePath); 1063d8bd7537SDouglas Gregor 1064d8bd7537SDouglas Gregor // export * 1065d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 1066d8bd7537SDouglas Gregor 1067a89c5ac4SDouglas Gregor // module * { export * } 1068a89c5ac4SDouglas Gregor Result->InferSubmodules = true; 1069a89c5ac4SDouglas Gregor Result->InferExportWildcard = true; 1070a89c5ac4SDouglas Gregor 1071e89dbc1dSDouglas Gregor // Look for subframeworks. 1072c080917eSRafael Espindola std::error_code EC; 10732c1dd271SDylan Noblesmith SmallString<128> SubframeworksDirName 1074ddaa69cbSDouglas Gregor = StringRef(FrameworkDir->getName()); 1075e89dbc1dSDouglas Gregor llvm::sys::path::append(SubframeworksDirName, "Frameworks"); 10762d4d8cb3SBenjamin Kramer llvm::sys::path::native(SubframeworksDirName); 1077db8a7422SDuncan P. N. Exon Smith llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); 1078fc51490bSJonas Devlieghere for (llvm::vfs::directory_iterator 1079fc51490bSJonas Devlieghere Dir = FS.dir_begin(SubframeworksDirName, EC), 1080b171a59bSBruno Cardoso Lopes DirEnd; 1081e89dbc1dSDouglas Gregor Dir != DirEnd && !EC; Dir.increment(EC)) { 10820ae00567SSam McCall if (!StringRef(Dir->path()).endswith(".framework")) 1083e89dbc1dSDouglas Gregor continue; 1084f2161a70SDouglas Gregor 10858d323d15SHarlan Haskins if (auto SubframeworkDir = 10860ae00567SSam McCall FileMgr.getDirectory(Dir->path())) { 108707c22b78SDouglas Gregor // Note: as an egregious but useful hack, we use the real path here and 108807c22b78SDouglas Gregor // check whether it is actually a subdirectory of the parent directory. 108907c22b78SDouglas Gregor // This will not be the case if the 'subframework' is actually a symlink 109007c22b78SDouglas Gregor // out to a top-level framework. 10918d323d15SHarlan Haskins StringRef SubframeworkDirName = 10928d323d15SHarlan Haskins FileMgr.getCanonicalName(*SubframeworkDir); 109307c22b78SDouglas Gregor bool FoundParent = false; 109407c22b78SDouglas Gregor do { 109507c22b78SDouglas Gregor // Get the parent directory name. 109607c22b78SDouglas Gregor SubframeworkDirName 109707c22b78SDouglas Gregor = llvm::sys::path::parent_path(SubframeworkDirName); 109807c22b78SDouglas Gregor if (SubframeworkDirName.empty()) 109907c22b78SDouglas Gregor break; 110007c22b78SDouglas Gregor 11018d323d15SHarlan Haskins if (auto SubDir = FileMgr.getDirectory(SubframeworkDirName)) { 11028d323d15SHarlan Haskins if (*SubDir == FrameworkDir) { 110307c22b78SDouglas Gregor FoundParent = true; 110407c22b78SDouglas Gregor break; 110507c22b78SDouglas Gregor } 11068d323d15SHarlan Haskins } 110707c22b78SDouglas Gregor } while (true); 110807c22b78SDouglas Gregor 110907c22b78SDouglas Gregor if (!FoundParent) 111007c22b78SDouglas Gregor continue; 111107c22b78SDouglas Gregor 1112e89dbc1dSDouglas Gregor // FIXME: Do we want to warn about subframeworks without umbrella headers? 11138d323d15SHarlan Haskins inferFrameworkModule(*SubframeworkDir, Attrs, Result); 1114e89dbc1dSDouglas Gregor } 1115e89dbc1dSDouglas Gregor } 1116e89dbc1dSDouglas Gregor 111711dfe6feSDouglas Gregor // If the module is a top-level framework, automatically link against the 111811dfe6feSDouglas Gregor // framework. 111911dfe6feSDouglas Gregor if (!Result->isSubFramework()) { 112011dfe6feSDouglas Gregor inferFrameworkLink(Result, FrameworkDir, FileMgr); 112111dfe6feSDouglas Gregor } 112211dfe6feSDouglas Gregor 112356c64013SDouglas Gregor return Result; 112456c64013SDouglas Gregor } 112556c64013SDouglas Gregor 11268587dfd9SBruno Cardoso Lopes Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework, 11278587dfd9SBruno Cardoso Lopes Module *ShadowingModule) { 11288587dfd9SBruno Cardoso Lopes 11298587dfd9SBruno Cardoso Lopes // Create a new module with this name. 11308587dfd9SBruno Cardoso Lopes Module *Result = 11318587dfd9SBruno Cardoso Lopes new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework, 11328587dfd9SBruno Cardoso Lopes /*IsExplicit=*/false, NumCreatedModules++); 11338587dfd9SBruno Cardoso Lopes Result->ShadowingModule = ShadowingModule; 1134fc76b4adSRichard Smith Result->markUnavailable(/*Unimportable*/true); 1135c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID; 11368587dfd9SBruno Cardoso Lopes ShadowModules.push_back(Result); 11378587dfd9SBruno Cardoso Lopes 11388587dfd9SBruno Cardoso Lopes return Result; 11398587dfd9SBruno Cardoso Lopes } 11408587dfd9SBruno Cardoso Lopes 1141d3676d4bSMichael Spencer void ModuleMap::setUmbrellaHeader( 1142d3676d4bSMichael Spencer Module *Mod, const FileEntry *UmbrellaHeader, const Twine &NameAsWritten, 1143d3676d4bSMichael Spencer const Twine &PathRelativeToRootModuleDirectory) { 114497da9178SDaniel Jasper Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader)); 114564d8c781SDuncan P. N. Exon Smith Mod->Umbrella = UmbrellaHeader; 11462b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 1147d3676d4bSMichael Spencer Mod->UmbrellaRelativeToRootModuleDirectory = 1148d3676d4bSMichael Spencer PathRelativeToRootModuleDirectory.str(); 114964d8c781SDuncan P. N. Exon Smith UmbrellaDirs[UmbrellaHeader->getDir()] = Mod; 1150b3a0fa48SBruno Cardoso Lopes 1151b3a0fa48SBruno Cardoso Lopes // Notify callbacks that we just added a new header. 1152b3a0fa48SBruno Cardoso Lopes for (const auto &Cb : Callbacks) 1153b3a0fa48SBruno Cardoso Lopes Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader); 1154a89c5ac4SDouglas Gregor } 1155a89c5ac4SDouglas Gregor 115664d8c781SDuncan P. N. Exon Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, 1157d3676d4bSMichael Spencer const Twine &NameAsWritten, 1158d3676d4bSMichael Spencer const Twine &PathRelativeToRootModuleDirectory) { 115964d8c781SDuncan P. N. Exon Smith Mod->Umbrella = UmbrellaDir; 11602b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 1161d3676d4bSMichael Spencer Mod->UmbrellaRelativeToRootModuleDirectory = 1162d3676d4bSMichael Spencer PathRelativeToRootModuleDirectory.str(); 1163524e33e1SDouglas Gregor UmbrellaDirs[UmbrellaDir] = Mod; 1164524e33e1SDouglas Gregor } 1165524e33e1SDouglas Gregor 1166040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod, 11679f6020bcSBruno Cardoso Lopes Module::UnresolvedHeaderDirective Header, 11689f6020bcSBruno Cardoso Lopes bool &NeedsFramework) { 1169040e1266SRichard Smith // If there is a builtin counterpart to this file, add it now so it can 1170040e1266SRichard Smith // wrap the system header. 1171040e1266SRichard Smith if (resolveAsBuiltinHeader(Mod, Header)) { 1172040e1266SRichard Smith // If we have both a builtin and system version of the file, the 1173040e1266SRichard Smith // builtin version may want to inject macros into the system header, so 1174040e1266SRichard Smith // force the system header to be treated as a textual header in this 1175040e1266SRichard Smith // case. 1176040e1266SRichard Smith Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole( 1177040e1266SRichard Smith headerKindToRole(Header.Kind) | ModuleMap::TextualHeader)); 1178040e1266SRichard Smith Header.HasBuiltinHeader = true; 11793c1a41adSRichard Smith } 1180040e1266SRichard Smith 1181040e1266SRichard Smith // If possible, don't stat the header until we need to. This requires the 1182040e1266SRichard Smith // user to have provided us with some stat information about the file. 1183040e1266SRichard Smith // FIXME: Add support for lazily stat'ing umbrella headers and excluded 1184040e1266SRichard Smith // headers. 1185040e1266SRichard Smith if ((Header.Size || Header.ModTime) && !Header.IsUmbrella && 1186040e1266SRichard Smith Header.Kind != Module::HK_Excluded) { 1187040e1266SRichard Smith // We expect more variation in mtime than size, so if we're given both, 1188040e1266SRichard Smith // use the mtime as the key. 1189040e1266SRichard Smith if (Header.ModTime) 1190040e1266SRichard Smith LazyHeadersByModTime[*Header.ModTime].push_back(Mod); 1191040e1266SRichard Smith else 1192040e1266SRichard Smith LazyHeadersBySize[*Header.Size].push_back(Mod); 1193040e1266SRichard Smith Mod->UnresolvedHeaders.push_back(Header); 1194040e1266SRichard Smith return; 1195040e1266SRichard Smith } 1196040e1266SRichard Smith 1197040e1266SRichard Smith // We don't have stat information or can't defer looking this file up. 1198040e1266SRichard Smith // Perform the lookup now. 11999f6020bcSBruno Cardoso Lopes resolveHeader(Mod, Header, NeedsFramework); 1200040e1266SRichard Smith } 1201040e1266SRichard Smith 1202040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const { 1203040e1266SRichard Smith auto BySize = LazyHeadersBySize.find(File->getSize()); 1204040e1266SRichard Smith if (BySize != LazyHeadersBySize.end()) { 1205040e1266SRichard Smith for (auto *M : BySize->second) 12068f4ea36bSAdam Czachorowski resolveHeaderDirectives(M, File); 1207040e1266SRichard Smith LazyHeadersBySize.erase(BySize); 1208040e1266SRichard Smith } 1209040e1266SRichard Smith 1210040e1266SRichard Smith auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime()); 1211040e1266SRichard Smith if (ByModTime != LazyHeadersByModTime.end()) { 1212040e1266SRichard Smith for (auto *M : ByModTime->second) 12138f4ea36bSAdam Czachorowski resolveHeaderDirectives(M, File); 1214040e1266SRichard Smith LazyHeadersByModTime.erase(ByModTime); 1215040e1266SRichard Smith } 1216040e1266SRichard Smith } 1217040e1266SRichard Smith 12188f4ea36bSAdam Czachorowski void ModuleMap::resolveHeaderDirectives( 12198f4ea36bSAdam Czachorowski Module *Mod, llvm::Optional<const FileEntry *> File) const { 12209f6020bcSBruno Cardoso Lopes bool NeedsFramework = false; 12218f4ea36bSAdam Czachorowski SmallVector<Module::UnresolvedHeaderDirective, 1> NewHeaders; 1222*cb2c8f69SKazu Hirata const auto Size = File ? File.value()->getSize() : 0; 1223*cb2c8f69SKazu Hirata const auto ModTime = File ? File.value()->getModificationTime() : 0; 12248f4ea36bSAdam Czachorowski 12258f4ea36bSAdam Czachorowski for (auto &Header : Mod->UnresolvedHeaders) { 12268f4ea36bSAdam Czachorowski if (File && ((Header.ModTime && Header.ModTime != ModTime) || 12278f4ea36bSAdam Czachorowski (Header.Size && Header.Size != Size))) 12288f4ea36bSAdam Czachorowski NewHeaders.push_back(Header); 12298f4ea36bSAdam Czachorowski else 1230040e1266SRichard Smith // This operation is logically const; we're just changing how we represent 1231040e1266SRichard Smith // the header information for this file. 12329f6020bcSBruno Cardoso Lopes const_cast<ModuleMap *>(this)->resolveHeader(Mod, Header, NeedsFramework); 12338f4ea36bSAdam Czachorowski } 12348f4ea36bSAdam Czachorowski Mod->UnresolvedHeaders.swap(NewHeaders); 12350e98d938SNAKAMURA Takumi } 1236202210b3SRichard Smith 12373c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header, 1238d8879c85SRichard Smith ModuleHeaderRole Role, bool Imported) { 1239386bb073SRichard Smith KnownHeader KH(Mod, Role); 12403c1a41adSRichard Smith 1241386bb073SRichard Smith // Only add each header to the headers list once. 1242386bb073SRichard Smith // FIXME: Should we diagnose if a header is listed twice in the 1243386bb073SRichard Smith // same module definition? 1244386bb073SRichard Smith auto &HeaderList = Headers[Header.Entry]; 12457cc8fa2dSKazu Hirata if (llvm::is_contained(HeaderList, KH)) 1246386bb073SRichard Smith return; 1247386bb073SRichard Smith 1248386bb073SRichard Smith HeaderList.push_back(KH); 12491ec383c7SPiotr Padlewski Mod->Headers[headerRoleToKind(Role)].push_back(Header); 1250386bb073SRichard Smith 12517e82e019SRichard Smith bool isCompilingModuleHeader = 1252bbcc9f04SRichard Smith LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule; 1253d8879c85SRichard Smith if (!Imported || isCompilingModuleHeader) { 1254d8879c85SRichard Smith // When we import HeaderFileInfo, the external source is expected to 1255d8879c85SRichard Smith // set the isModuleHeader flag itself. 1256d8879c85SRichard Smith HeaderInfo.MarkFileModuleHeader(Header.Entry, Role, 1257d8879c85SRichard Smith isCompilingModuleHeader); 1258d8879c85SRichard Smith } 1259e62cfd7cSBruno Cardoso Lopes 1260e62cfd7cSBruno Cardoso Lopes // Notify callbacks that we just added a new header. 1261e62cfd7cSBruno Cardoso Lopes for (const auto &Cb : Callbacks) 1262f0841790SBruno Cardoso Lopes Cb->moduleMapAddHeader(Header.Entry->getName()); 1263a89c5ac4SDouglas Gregor } 1264a89c5ac4SDouglas Gregor 12653c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) { 1266feb54b6dSRichard Smith // Add this as a known header so we won't implicitly add it to any 1267feb54b6dSRichard Smith // umbrella directory module. 1268feb54b6dSRichard Smith // FIXME: Should we only exclude it from umbrella modules within the 1269feb54b6dSRichard Smith // specified module? 12703c1a41adSRichard Smith (void) Headers[Header.Entry]; 12713c1a41adSRichard Smith 12723c1a41adSRichard Smith Mod->Headers[Module::HK_Excluded].push_back(std::move(Header)); 1273feb54b6dSRichard Smith } 1274feb54b6dSRichard Smith 1275514b636aSDouglas Gregor const FileEntry * 12764b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const { 12771f76c4e8SManuel Klimek if (Module->DefinitionLoc.isInvalid()) 1278d2d442caSCraig Topper return nullptr; 1279514b636aSDouglas Gregor 12801f76c4e8SManuel Klimek return SourceMgr.getFileEntryForID( 12811f76c4e8SManuel Klimek SourceMgr.getFileID(Module->DefinitionLoc)); 1282514b636aSDouglas Gregor } 1283514b636aSDouglas Gregor 12844b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const { 12859d6448b1SBen Langmuir if (M->IsInferred) { 12869d6448b1SBen Langmuir assert(InferredModuleAllowedBy.count(M) && "missing inferred module map"); 12879d6448b1SBen Langmuir return InferredModuleAllowedBy.find(M)->second; 12889d6448b1SBen Langmuir } 12899d6448b1SBen Langmuir return getContainingModuleMapFile(M); 12909d6448b1SBen Langmuir } 12919d6448b1SBen Langmuir 12929d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) { 12939d6448b1SBen Langmuir assert(M->IsInferred && "module not inferred"); 12949d6448b1SBen Langmuir InferredModuleAllowedBy[M] = ModMap; 12959d6448b1SBen Langmuir } 12969d6448b1SBen Langmuir 1297e08464fbSReid Kleckner void ModuleMap::addAdditionalModuleMapFile(const Module *M, 1298e08464fbSReid Kleckner const FileEntry *ModuleMap) { 1299e08464fbSReid Kleckner AdditionalModMaps[M].insert(ModuleMap); 1300e08464fbSReid Kleckner } 1301e08464fbSReid Kleckner 1302cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() { 1303718292f2SDouglas Gregor llvm::errs() << "Modules:"; 1304718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 1305718292f2SDouglas Gregor MEnd = Modules.end(); 1306718292f2SDouglas Gregor M != MEnd; ++M) 1307d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 1308718292f2SDouglas Gregor 1309718292f2SDouglas Gregor llvm::errs() << "Headers:"; 131059527666SDouglas Gregor for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end(); 1311718292f2SDouglas Gregor H != HEnd; ++H) { 131297da9178SDaniel Jasper llvm::errs() << " \"" << H->first->getName() << "\" -> "; 131397da9178SDaniel Jasper for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(), 131497da9178SDaniel Jasper E = H->second.end(); 131597da9178SDaniel Jasper I != E; ++I) { 131697da9178SDaniel Jasper if (I != H->second.begin()) 131797da9178SDaniel Jasper llvm::errs() << ","; 131897da9178SDaniel Jasper llvm::errs() << I->getModule()->getFullModuleName(); 131997da9178SDaniel Jasper } 132097da9178SDaniel Jasper llvm::errs() << "\n"; 1321718292f2SDouglas Gregor } 1322718292f2SDouglas Gregor } 1323718292f2SDouglas Gregor 13242b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) { 132542413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedExports); 132642413141SRichard Smith Mod->UnresolvedExports.clear(); 132742413141SRichard Smith for (auto &UE : Unresolved) { 132842413141SRichard Smith Module::ExportDecl Export = resolveExport(Mod, UE, Complain); 1329f5eedd05SDouglas Gregor if (Export.getPointer() || Export.getInt()) 13302b82c2a5SDouglas Gregor Mod->Exports.push_back(Export); 13312b82c2a5SDouglas Gregor else 133242413141SRichard Smith Mod->UnresolvedExports.push_back(UE); 13332b82c2a5SDouglas Gregor } 133442413141SRichard Smith return !Mod->UnresolvedExports.empty(); 13352b82c2a5SDouglas Gregor } 13362b82c2a5SDouglas Gregor 1337ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) { 133842413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedDirectUses); 133942413141SRichard Smith Mod->UnresolvedDirectUses.clear(); 134042413141SRichard Smith for (auto &UDU : Unresolved) { 134142413141SRichard Smith Module *DirectUse = resolveModuleId(UDU, Mod, Complain); 1342ba7f2f71SDaniel Jasper if (DirectUse) 1343ba7f2f71SDaniel Jasper Mod->DirectUses.push_back(DirectUse); 1344ba7f2f71SDaniel Jasper else 134542413141SRichard Smith Mod->UnresolvedDirectUses.push_back(UDU); 1346ba7f2f71SDaniel Jasper } 134742413141SRichard Smith return !Mod->UnresolvedDirectUses.empty(); 1348ba7f2f71SDaniel Jasper } 1349ba7f2f71SDaniel Jasper 1350fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) { 135142413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedConflicts); 135242413141SRichard Smith Mod->UnresolvedConflicts.clear(); 135342413141SRichard Smith for (auto &UC : Unresolved) { 135442413141SRichard Smith if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) { 1355fb912657SDouglas Gregor Module::Conflict Conflict; 1356fb912657SDouglas Gregor Conflict.Other = OtherMod; 135742413141SRichard Smith Conflict.Message = UC.Message; 1358fb912657SDouglas Gregor Mod->Conflicts.push_back(Conflict); 135942413141SRichard Smith } else 136042413141SRichard Smith Mod->UnresolvedConflicts.push_back(UC); 1361fb912657SDouglas Gregor } 136242413141SRichard Smith return !Mod->UnresolvedConflicts.empty(); 1363fb912657SDouglas Gregor } 1364fb912657SDouglas Gregor 1365718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1366718292f2SDouglas Gregor // Module map file parser 1367718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1368718292f2SDouglas Gregor 1369718292f2SDouglas Gregor namespace clang { 1370afd1b1c9SEugene Zelenko 13719fc8faf9SAdrian Prantl /// A token in a module map file. 1372718292f2SDouglas Gregor struct MMToken { 1373718292f2SDouglas Gregor enum TokenKind { 13741fb5c3a6SDouglas Gregor Comma, 137535b13eceSDouglas Gregor ConfigMacros, 1376fb912657SDouglas Gregor Conflict, 1377718292f2SDouglas Gregor EndOfFile, 1378718292f2SDouglas Gregor HeaderKeyword, 1379718292f2SDouglas Gregor Identifier, 1380a3feee2aSRichard Smith Exclaim, 138159527666SDouglas Gregor ExcludeKeyword, 1382718292f2SDouglas Gregor ExplicitKeyword, 13832b82c2a5SDouglas Gregor ExportKeyword, 1384f0b11de2SDouglas Gregor ExportAsKeyword, 138597292843SDaniel Jasper ExternKeyword, 1386755b2055SDouglas Gregor FrameworkKeyword, 13876ddfca91SDouglas Gregor LinkKeyword, 1388718292f2SDouglas Gregor ModuleKeyword, 13892b82c2a5SDouglas Gregor Period, 1390b53e5483SLawrence Crowl PrivateKeyword, 1391718292f2SDouglas Gregor UmbrellaKeyword, 1392ba7f2f71SDaniel Jasper UseKeyword, 13931fb5c3a6SDouglas Gregor RequiresKeyword, 13942b82c2a5SDouglas Gregor Star, 1395718292f2SDouglas Gregor StringLiteral, 1396040e1266SRichard Smith IntegerLiteral, 1397306d8920SRichard Smith TextualKeyword, 1398718292f2SDouglas Gregor LBrace, 1399a686e1b0SDouglas Gregor RBrace, 1400a686e1b0SDouglas Gregor LSquare, 1401a686e1b0SDouglas Gregor RSquare 1402718292f2SDouglas Gregor } Kind; 1403718292f2SDouglas Gregor 140421401a72SSimon Tatham SourceLocation::UIntTy Location; 1405718292f2SDouglas Gregor unsigned StringLength; 1406040e1266SRichard Smith union { 1407040e1266SRichard Smith // If Kind != IntegerLiteral. 1408718292f2SDouglas Gregor const char *StringData; 1409afd1b1c9SEugene Zelenko 1410040e1266SRichard Smith // If Kind == IntegerLiteral. 1411040e1266SRichard Smith uint64_t IntegerValue; 1412040e1266SRichard Smith }; 1413718292f2SDouglas Gregor 1414718292f2SDouglas Gregor void clear() { 1415718292f2SDouglas Gregor Kind = EndOfFile; 1416718292f2SDouglas Gregor Location = 0; 1417718292f2SDouglas Gregor StringLength = 0; 1418d2d442caSCraig Topper StringData = nullptr; 1419718292f2SDouglas Gregor } 1420718292f2SDouglas Gregor 1421718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 1422718292f2SDouglas Gregor 1423718292f2SDouglas Gregor SourceLocation getLocation() const { 1424718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 1425718292f2SDouglas Gregor } 1426718292f2SDouglas Gregor 1427040e1266SRichard Smith uint64_t getInteger() const { 1428040e1266SRichard Smith return Kind == IntegerLiteral ? IntegerValue : 0; 1429040e1266SRichard Smith } 1430040e1266SRichard Smith 1431718292f2SDouglas Gregor StringRef getString() const { 1432040e1266SRichard Smith return Kind == IntegerLiteral ? StringRef() 1433040e1266SRichard Smith : StringRef(StringData, StringLength); 1434718292f2SDouglas Gregor } 1435718292f2SDouglas Gregor }; 1436718292f2SDouglas Gregor 1437718292f2SDouglas Gregor class ModuleMapParser { 1438718292f2SDouglas Gregor Lexer &L; 1439718292f2SDouglas Gregor SourceManager &SourceMgr; 1440bc10b9fbSDouglas Gregor 14419fc8faf9SAdrian Prantl /// Default target information, used only for string literal 1442bc10b9fbSDouglas Gregor /// parsing. 1443bc10b9fbSDouglas Gregor const TargetInfo *Target; 1444bc10b9fbSDouglas Gregor 1445718292f2SDouglas Gregor DiagnosticsEngine &Diags; 1446718292f2SDouglas Gregor ModuleMap ⤅ 1447718292f2SDouglas Gregor 14489fc8faf9SAdrian Prantl /// The current module map file. 1449beee15e7SBen Langmuir const FileEntry *ModuleMapFile; 1450beee15e7SBen Langmuir 14519f6020bcSBruno Cardoso Lopes /// Source location of most recent parsed module declaration 14529f6020bcSBruno Cardoso Lopes SourceLocation CurrModuleDeclLoc; 14539f6020bcSBruno Cardoso Lopes 14549fc8faf9SAdrian Prantl /// The directory that file names in this module map file should 14559acb99e3SRichard Smith /// be resolved relative to. 14565257fc63SDouglas Gregor const DirectoryEntry *Directory; 14575257fc63SDouglas Gregor 14589fc8faf9SAdrian Prantl /// Whether this module map is in a system header directory. 1459963c5535SDouglas Gregor bool IsSystem; 1460963c5535SDouglas Gregor 14619fc8faf9SAdrian Prantl /// Whether an error occurred. 1462afd1b1c9SEugene Zelenko bool HadError = false; 1463718292f2SDouglas Gregor 14649fc8faf9SAdrian Prantl /// Stores string data for the various string literals referenced 1465718292f2SDouglas Gregor /// during parsing. 1466718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 1467718292f2SDouglas Gregor 14689fc8faf9SAdrian Prantl /// The current token. 1469718292f2SDouglas Gregor MMToken Tok; 1470718292f2SDouglas Gregor 14719fc8faf9SAdrian Prantl /// The active module. 1472afd1b1c9SEugene Zelenko Module *ActiveModule = nullptr; 1473718292f2SDouglas Gregor 14749fc8faf9SAdrian Prantl /// Whether a module uses the 'requires excluded' hack to mark its 14757ff29148SBen Langmuir /// contents as 'textual'. 14767ff29148SBen Langmuir /// 14777ff29148SBen Langmuir /// On older Darwin SDK versions, 'requires excluded' is used to mark the 14787ff29148SBen Langmuir /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as 14797ff29148SBen Langmuir /// non-modular headers. For backwards compatibility, we continue to 14807ff29148SBen Langmuir /// support this idiom for just these modules, and map the headers to 14817ff29148SBen Langmuir /// 'textual' to match the original intent. 14827ff29148SBen Langmuir llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack; 14837ff29148SBen Langmuir 14849fc8faf9SAdrian Prantl /// Consume the current token and return its location. 1485718292f2SDouglas Gregor SourceLocation consumeToken(); 1486718292f2SDouglas Gregor 14879fc8faf9SAdrian Prantl /// Skip tokens until we reach the a token with the given kind 1488718292f2SDouglas Gregor /// (or the end of the file). 1489718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 1490718292f2SDouglas Gregor 1491afd1b1c9SEugene Zelenko using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>; 1492afd1b1c9SEugene Zelenko 1493e7ab3669SDouglas Gregor bool parseModuleId(ModuleId &Id); 1494718292f2SDouglas Gregor void parseModuleDecl(); 149597292843SDaniel Jasper void parseExternModuleDecl(); 14961fb5c3a6SDouglas Gregor void parseRequiresDecl(); 1497afd1b1c9SEugene Zelenko void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc); 1498524e33e1SDouglas Gregor void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc); 14992b82c2a5SDouglas Gregor void parseExportDecl(); 1500f0b11de2SDouglas Gregor void parseExportAsDecl(); 1501ba7f2f71SDaniel Jasper void parseUseDecl(); 15026ddfca91SDouglas Gregor void parseLinkDecl(); 150335b13eceSDouglas Gregor void parseConfigMacros(); 1504fb912657SDouglas Gregor void parseConflict(); 15059194a91dSDouglas Gregor void parseInferredModuleDecl(bool Framework, bool Explicit); 1506c1d88ea5SBen Langmuir 15075f11e128SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra 15085f11e128SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH 15095f11e128SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written 15105f11e128SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits. 15115f11e128SBruno Cardoso Lopes void diagnosePrivateModules(SourceLocation ExplicitLoc, 15125f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc); 15135f11e128SBruno Cardoso Lopes 1514afd1b1c9SEugene Zelenko using Attributes = ModuleMap::Attributes; 1515afd1b1c9SEugene Zelenko 15164442605fSBill Wendling bool parseOptionalAttributes(Attributes &Attrs); 1517718292f2SDouglas Gregor 1518718292f2SDouglas Gregor public: 1519718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 15208587dfd9SBruno Cardoso Lopes const TargetInfo *Target, DiagnosticsEngine &Diags, 15218587dfd9SBruno Cardoso Lopes ModuleMap &Map, const FileEntry *ModuleMapFile, 1522c192d194SBruno Cardoso Lopes const DirectoryEntry *Directory, bool IsSystem) 1523bc10b9fbSDouglas Gregor : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map), 1524beee15e7SBen Langmuir ModuleMapFile(ModuleMapFile), Directory(Directory), 1525c192d194SBruno Cardoso Lopes IsSystem(IsSystem) { 1526718292f2SDouglas Gregor Tok.clear(); 1527718292f2SDouglas Gregor consumeToken(); 1528718292f2SDouglas Gregor } 1529718292f2SDouglas Gregor 1530718292f2SDouglas Gregor bool parseModuleMapFile(); 15318128f332SRichard Smith 15328128f332SRichard Smith bool terminatedByDirective() { return false; } 15338128f332SRichard Smith SourceLocation getLocation() { return Tok.getLocation(); } 1534718292f2SDouglas Gregor }; 1535afd1b1c9SEugene Zelenko 1536afd1b1c9SEugene Zelenko } // namespace clang 1537718292f2SDouglas Gregor 1538718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 1539718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 1540718292f2SDouglas Gregor 15418128f332SRichard Smith retry: 15428128f332SRichard Smith Tok.clear(); 1543718292f2SDouglas Gregor Token LToken; 1544718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 1545718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 1546718292f2SDouglas Gregor switch (LToken.getKind()) { 15472d57cea2SAlp Toker case tok::raw_identifier: { 15482d57cea2SAlp Toker StringRef RI = LToken.getRawIdentifier(); 15492d57cea2SAlp Toker Tok.StringData = RI.data(); 15502d57cea2SAlp Toker Tok.StringLength = RI.size(); 15512d57cea2SAlp Toker Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI) 155235b13eceSDouglas Gregor .Case("config_macros", MMToken::ConfigMacros) 1553fb912657SDouglas Gregor .Case("conflict", MMToken::Conflict) 155459527666SDouglas Gregor .Case("exclude", MMToken::ExcludeKeyword) 1555718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 15562b82c2a5SDouglas Gregor .Case("export", MMToken::ExportKeyword) 1557f0b11de2SDouglas Gregor .Case("export_as", MMToken::ExportAsKeyword) 155897292843SDaniel Jasper .Case("extern", MMToken::ExternKeyword) 1559755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 156035b13eceSDouglas Gregor .Case("header", MMToken::HeaderKeyword) 15616ddfca91SDouglas Gregor .Case("link", MMToken::LinkKeyword) 1562718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 1563b53e5483SLawrence Crowl .Case("private", MMToken::PrivateKeyword) 15641fb5c3a6SDouglas Gregor .Case("requires", MMToken::RequiresKeyword) 1565306d8920SRichard Smith .Case("textual", MMToken::TextualKeyword) 1566718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 1567ba7f2f71SDaniel Jasper .Case("use", MMToken::UseKeyword) 1568718292f2SDouglas Gregor .Default(MMToken::Identifier); 1569718292f2SDouglas Gregor break; 15702d57cea2SAlp Toker } 1571718292f2SDouglas Gregor 15721fb5c3a6SDouglas Gregor case tok::comma: 15731fb5c3a6SDouglas Gregor Tok.Kind = MMToken::Comma; 15741fb5c3a6SDouglas Gregor break; 15751fb5c3a6SDouglas Gregor 1576718292f2SDouglas Gregor case tok::eof: 1577718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 1578718292f2SDouglas Gregor break; 1579718292f2SDouglas Gregor 1580718292f2SDouglas Gregor case tok::l_brace: 1581718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 1582718292f2SDouglas Gregor break; 1583718292f2SDouglas Gregor 1584a686e1b0SDouglas Gregor case tok::l_square: 1585a686e1b0SDouglas Gregor Tok.Kind = MMToken::LSquare; 1586a686e1b0SDouglas Gregor break; 1587a686e1b0SDouglas Gregor 15882b82c2a5SDouglas Gregor case tok::period: 15892b82c2a5SDouglas Gregor Tok.Kind = MMToken::Period; 15902b82c2a5SDouglas Gregor break; 15912b82c2a5SDouglas Gregor 1592718292f2SDouglas Gregor case tok::r_brace: 1593718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 1594718292f2SDouglas Gregor break; 1595718292f2SDouglas Gregor 1596a686e1b0SDouglas Gregor case tok::r_square: 1597a686e1b0SDouglas Gregor Tok.Kind = MMToken::RSquare; 1598a686e1b0SDouglas Gregor break; 1599a686e1b0SDouglas Gregor 16002b82c2a5SDouglas Gregor case tok::star: 16012b82c2a5SDouglas Gregor Tok.Kind = MMToken::Star; 16022b82c2a5SDouglas Gregor break; 16032b82c2a5SDouglas Gregor 1604a3feee2aSRichard Smith case tok::exclaim: 1605a3feee2aSRichard Smith Tok.Kind = MMToken::Exclaim; 1606a3feee2aSRichard Smith break; 1607a3feee2aSRichard Smith 1608718292f2SDouglas Gregor case tok::string_literal: { 1609d67aea28SRichard Smith if (LToken.hasUDSuffix()) { 1610d67aea28SRichard Smith Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl); 1611d67aea28SRichard Smith HadError = true; 1612d67aea28SRichard Smith goto retry; 1613d67aea28SRichard Smith } 1614d67aea28SRichard Smith 1615718292f2SDouglas Gregor // Parse the string literal. 1616718292f2SDouglas Gregor LangOptions LangOpts; 16179d5583efSCraig Topper StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target); 1618718292f2SDouglas Gregor if (StringLiteral.hadError) 1619718292f2SDouglas Gregor goto retry; 1620718292f2SDouglas Gregor 1621718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 1622718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 1623718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 1624718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 1625718292f2SDouglas Gregor Saved[Length] = 0; 1626718292f2SDouglas Gregor 1627718292f2SDouglas Gregor // Form the token. 1628718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 1629718292f2SDouglas Gregor Tok.StringData = Saved; 1630718292f2SDouglas Gregor Tok.StringLength = Length; 1631718292f2SDouglas Gregor break; 1632718292f2SDouglas Gregor } 1633718292f2SDouglas Gregor 1634040e1266SRichard Smith case tok::numeric_constant: { 1635040e1266SRichard Smith // We don't support any suffixes or other complications. 1636040e1266SRichard Smith SmallString<32> SpellingBuffer; 1637040e1266SRichard Smith SpellingBuffer.resize(LToken.getLength() + 1); 1638040e1266SRichard Smith const char *Start = SpellingBuffer.data(); 1639040e1266SRichard Smith unsigned Length = 1640d813116cSDawid Jurczak Lexer::getSpelling(LToken, Start, SourceMgr, Map.LangOpts); 1641040e1266SRichard Smith uint64_t Value; 1642040e1266SRichard Smith if (StringRef(Start, Length).getAsInteger(0, Value)) { 1643040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1644040e1266SRichard Smith HadError = true; 1645040e1266SRichard Smith goto retry; 1646040e1266SRichard Smith } 1647040e1266SRichard Smith 1648040e1266SRichard Smith Tok.Kind = MMToken::IntegerLiteral; 1649040e1266SRichard Smith Tok.IntegerValue = Value; 1650040e1266SRichard Smith break; 1651040e1266SRichard Smith } 1652040e1266SRichard Smith 1653718292f2SDouglas Gregor case tok::comment: 1654718292f2SDouglas Gregor goto retry; 1655718292f2SDouglas Gregor 16568128f332SRichard Smith case tok::hash: 16578128f332SRichard Smith // A module map can be terminated prematurely by 16588128f332SRichard Smith // #pragma clang module contents 16598128f332SRichard Smith // When building the module, we'll treat the rest of the file as the 16608128f332SRichard Smith // contents of the module. 16618128f332SRichard Smith { 16628128f332SRichard Smith auto NextIsIdent = [&](StringRef Str) -> bool { 16638128f332SRichard Smith L.LexFromRawLexer(LToken); 16648128f332SRichard Smith return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) && 16658128f332SRichard Smith LToken.getRawIdentifier() == Str; 16668128f332SRichard Smith }; 16678128f332SRichard Smith if (NextIsIdent("pragma") && NextIsIdent("clang") && 16688128f332SRichard Smith NextIsIdent("module") && NextIsIdent("contents")) { 16698128f332SRichard Smith Tok.Kind = MMToken::EndOfFile; 16708128f332SRichard Smith break; 16718128f332SRichard Smith } 16728128f332SRichard Smith } 16738128f332SRichard Smith LLVM_FALLTHROUGH; 16748128f332SRichard Smith 1675718292f2SDouglas Gregor default: 16768128f332SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1677718292f2SDouglas Gregor HadError = true; 1678718292f2SDouglas Gregor goto retry; 1679718292f2SDouglas Gregor } 1680718292f2SDouglas Gregor 1681718292f2SDouglas Gregor return Result; 1682718292f2SDouglas Gregor } 1683718292f2SDouglas Gregor 1684718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 1685718292f2SDouglas Gregor unsigned braceDepth = 0; 1686a686e1b0SDouglas Gregor unsigned squareDepth = 0; 1687718292f2SDouglas Gregor do { 1688718292f2SDouglas Gregor switch (Tok.Kind) { 1689718292f2SDouglas Gregor case MMToken::EndOfFile: 1690718292f2SDouglas Gregor return; 1691718292f2SDouglas Gregor 1692718292f2SDouglas Gregor case MMToken::LBrace: 1693a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1694718292f2SDouglas Gregor return; 1695718292f2SDouglas Gregor 1696718292f2SDouglas Gregor ++braceDepth; 1697718292f2SDouglas Gregor break; 1698718292f2SDouglas Gregor 1699a686e1b0SDouglas Gregor case MMToken::LSquare: 1700a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1701a686e1b0SDouglas Gregor return; 1702a686e1b0SDouglas Gregor 1703a686e1b0SDouglas Gregor ++squareDepth; 1704a686e1b0SDouglas Gregor break; 1705a686e1b0SDouglas Gregor 1706718292f2SDouglas Gregor case MMToken::RBrace: 1707718292f2SDouglas Gregor if (braceDepth > 0) 1708718292f2SDouglas Gregor --braceDepth; 1709718292f2SDouglas Gregor else if (Tok.is(K)) 1710718292f2SDouglas Gregor return; 1711718292f2SDouglas Gregor break; 1712718292f2SDouglas Gregor 1713a686e1b0SDouglas Gregor case MMToken::RSquare: 1714a686e1b0SDouglas Gregor if (squareDepth > 0) 1715a686e1b0SDouglas Gregor --squareDepth; 1716a686e1b0SDouglas Gregor else if (Tok.is(K)) 1717a686e1b0SDouglas Gregor return; 1718a686e1b0SDouglas Gregor break; 1719a686e1b0SDouglas Gregor 1720718292f2SDouglas Gregor default: 1721a686e1b0SDouglas Gregor if (braceDepth == 0 && squareDepth == 0 && Tok.is(K)) 1722718292f2SDouglas Gregor return; 1723718292f2SDouglas Gregor break; 1724718292f2SDouglas Gregor } 1725718292f2SDouglas Gregor 1726718292f2SDouglas Gregor consumeToken(); 1727718292f2SDouglas Gregor } while (true); 1728718292f2SDouglas Gregor } 1729718292f2SDouglas Gregor 17309fc8faf9SAdrian Prantl /// Parse a module-id. 1731e7ab3669SDouglas Gregor /// 1732e7ab3669SDouglas Gregor /// module-id: 1733e7ab3669SDouglas Gregor /// identifier 1734e7ab3669SDouglas Gregor /// identifier '.' module-id 1735e7ab3669SDouglas Gregor /// 1736e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise. 1737e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) { 1738e7ab3669SDouglas Gregor Id.clear(); 1739e7ab3669SDouglas Gregor do { 17403cd34c76SDaniel Jasper if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) { 1741adcd0268SBenjamin Kramer Id.push_back( 1742adcd0268SBenjamin Kramer std::make_pair(std::string(Tok.getString()), Tok.getLocation())); 1743e7ab3669SDouglas Gregor consumeToken(); 1744e7ab3669SDouglas Gregor } else { 1745e7ab3669SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 1746e7ab3669SDouglas Gregor return true; 1747e7ab3669SDouglas Gregor } 1748e7ab3669SDouglas Gregor 1749e7ab3669SDouglas Gregor if (!Tok.is(MMToken::Period)) 1750e7ab3669SDouglas Gregor break; 1751e7ab3669SDouglas Gregor 1752e7ab3669SDouglas Gregor consumeToken(); 1753e7ab3669SDouglas Gregor } while (true); 1754e7ab3669SDouglas Gregor 1755e7ab3669SDouglas Gregor return false; 1756e7ab3669SDouglas Gregor } 1757e7ab3669SDouglas Gregor 1758a686e1b0SDouglas Gregor namespace { 1759afd1b1c9SEugene Zelenko 17609fc8faf9SAdrian Prantl /// Enumerates the known attributes. 1761a686e1b0SDouglas Gregor enum AttributeKind { 17629fc8faf9SAdrian Prantl /// An unknown attribute. 1763a686e1b0SDouglas Gregor AT_unknown, 1764afd1b1c9SEugene Zelenko 17659fc8faf9SAdrian Prantl /// The 'system' attribute. 176635b13eceSDouglas Gregor AT_system, 1767afd1b1c9SEugene Zelenko 17689fc8faf9SAdrian Prantl /// The 'extern_c' attribute. 176977944868SRichard Smith AT_extern_c, 1770afd1b1c9SEugene Zelenko 17719fc8faf9SAdrian Prantl /// The 'exhaustive' attribute. 1772ed84df00SBruno Cardoso Lopes AT_exhaustive, 1773afd1b1c9SEugene Zelenko 17749fc8faf9SAdrian Prantl /// The 'no_undeclared_includes' attribute. 1775ed84df00SBruno Cardoso Lopes AT_no_undeclared_includes 1776a686e1b0SDouglas Gregor }; 1777afd1b1c9SEugene Zelenko 1778afd1b1c9SEugene Zelenko } // namespace 1779a686e1b0SDouglas Gregor 178029729919SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra 178129729919SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH 178229729919SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written 178329729919SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits. 17845f11e128SBruno Cardoso Lopes void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc, 17855f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc) { 178629729919SBruno Cardoso Lopes auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical, 17877d29486dSBruno Cardoso Lopes const Module *M, SourceRange ReplLoc) { 178829729919SBruno Cardoso Lopes auto D = Diags.Report(ActiveModule->DefinitionLoc, 178929729919SBruno Cardoso Lopes diag::note_mmap_rename_top_level_private_module); 179029729919SBruno Cardoso Lopes D << BadName << M->Name; 17917d29486dSBruno Cardoso Lopes D << FixItHint::CreateReplacement(ReplLoc, Canonical); 179229729919SBruno Cardoso Lopes }; 179329729919SBruno Cardoso Lopes 179429729919SBruno Cardoso Lopes for (auto E = Map.module_begin(); E != Map.module_end(); ++E) { 179529729919SBruno Cardoso Lopes auto const *M = E->getValue(); 179629729919SBruno Cardoso Lopes if (M->Directory != ActiveModule->Directory) 179729729919SBruno Cardoso Lopes continue; 179829729919SBruno Cardoso Lopes 179929729919SBruno Cardoso Lopes SmallString<128> FullName(ActiveModule->getFullModuleName()); 180029729919SBruno Cardoso Lopes if (!FullName.startswith(M->Name) && !FullName.endswith("Private")) 180129729919SBruno Cardoso Lopes continue; 18025f11e128SBruno Cardoso Lopes SmallString<128> FixedPrivModDecl; 180329729919SBruno Cardoso Lopes SmallString<128> Canonical(M->Name); 180429729919SBruno Cardoso Lopes Canonical.append("_Private"); 180529729919SBruno Cardoso Lopes 180629729919SBruno Cardoso Lopes // Foo.Private -> Foo_Private 180729729919SBruno Cardoso Lopes if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent && 180829729919SBruno Cardoso Lopes M->Name == ActiveModule->Parent->Name) { 180929729919SBruno Cardoso Lopes Diags.Report(ActiveModule->DefinitionLoc, 181029729919SBruno Cardoso Lopes diag::warn_mmap_mismatched_private_submodule) 181129729919SBruno Cardoso Lopes << FullName; 18125f11e128SBruno Cardoso Lopes 18135f11e128SBruno Cardoso Lopes SourceLocation FixItInitBegin = CurrModuleDeclLoc; 18145f11e128SBruno Cardoso Lopes if (FrameworkLoc.isValid()) 18155f11e128SBruno Cardoso Lopes FixItInitBegin = FrameworkLoc; 18165f11e128SBruno Cardoso Lopes if (ExplicitLoc.isValid()) 18175f11e128SBruno Cardoso Lopes FixItInitBegin = ExplicitLoc; 18185f11e128SBruno Cardoso Lopes 18195f11e128SBruno Cardoso Lopes if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework) 18205f11e128SBruno Cardoso Lopes FixedPrivModDecl.append("framework "); 18215f11e128SBruno Cardoso Lopes FixedPrivModDecl.append("module "); 18225f11e128SBruno Cardoso Lopes FixedPrivModDecl.append(Canonical); 18235f11e128SBruno Cardoso Lopes 18245f11e128SBruno Cardoso Lopes GenNoteAndFixIt(FullName, FixedPrivModDecl, M, 18255f11e128SBruno Cardoso Lopes SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc)); 182629729919SBruno Cardoso Lopes continue; 182729729919SBruno Cardoso Lopes } 182829729919SBruno Cardoso Lopes 182929729919SBruno Cardoso Lopes // FooPrivate and whatnots -> Foo_Private 183029729919SBruno Cardoso Lopes if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name && 183129729919SBruno Cardoso Lopes ActiveModule->Name != Canonical) { 183229729919SBruno Cardoso Lopes Diags.Report(ActiveModule->DefinitionLoc, 183329729919SBruno Cardoso Lopes diag::warn_mmap_mismatched_private_module_name) 183429729919SBruno Cardoso Lopes << ActiveModule->Name; 18357d29486dSBruno Cardoso Lopes GenNoteAndFixIt(ActiveModule->Name, Canonical, M, 18367d29486dSBruno Cardoso Lopes SourceRange(ActiveModule->DefinitionLoc)); 183729729919SBruno Cardoso Lopes } 183829729919SBruno Cardoso Lopes } 183929729919SBruno Cardoso Lopes } 184029729919SBruno Cardoso Lopes 18419fc8faf9SAdrian Prantl /// Parse a module declaration. 1842718292f2SDouglas Gregor /// 1843718292f2SDouglas Gregor /// module-declaration: 184497292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 1845a686e1b0SDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt] 1846a686e1b0SDouglas Gregor /// { module-member* } 1847a686e1b0SDouglas Gregor /// 1848718292f2SDouglas Gregor /// module-member: 18491fb5c3a6SDouglas Gregor /// requires-declaration 1850718292f2SDouglas Gregor /// header-declaration 1851e7ab3669SDouglas Gregor /// submodule-declaration 18522b82c2a5SDouglas Gregor /// export-declaration 1853f0b11de2SDouglas Gregor /// export-as-declaration 18546ddfca91SDouglas Gregor /// link-declaration 185573441091SDouglas Gregor /// 185673441091SDouglas Gregor /// submodule-declaration: 185773441091SDouglas Gregor /// module-declaration 185873441091SDouglas Gregor /// inferred-submodule-declaration 1859718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 1860755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 186197292843SDaniel Jasper Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword)); 186297292843SDaniel Jasper if (Tok.is(MMToken::ExternKeyword)) { 186397292843SDaniel Jasper parseExternModuleDecl(); 186497292843SDaniel Jasper return; 186597292843SDaniel Jasper } 186697292843SDaniel Jasper 1867f2161a70SDouglas Gregor // Parse 'explicit' or 'framework' keyword, if present. 1868e7ab3669SDouglas Gregor SourceLocation ExplicitLoc; 18695f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc; 1870718292f2SDouglas Gregor bool Explicit = false; 1871f2161a70SDouglas Gregor bool Framework = false; 1872755b2055SDouglas Gregor 1873f2161a70SDouglas Gregor // Parse 'explicit' keyword, if present. 1874f2161a70SDouglas Gregor if (Tok.is(MMToken::ExplicitKeyword)) { 1875e7ab3669SDouglas Gregor ExplicitLoc = consumeToken(); 1876f2161a70SDouglas Gregor Explicit = true; 1877f2161a70SDouglas Gregor } 1878f2161a70SDouglas Gregor 1879f2161a70SDouglas Gregor // Parse 'framework' keyword, if present. 1880755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 18815f11e128SBruno Cardoso Lopes FrameworkLoc = consumeToken(); 1882755b2055SDouglas Gregor Framework = true; 1883755b2055SDouglas Gregor } 1884718292f2SDouglas Gregor 1885718292f2SDouglas Gregor // Parse 'module' keyword. 1886718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 1887d6343c99SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 1888718292f2SDouglas Gregor consumeToken(); 1889718292f2SDouglas Gregor HadError = true; 1890718292f2SDouglas Gregor return; 1891718292f2SDouglas Gregor } 18929f6020bcSBruno Cardoso Lopes CurrModuleDeclLoc = consumeToken(); // 'module' keyword 1893718292f2SDouglas Gregor 189473441091SDouglas Gregor // If we have a wildcard for the module name, this is an inferred submodule. 189573441091SDouglas Gregor // Parse it. 189673441091SDouglas Gregor if (Tok.is(MMToken::Star)) 18979194a91dSDouglas Gregor return parseInferredModuleDecl(Framework, Explicit); 189873441091SDouglas Gregor 1899718292f2SDouglas Gregor // Parse the module name. 1900e7ab3669SDouglas Gregor ModuleId Id; 1901e7ab3669SDouglas Gregor if (parseModuleId(Id)) { 1902718292f2SDouglas Gregor HadError = true; 1903718292f2SDouglas Gregor return; 1904718292f2SDouglas Gregor } 1905e7ab3669SDouglas Gregor 1906e7ab3669SDouglas Gregor if (ActiveModule) { 1907e7ab3669SDouglas Gregor if (Id.size() > 1) { 1908e7ab3669SDouglas Gregor Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id) 1909e7ab3669SDouglas Gregor << SourceRange(Id.front().second, Id.back().second); 1910e7ab3669SDouglas Gregor 1911e7ab3669SDouglas Gregor HadError = true; 1912e7ab3669SDouglas Gregor return; 1913e7ab3669SDouglas Gregor } 1914e7ab3669SDouglas Gregor } else if (Id.size() == 1 && Explicit) { 1915e7ab3669SDouglas Gregor // Top-level modules can't be explicit. 1916e7ab3669SDouglas Gregor Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level); 1917e7ab3669SDouglas Gregor Explicit = false; 1918e7ab3669SDouglas Gregor ExplicitLoc = SourceLocation(); 1919e7ab3669SDouglas Gregor HadError = true; 1920e7ab3669SDouglas Gregor } 1921e7ab3669SDouglas Gregor 1922e7ab3669SDouglas Gregor Module *PreviousActiveModule = ActiveModule; 1923e7ab3669SDouglas Gregor if (Id.size() > 1) { 1924e7ab3669SDouglas Gregor // This module map defines a submodule. Go find the module of which it 1925e7ab3669SDouglas Gregor // is a submodule. 1926d2d442caSCraig Topper ActiveModule = nullptr; 19274b8a9e95SBen Langmuir const Module *TopLevelModule = nullptr; 1928e7ab3669SDouglas Gregor for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) { 1929e7ab3669SDouglas Gregor if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) { 19304b8a9e95SBen Langmuir if (I == 0) 19314b8a9e95SBen Langmuir TopLevelModule = Next; 1932e7ab3669SDouglas Gregor ActiveModule = Next; 1933e7ab3669SDouglas Gregor continue; 1934e7ab3669SDouglas Gregor } 1935e7ab3669SDouglas Gregor 19368839e278SVolodymyr Sapsai Diags.Report(Id[I].second, diag::err_mmap_missing_parent_module) 19378839e278SVolodymyr Sapsai << Id[I].first << (ActiveModule != nullptr) 19388839e278SVolodymyr Sapsai << (ActiveModule 19398839e278SVolodymyr Sapsai ? ActiveModule->getTopLevelModule()->getFullModuleName() 19408839e278SVolodymyr Sapsai : ""); 1941e7ab3669SDouglas Gregor HadError = true; 1942e7ab3669SDouglas Gregor } 19434b8a9e95SBen Langmuir 19448839e278SVolodymyr Sapsai if (TopLevelModule && 19458839e278SVolodymyr Sapsai ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) { 19464b8a9e95SBen Langmuir assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) && 19474b8a9e95SBen Langmuir "submodule defined in same file as 'module *' that allowed its " 19484b8a9e95SBen Langmuir "top-level module"); 19494b8a9e95SBen Langmuir Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile); 19504b8a9e95SBen Langmuir } 1951e7ab3669SDouglas Gregor } 1952e7ab3669SDouglas Gregor 1953e7ab3669SDouglas Gregor StringRef ModuleName = Id.back().first; 1954e7ab3669SDouglas Gregor SourceLocation ModuleNameLoc = Id.back().second; 1955718292f2SDouglas Gregor 1956a686e1b0SDouglas Gregor // Parse the optional attribute list. 19574442605fSBill Wendling Attributes Attrs; 19585d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 19595d29dee0SDavide Italiano return; 19605d29dee0SDavide Italiano 1961718292f2SDouglas Gregor // Parse the opening brace. 1962718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 1963718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 1964718292f2SDouglas Gregor << ModuleName; 1965718292f2SDouglas Gregor HadError = true; 1966718292f2SDouglas Gregor return; 1967718292f2SDouglas Gregor } 1968718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 1969718292f2SDouglas Gregor 1970718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 19718587dfd9SBruno Cardoso Lopes Module *ShadowingModule = nullptr; 1972eb90e830SDouglas Gregor if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { 19734a3751ffSRichard Smith // We might see a (re)definition of a module that we already have a 19744a3751ffSRichard Smith // definition for in two cases: 19754a3751ffSRichard Smith // - If we loaded one definition from an AST file and we've just found a 19764a3751ffSRichard Smith // corresponding definition in a module map file, or 19774a3751ffSRichard Smith bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid(); 19784a3751ffSRichard Smith // - If we're building a (preprocessed) module and we've just loaded the 19794a3751ffSRichard Smith // module map file from which it was created. 19804a3751ffSRichard Smith bool ParsedAsMainInput = 19814a3751ffSRichard Smith Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap && 19824a3751ffSRichard Smith Map.LangOpts.CurrentModule == ModuleName && 19834a3751ffSRichard Smith SourceMgr.getDecomposedLoc(ModuleNameLoc).first != 19844a3751ffSRichard Smith SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first; 19854a3751ffSRichard Smith if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) { 1986fcc54a3bSDouglas Gregor // Skip the module definition. 1987fcc54a3bSDouglas Gregor skipUntil(MMToken::RBrace); 1988fcc54a3bSDouglas Gregor if (Tok.is(MMToken::RBrace)) 1989fcc54a3bSDouglas Gregor consumeToken(); 1990fcc54a3bSDouglas Gregor else { 1991fcc54a3bSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 1992fcc54a3bSDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 1993fcc54a3bSDouglas Gregor HadError = true; 1994fcc54a3bSDouglas Gregor } 1995fcc54a3bSDouglas Gregor return; 1996fcc54a3bSDouglas Gregor } 1997fcc54a3bSDouglas Gregor 1998c192d194SBruno Cardoso Lopes if (!Existing->Parent && Map.mayShadowNewModule(Existing)) { 19998587dfd9SBruno Cardoso Lopes ShadowingModule = Existing; 20008587dfd9SBruno Cardoso Lopes } else { 20018587dfd9SBruno Cardoso Lopes // This is not a shawdowed module decl, it is an illegal redefinition. 2002718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 2003718292f2SDouglas Gregor << ModuleName; 2004eb90e830SDouglas Gregor Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition); 2005718292f2SDouglas Gregor 2006718292f2SDouglas Gregor // Skip the module definition. 2007718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 2008718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 2009718292f2SDouglas Gregor consumeToken(); 2010718292f2SDouglas Gregor 2011718292f2SDouglas Gregor HadError = true; 2012718292f2SDouglas Gregor return; 2013718292f2SDouglas Gregor } 20148587dfd9SBruno Cardoso Lopes } 2015718292f2SDouglas Gregor 2016718292f2SDouglas Gregor // Start defining this module. 20178587dfd9SBruno Cardoso Lopes if (ShadowingModule) { 20188587dfd9SBruno Cardoso Lopes ActiveModule = 20198587dfd9SBruno Cardoso Lopes Map.createShadowedModule(ModuleName, Framework, ShadowingModule); 20208587dfd9SBruno Cardoso Lopes } else { 2021c192d194SBruno Cardoso Lopes ActiveModule = 2022c192d194SBruno Cardoso Lopes Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit) 20238587dfd9SBruno Cardoso Lopes .first; 20248587dfd9SBruno Cardoso Lopes } 20258587dfd9SBruno Cardoso Lopes 2026eb90e830SDouglas Gregor ActiveModule->DefinitionLoc = ModuleNameLoc; 2027963c5535SDouglas Gregor if (Attrs.IsSystem || IsSystem) 2028a686e1b0SDouglas Gregor ActiveModule->IsSystem = true; 202977944868SRichard Smith if (Attrs.IsExternC) 203077944868SRichard Smith ActiveModule->IsExternC = true; 2031ed84df00SBruno Cardoso Lopes if (Attrs.NoUndeclaredIncludes || 2032ed84df00SBruno Cardoso Lopes (!ActiveModule->Parent && ModuleName == "Darwin")) 2033ed84df00SBruno Cardoso Lopes ActiveModule->NoUndeclaredIncludes = true; 20343c1a41adSRichard Smith ActiveModule->Directory = Directory; 2035718292f2SDouglas Gregor 203690b0a1fcSJordan Rose StringRef MapFileName(ModuleMapFile->getName()); 203790b0a1fcSJordan Rose if (MapFileName.endswith("module.private.modulemap") || 203890b0a1fcSJordan Rose MapFileName.endswith("module_private.map")) { 203990b0a1fcSJordan Rose ActiveModule->ModuleMapIsPrivate = true; 204090b0a1fcSJordan Rose } 204129729919SBruno Cardoso Lopes 204229729919SBruno Cardoso Lopes // Private modules named as FooPrivate, Foo.Private or similar are likely a 204329729919SBruno Cardoso Lopes // user error; provide warnings, notes and fixits to direct users to use 204429729919SBruno Cardoso Lopes // Foo_Private instead. 204529729919SBruno Cardoso Lopes SourceLocation StartLoc = 204629729919SBruno Cardoso Lopes SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()); 204729729919SBruno Cardoso Lopes if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && 204829729919SBruno Cardoso Lopes !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule, 204929729919SBruno Cardoso Lopes StartLoc) && 205029729919SBruno Cardoso Lopes !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name, 205129729919SBruno Cardoso Lopes StartLoc) && 205290b0a1fcSJordan Rose ActiveModule->ModuleMapIsPrivate) 20535f11e128SBruno Cardoso Lopes diagnosePrivateModules(ExplicitLoc, FrameworkLoc); 20544d867640SGraydon Hoare 2055718292f2SDouglas Gregor bool Done = false; 2056718292f2SDouglas Gregor do { 2057718292f2SDouglas Gregor switch (Tok.Kind) { 2058718292f2SDouglas Gregor case MMToken::EndOfFile: 2059718292f2SDouglas Gregor case MMToken::RBrace: 2060718292f2SDouglas Gregor Done = true; 2061718292f2SDouglas Gregor break; 2062718292f2SDouglas Gregor 206335b13eceSDouglas Gregor case MMToken::ConfigMacros: 206435b13eceSDouglas Gregor parseConfigMacros(); 206535b13eceSDouglas Gregor break; 206635b13eceSDouglas Gregor 2067fb912657SDouglas Gregor case MMToken::Conflict: 2068fb912657SDouglas Gregor parseConflict(); 2069fb912657SDouglas Gregor break; 2070fb912657SDouglas Gregor 2071718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 207297292843SDaniel Jasper case MMToken::ExternKeyword: 2073f2161a70SDouglas Gregor case MMToken::FrameworkKeyword: 2074718292f2SDouglas Gregor case MMToken::ModuleKeyword: 2075718292f2SDouglas Gregor parseModuleDecl(); 2076718292f2SDouglas Gregor break; 2077718292f2SDouglas Gregor 20782b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 20792b82c2a5SDouglas Gregor parseExportDecl(); 20802b82c2a5SDouglas Gregor break; 20812b82c2a5SDouglas Gregor 2082f0b11de2SDouglas Gregor case MMToken::ExportAsKeyword: 2083f0b11de2SDouglas Gregor parseExportAsDecl(); 2084f0b11de2SDouglas Gregor break; 2085f0b11de2SDouglas Gregor 2086ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 2087ba7f2f71SDaniel Jasper parseUseDecl(); 2088ba7f2f71SDaniel Jasper break; 2089ba7f2f71SDaniel Jasper 20901fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 20911fb5c3a6SDouglas Gregor parseRequiresDecl(); 20921fb5c3a6SDouglas Gregor break; 20931fb5c3a6SDouglas Gregor 2094202210b3SRichard Smith case MMToken::TextualKeyword: 2095202210b3SRichard Smith parseHeaderDecl(MMToken::TextualKeyword, consumeToken()); 2096306d8920SRichard Smith break; 2097306d8920SRichard Smith 2098524e33e1SDouglas Gregor case MMToken::UmbrellaKeyword: { 2099524e33e1SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 2100524e33e1SDouglas Gregor if (Tok.is(MMToken::HeaderKeyword)) 2101b53e5483SLawrence Crowl parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc); 2102524e33e1SDouglas Gregor else 2103524e33e1SDouglas Gregor parseUmbrellaDirDecl(UmbrellaLoc); 2104718292f2SDouglas Gregor break; 2105524e33e1SDouglas Gregor } 2106718292f2SDouglas Gregor 2107202210b3SRichard Smith case MMToken::ExcludeKeyword: 2108202210b3SRichard Smith parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken()); 210959527666SDouglas Gregor break; 211059527666SDouglas Gregor 2111202210b3SRichard Smith case MMToken::PrivateKeyword: 2112202210b3SRichard Smith parseHeaderDecl(MMToken::PrivateKeyword, consumeToken()); 2113b53e5483SLawrence Crowl break; 2114b53e5483SLawrence Crowl 2115322f633cSDouglas Gregor case MMToken::HeaderKeyword: 2116202210b3SRichard Smith parseHeaderDecl(MMToken::HeaderKeyword, consumeToken()); 2117718292f2SDouglas Gregor break; 2118718292f2SDouglas Gregor 21196ddfca91SDouglas Gregor case MMToken::LinkKeyword: 21206ddfca91SDouglas Gregor parseLinkDecl(); 21216ddfca91SDouglas Gregor break; 21226ddfca91SDouglas Gregor 2123718292f2SDouglas Gregor default: 2124718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 2125718292f2SDouglas Gregor consumeToken(); 2126718292f2SDouglas Gregor break; 2127718292f2SDouglas Gregor } 2128718292f2SDouglas Gregor } while (!Done); 2129718292f2SDouglas Gregor 2130718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 2131718292f2SDouglas Gregor consumeToken(); 2132718292f2SDouglas Gregor else { 2133718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 2134718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 2135718292f2SDouglas Gregor HadError = true; 2136718292f2SDouglas Gregor } 2137718292f2SDouglas Gregor 213811dfe6feSDouglas Gregor // If the active module is a top-level framework, and there are no link 213911dfe6feSDouglas Gregor // libraries, automatically link against the framework. 214011dfe6feSDouglas Gregor if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() && 214111dfe6feSDouglas Gregor ActiveModule->LinkLibraries.empty()) { 214211dfe6feSDouglas Gregor inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager()); 214311dfe6feSDouglas Gregor } 214411dfe6feSDouglas Gregor 2145ec8c9752SBen Langmuir // If the module meets all requirements but is still unavailable, mark the 2146ec8c9752SBen Langmuir // whole tree as unavailable to prevent it from building. 2147fc76b4adSRichard Smith if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable && 2148ec8c9752SBen Langmuir ActiveModule->Parent) { 2149fc76b4adSRichard Smith ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false); 2150ec8c9752SBen Langmuir ActiveModule->getTopLevelModule()->MissingHeaders.append( 2151ec8c9752SBen Langmuir ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end()); 2152ec8c9752SBen Langmuir } 2153ec8c9752SBen Langmuir 2154e7ab3669SDouglas Gregor // We're done parsing this module. Pop back to the previous module. 2155e7ab3669SDouglas Gregor ActiveModule = PreviousActiveModule; 2156718292f2SDouglas Gregor } 2157718292f2SDouglas Gregor 21589fc8faf9SAdrian Prantl /// Parse an extern module declaration. 215997292843SDaniel Jasper /// 216097292843SDaniel Jasper /// extern module-declaration: 216197292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 216297292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() { 216397292843SDaniel Jasper assert(Tok.is(MMToken::ExternKeyword)); 2164ae6df27eSRichard Smith SourceLocation ExternLoc = consumeToken(); // 'extern' keyword 216597292843SDaniel Jasper 216697292843SDaniel Jasper // Parse 'module' keyword. 216797292843SDaniel Jasper if (!Tok.is(MMToken::ModuleKeyword)) { 216897292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 216997292843SDaniel Jasper consumeToken(); 217097292843SDaniel Jasper HadError = true; 217197292843SDaniel Jasper return; 217297292843SDaniel Jasper } 217397292843SDaniel Jasper consumeToken(); // 'module' keyword 217497292843SDaniel Jasper 217597292843SDaniel Jasper // Parse the module name. 217697292843SDaniel Jasper ModuleId Id; 217797292843SDaniel Jasper if (parseModuleId(Id)) { 217897292843SDaniel Jasper HadError = true; 217997292843SDaniel Jasper return; 218097292843SDaniel Jasper } 218197292843SDaniel Jasper 218297292843SDaniel Jasper // Parse the referenced module map file name. 218397292843SDaniel Jasper if (!Tok.is(MMToken::StringLiteral)) { 218497292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file); 218597292843SDaniel Jasper HadError = true; 218697292843SDaniel Jasper return; 218797292843SDaniel Jasper } 2188adcd0268SBenjamin Kramer std::string FileName = std::string(Tok.getString()); 218997292843SDaniel Jasper consumeToken(); // filename 219097292843SDaniel Jasper 219197292843SDaniel Jasper StringRef FileNameRef = FileName; 219297292843SDaniel Jasper SmallString<128> ModuleMapFileName; 219397292843SDaniel Jasper if (llvm::sys::path::is_relative(FileNameRef)) { 219497292843SDaniel Jasper ModuleMapFileName += Directory->getName(); 219597292843SDaniel Jasper llvm::sys::path::append(ModuleMapFileName, FileName); 219692e1b62dSYaron Keren FileNameRef = ModuleMapFileName; 219797292843SDaniel Jasper } 21987799ef71SNico Weber if (auto File = SourceMgr.getFileManager().getFile(FileNameRef)) 21999acb99e3SRichard Smith Map.parseModuleMapFile( 2200d0e7bdc2SVolodymyr Sapsai *File, IsSystem, 22019acb99e3SRichard Smith Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd 22029acb99e3SRichard Smith ? Directory 22037799ef71SNico Weber : (*File)->getDir(), 2204c192d194SBruno Cardoso Lopes FileID(), nullptr, ExternLoc); 220597292843SDaniel Jasper } 220697292843SDaniel Jasper 22077ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M. 22087ff29148SBen Langmuir /// 22097ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system 22107ff29148SBen Langmuir /// module map files: 22117ff29148SBen Langmuir /// 22127ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which 22137ff29148SBen Langmuir /// should really be mapped to 'textual' now that we have this feature. We 22147ff29148SBen Langmuir /// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to 22157ff29148SBen Langmuir /// true. Later, this bit will be used to map all the headers inside this 22167ff29148SBen Langmuir /// module to 'textual'. 22177ff29148SBen Langmuir /// 22187ff29148SBen Langmuir /// This affects Darwin.C.excluded (for assert.h) and Tcl.Private. 22197ff29148SBen Langmuir /// 22207ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement 22217ff29148SBen Langmuir /// was never correct and causes issues now that we check it, so drop it. 22227ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature, 22237ff29148SBen Langmuir bool &IsRequiresExcludedHack) { 22248013e81dSBenjamin Kramer if (Feature == "excluded" && 22258013e81dSBenjamin Kramer (M->fullModuleNameIs({"Darwin", "C", "excluded"}) || 22268013e81dSBenjamin Kramer M->fullModuleNameIs({"Tcl", "Private"}))) { 22277ff29148SBen Langmuir IsRequiresExcludedHack = true; 22287ff29148SBen Langmuir return false; 22298013e81dSBenjamin Kramer } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) { 22307ff29148SBen Langmuir return false; 22317ff29148SBen Langmuir } 22327ff29148SBen Langmuir 22337ff29148SBen Langmuir return true; 22347ff29148SBen Langmuir } 22357ff29148SBen Langmuir 22369fc8faf9SAdrian Prantl /// Parse a requires declaration. 22371fb5c3a6SDouglas Gregor /// 22381fb5c3a6SDouglas Gregor /// requires-declaration: 22391fb5c3a6SDouglas Gregor /// 'requires' feature-list 22401fb5c3a6SDouglas Gregor /// 22411fb5c3a6SDouglas Gregor /// feature-list: 2242a3feee2aSRichard Smith /// feature ',' feature-list 2243a3feee2aSRichard Smith /// feature 2244a3feee2aSRichard Smith /// 2245a3feee2aSRichard Smith /// feature: 2246a3feee2aSRichard Smith /// '!'[opt] identifier 22471fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() { 22481fb5c3a6SDouglas Gregor assert(Tok.is(MMToken::RequiresKeyword)); 22491fb5c3a6SDouglas Gregor 22501fb5c3a6SDouglas Gregor // Parse 'requires' keyword. 22511fb5c3a6SDouglas Gregor consumeToken(); 22521fb5c3a6SDouglas Gregor 22531fb5c3a6SDouglas Gregor // Parse the feature-list. 22541fb5c3a6SDouglas Gregor do { 2255a3feee2aSRichard Smith bool RequiredState = true; 2256a3feee2aSRichard Smith if (Tok.is(MMToken::Exclaim)) { 2257a3feee2aSRichard Smith RequiredState = false; 2258a3feee2aSRichard Smith consumeToken(); 2259a3feee2aSRichard Smith } 2260a3feee2aSRichard Smith 22611fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 22621fb5c3a6SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature); 22631fb5c3a6SDouglas Gregor HadError = true; 22641fb5c3a6SDouglas Gregor return; 22651fb5c3a6SDouglas Gregor } 22661fb5c3a6SDouglas Gregor 22671fb5c3a6SDouglas Gregor // Consume the feature name. 2268adcd0268SBenjamin Kramer std::string Feature = std::string(Tok.getString()); 22691fb5c3a6SDouglas Gregor consumeToken(); 22701fb5c3a6SDouglas Gregor 22717ff29148SBen Langmuir bool IsRequiresExcludedHack = false; 22727ff29148SBen Langmuir bool ShouldAddRequirement = 22737ff29148SBen Langmuir shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack); 22747ff29148SBen Langmuir 22757ff29148SBen Langmuir if (IsRequiresExcludedHack) 22767ff29148SBen Langmuir UsesRequiresExcludedHack.insert(ActiveModule); 22777ff29148SBen Langmuir 22787ff29148SBen Langmuir if (ShouldAddRequirement) { 22791fb5c3a6SDouglas Gregor // Add this feature. 22807ff29148SBen Langmuir ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts, 22817ff29148SBen Langmuir *Map.Target); 22827ff29148SBen Langmuir } 22831fb5c3a6SDouglas Gregor 22841fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Comma)) 22851fb5c3a6SDouglas Gregor break; 22861fb5c3a6SDouglas Gregor 22871fb5c3a6SDouglas Gregor // Consume the comma. 22881fb5c3a6SDouglas Gregor consumeToken(); 22891fb5c3a6SDouglas Gregor } while (true); 22901fb5c3a6SDouglas Gregor } 22911fb5c3a6SDouglas Gregor 22929fc8faf9SAdrian Prantl /// Parse a header declaration. 2293718292f2SDouglas Gregor /// 2294718292f2SDouglas Gregor /// header-declaration: 2295306d8920SRichard Smith /// 'textual'[opt] 'header' string-literal 2296202210b3SRichard Smith /// 'private' 'textual'[opt] 'header' string-literal 2297202210b3SRichard Smith /// 'exclude' 'header' string-literal 2298202210b3SRichard Smith /// 'umbrella' 'header' string-literal 2299306d8920SRichard Smith /// 2300306d8920SRichard Smith /// FIXME: Support 'private textual header'. 2301b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, 2302b53e5483SLawrence Crowl SourceLocation LeadingLoc) { 2303202210b3SRichard Smith // We've already consumed the first token. 2304202210b3SRichard Smith ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader; 2305202210b3SRichard Smith if (LeadingToken == MMToken::PrivateKeyword) { 2306202210b3SRichard Smith Role = ModuleMap::PrivateHeader; 2307202210b3SRichard Smith // 'private' may optionally be followed by 'textual'. 2308202210b3SRichard Smith if (Tok.is(MMToken::TextualKeyword)) { 2309202210b3SRichard Smith LeadingToken = Tok.Kind; 23101871ed3dSBenjamin Kramer consumeToken(); 2311202210b3SRichard Smith } 2312202210b3SRichard Smith } 23137ff29148SBen Langmuir 2314202210b3SRichard Smith if (LeadingToken == MMToken::TextualKeyword) 2315202210b3SRichard Smith Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 2316202210b3SRichard Smith 23177ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 23187ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 23197ff29148SBen Langmuir // Module::UsesRequiresExcludedHack). 23207ff29148SBen Langmuir Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 23217ff29148SBen Langmuir } 23227ff29148SBen Langmuir 2323202210b3SRichard Smith if (LeadingToken != MMToken::HeaderKeyword) { 2324202210b3SRichard Smith if (!Tok.is(MMToken::HeaderKeyword)) { 2325202210b3SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2326202210b3SRichard Smith << (LeadingToken == MMToken::PrivateKeyword ? "private" : 2327202210b3SRichard Smith LeadingToken == MMToken::ExcludeKeyword ? "exclude" : 2328202210b3SRichard Smith LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella"); 2329202210b3SRichard Smith return; 2330202210b3SRichard Smith } 2331202210b3SRichard Smith consumeToken(); 2332202210b3SRichard Smith } 2333718292f2SDouglas Gregor 2334718292f2SDouglas Gregor // Parse the header name. 2335718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2336718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2337718292f2SDouglas Gregor << "header"; 2338718292f2SDouglas Gregor HadError = true; 2339718292f2SDouglas Gregor return; 2340718292f2SDouglas Gregor } 23413c1a41adSRichard Smith Module::UnresolvedHeaderDirective Header; 2342adcd0268SBenjamin Kramer Header.FileName = std::string(Tok.getString()); 23430761a8a0SDaniel Jasper Header.FileNameLoc = consumeToken(); 23441d60987fSRichard Smith Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword; 2345040e1266SRichard Smith Header.Kind = 2346040e1266SRichard Smith (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded 2347040e1266SRichard Smith : Map.headerRoleToKind(Role)); 2348718292f2SDouglas Gregor 2349524e33e1SDouglas Gregor // Check whether we already have an umbrella. 23501d60987fSRichard Smith if (Header.IsUmbrella && ActiveModule->Umbrella) { 23510761a8a0SDaniel Jasper Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) 2352524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2353322f633cSDouglas Gregor HadError = true; 2354322f633cSDouglas Gregor return; 2355322f633cSDouglas Gregor } 2356322f633cSDouglas Gregor 2357040e1266SRichard Smith // If we were given stat information, parse it so we can skip looking for 2358040e1266SRichard Smith // the file. 2359040e1266SRichard Smith if (Tok.is(MMToken::LBrace)) { 2360040e1266SRichard Smith SourceLocation LBraceLoc = consumeToken(); 23613ec6663bSDouglas Gregor 2362040e1266SRichard Smith while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) { 2363040e1266SRichard Smith enum Attribute { Size, ModTime, Unknown }; 2364040e1266SRichard Smith StringRef Str = Tok.getString(); 2365040e1266SRichard Smith SourceLocation Loc = consumeToken(); 2366040e1266SRichard Smith switch (llvm::StringSwitch<Attribute>(Str) 2367040e1266SRichard Smith .Case("size", Size) 2368040e1266SRichard Smith .Case("mtime", ModTime) 2369040e1266SRichard Smith .Default(Unknown)) { 2370040e1266SRichard Smith case Size: 2371040e1266SRichard Smith if (Header.Size) 2372040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2373040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2374040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2375040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2376040e1266SRichard Smith skipUntil(MMToken::RBrace); 2377040e1266SRichard Smith break; 2378040e1266SRichard Smith } 2379040e1266SRichard Smith Header.Size = Tok.getInteger(); 2380040e1266SRichard Smith consumeToken(); 2381040e1266SRichard Smith break; 2382040e1266SRichard Smith 2383040e1266SRichard Smith case ModTime: 2384040e1266SRichard Smith if (Header.ModTime) 2385040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2386040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2387040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2388040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2389040e1266SRichard Smith skipUntil(MMToken::RBrace); 2390040e1266SRichard Smith break; 2391040e1266SRichard Smith } 2392040e1266SRichard Smith Header.ModTime = Tok.getInteger(); 2393040e1266SRichard Smith consumeToken(); 2394040e1266SRichard Smith break; 2395040e1266SRichard Smith 2396040e1266SRichard Smith case Unknown: 2397040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_expected_header_attribute); 2398040e1266SRichard Smith skipUntil(MMToken::RBrace); 2399040e1266SRichard Smith break; 2400040e1266SRichard Smith } 24013ec6663bSDouglas Gregor } 24025257fc63SDouglas Gregor 2403040e1266SRichard Smith if (Tok.is(MMToken::RBrace)) 2404040e1266SRichard Smith consumeToken(); 2405040e1266SRichard Smith else { 2406040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 2407040e1266SRichard Smith Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 2408322f633cSDouglas Gregor HadError = true; 2409322f633cSDouglas Gregor } 24100101b540SHans Wennborg } 241125d50758SRichard Smith 24129f6020bcSBruno Cardoso Lopes bool NeedsFramework = false; 24139f6020bcSBruno Cardoso Lopes Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework); 24149f6020bcSBruno Cardoso Lopes 24159f6020bcSBruno Cardoso Lopes if (NeedsFramework && ActiveModule) 24169f6020bcSBruno Cardoso Lopes Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword) 24179f6020bcSBruno Cardoso Lopes << ActiveModule->getFullModuleName() 24189f6020bcSBruno Cardoso Lopes << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module"); 2419718292f2SDouglas Gregor } 2420718292f2SDouglas Gregor 242141f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A, 242241f81994SBen Langmuir const Module::Header *B) { 242341f81994SBen Langmuir return A->NameAsWritten.compare(B->NameAsWritten); 242441f81994SBen Langmuir } 242541f81994SBen Langmuir 24269fc8faf9SAdrian Prantl /// Parse an umbrella directory declaration. 2427524e33e1SDouglas Gregor /// 2428524e33e1SDouglas Gregor /// umbrella-dir-declaration: 2429524e33e1SDouglas Gregor /// umbrella string-literal 2430524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { 2431524e33e1SDouglas Gregor // Parse the directory name. 2432524e33e1SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2433524e33e1SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2434524e33e1SDouglas Gregor << "umbrella"; 2435524e33e1SDouglas Gregor HadError = true; 2436524e33e1SDouglas Gregor return; 2437524e33e1SDouglas Gregor } 2438524e33e1SDouglas Gregor 2439adcd0268SBenjamin Kramer std::string DirName = std::string(Tok.getString()); 2440d3676d4bSMichael Spencer std::string DirNameAsWritten = DirName; 2441524e33e1SDouglas Gregor SourceLocation DirNameLoc = consumeToken(); 2442524e33e1SDouglas Gregor 2443524e33e1SDouglas Gregor // Check whether we already have an umbrella. 2444524e33e1SDouglas Gregor if (ActiveModule->Umbrella) { 2445524e33e1SDouglas Gregor Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash) 2446524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2447524e33e1SDouglas Gregor HadError = true; 2448524e33e1SDouglas Gregor return; 2449524e33e1SDouglas Gregor } 2450524e33e1SDouglas Gregor 2451524e33e1SDouglas Gregor // Look for this file. 245264d8c781SDuncan P. N. Exon Smith const DirectoryEntry *Dir = nullptr; 24538d323d15SHarlan Haskins if (llvm::sys::path::is_absolute(DirName)) { 245464d8c781SDuncan P. N. Exon Smith if (auto D = SourceMgr.getFileManager().getDirectory(DirName)) 24558d323d15SHarlan Haskins Dir = *D; 24568d323d15SHarlan Haskins } else { 24572c1dd271SDylan Noblesmith SmallString<128> PathName; 2458524e33e1SDouglas Gregor PathName = Directory->getName(); 2459524e33e1SDouglas Gregor llvm::sys::path::append(PathName, DirName); 246064d8c781SDuncan P. N. Exon Smith if (auto D = SourceMgr.getFileManager().getDirectory(PathName)) 24618d323d15SHarlan Haskins Dir = *D; 2462524e33e1SDouglas Gregor } 2463524e33e1SDouglas Gregor 2464524e33e1SDouglas Gregor if (!Dir) { 2465a0320b97SVassil Vassilev Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found) 2466524e33e1SDouglas Gregor << DirName; 2467524e33e1SDouglas Gregor return; 2468524e33e1SDouglas Gregor } 2469524e33e1SDouglas Gregor 24707ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 24717ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 24727ff29148SBen Langmuir // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the 24737ff29148SBen Langmuir // directory is relatively expensive, in practice this only applies to the 24747ff29148SBen Langmuir // uncommonly used Tcl module on Darwin platforms. 24757ff29148SBen Langmuir std::error_code EC; 24767ff29148SBen Langmuir SmallVector<Module::Header, 6> Headers; 2477fc51490bSJonas Devlieghere llvm::vfs::FileSystem &FS = 2478db8a7422SDuncan P. N. Exon Smith SourceMgr.getFileManager().getVirtualFileSystem(); 2479fc51490bSJonas Devlieghere for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E; 24807ff29148SBen Langmuir I != E && !EC; I.increment(EC)) { 248164d8c781SDuncan P. N. Exon Smith if (auto FE = SourceMgr.getFileManager().getFile(I->path())) { 2482d3676d4bSMichael Spencer Module::Header Header = {"", std::string(I->path()), *FE}; 24837ff29148SBen Langmuir Headers.push_back(std::move(Header)); 24847ff29148SBen Langmuir } 24857ff29148SBen Langmuir } 24867ff29148SBen Langmuir 24877ff29148SBen Langmuir // Sort header paths so that the pcm doesn't depend on iteration order. 248841f81994SBen Langmuir llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders); 248941f81994SBen Langmuir 24907ff29148SBen Langmuir for (auto &Header : Headers) 24917ff29148SBen Langmuir Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader); 24927ff29148SBen Langmuir return; 24937ff29148SBen Langmuir } 24947ff29148SBen Langmuir 249564d8c781SDuncan P. N. Exon Smith if (Module *OwningModule = Map.UmbrellaDirs[Dir]) { 2496524e33e1SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 2497524e33e1SDouglas Gregor << OwningModule->getFullModuleName(); 2498524e33e1SDouglas Gregor HadError = true; 2499524e33e1SDouglas Gregor return; 2500524e33e1SDouglas Gregor } 2501524e33e1SDouglas Gregor 2502524e33e1SDouglas Gregor // Record this umbrella directory. 2503d3676d4bSMichael Spencer Map.setUmbrellaDir(ActiveModule, Dir, DirNameAsWritten, DirName); 2504524e33e1SDouglas Gregor } 2505524e33e1SDouglas Gregor 25069fc8faf9SAdrian Prantl /// Parse a module export declaration. 25072b82c2a5SDouglas Gregor /// 25082b82c2a5SDouglas Gregor /// export-declaration: 25092b82c2a5SDouglas Gregor /// 'export' wildcard-module-id 25102b82c2a5SDouglas Gregor /// 25112b82c2a5SDouglas Gregor /// wildcard-module-id: 25122b82c2a5SDouglas Gregor /// identifier 25132b82c2a5SDouglas Gregor /// '*' 25142b82c2a5SDouglas Gregor /// identifier '.' wildcard-module-id 25152b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() { 25162b82c2a5SDouglas Gregor assert(Tok.is(MMToken::ExportKeyword)); 25172b82c2a5SDouglas Gregor SourceLocation ExportLoc = consumeToken(); 25182b82c2a5SDouglas Gregor 25192b82c2a5SDouglas Gregor // Parse the module-id with an optional wildcard at the end. 25202b82c2a5SDouglas Gregor ModuleId ParsedModuleId; 25212b82c2a5SDouglas Gregor bool Wildcard = false; 25222b82c2a5SDouglas Gregor do { 2523306d8920SRichard Smith // FIXME: Support string-literal module names here. 25242b82c2a5SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 2525adcd0268SBenjamin Kramer ParsedModuleId.push_back( 2526adcd0268SBenjamin Kramer std::make_pair(std::string(Tok.getString()), Tok.getLocation())); 25272b82c2a5SDouglas Gregor consumeToken(); 25282b82c2a5SDouglas Gregor 25292b82c2a5SDouglas Gregor if (Tok.is(MMToken::Period)) { 25302b82c2a5SDouglas Gregor consumeToken(); 25312b82c2a5SDouglas Gregor continue; 25322b82c2a5SDouglas Gregor } 25332b82c2a5SDouglas Gregor 25342b82c2a5SDouglas Gregor break; 25352b82c2a5SDouglas Gregor } 25362b82c2a5SDouglas Gregor 25372b82c2a5SDouglas Gregor if(Tok.is(MMToken::Star)) { 25382b82c2a5SDouglas Gregor Wildcard = true; 2539f5eedd05SDouglas Gregor consumeToken(); 25402b82c2a5SDouglas Gregor break; 25412b82c2a5SDouglas Gregor } 25422b82c2a5SDouglas Gregor 2543ba7f2f71SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_module_id); 25442b82c2a5SDouglas Gregor HadError = true; 25452b82c2a5SDouglas Gregor return; 25462b82c2a5SDouglas Gregor } while (true); 25472b82c2a5SDouglas Gregor 25482b82c2a5SDouglas Gregor Module::UnresolvedExportDecl Unresolved = { 25492b82c2a5SDouglas Gregor ExportLoc, ParsedModuleId, Wildcard 25502b82c2a5SDouglas Gregor }; 25512b82c2a5SDouglas Gregor ActiveModule->UnresolvedExports.push_back(Unresolved); 25522b82c2a5SDouglas Gregor } 25532b82c2a5SDouglas Gregor 25549fc8faf9SAdrian Prantl /// Parse a module export_as declaration. 2555f0b11de2SDouglas Gregor /// 2556f0b11de2SDouglas Gregor /// export-as-declaration: 2557f0b11de2SDouglas Gregor /// 'export_as' identifier 2558f0b11de2SDouglas Gregor void ModuleMapParser::parseExportAsDecl() { 2559f0b11de2SDouglas Gregor assert(Tok.is(MMToken::ExportAsKeyword)); 2560f0b11de2SDouglas Gregor consumeToken(); 2561f0b11de2SDouglas Gregor 2562f0b11de2SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 2563f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_module_id); 2564f0b11de2SDouglas Gregor HadError = true; 2565f0b11de2SDouglas Gregor return; 2566f0b11de2SDouglas Gregor } 2567f0b11de2SDouglas Gregor 2568f0b11de2SDouglas Gregor if (ActiveModule->Parent) { 2569f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as); 2570f0b11de2SDouglas Gregor consumeToken(); 2571f0b11de2SDouglas Gregor return; 2572f0b11de2SDouglas Gregor } 2573f0b11de2SDouglas Gregor 2574f0b11de2SDouglas Gregor if (!ActiveModule->ExportAsModule.empty()) { 2575f0b11de2SDouglas Gregor if (ActiveModule->ExportAsModule == Tok.getString()) { 2576f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as) 2577f0b11de2SDouglas Gregor << ActiveModule->Name << Tok.getString(); 2578f0b11de2SDouglas Gregor } else { 2579f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as) 2580f0b11de2SDouglas Gregor << ActiveModule->Name << ActiveModule->ExportAsModule 2581f0b11de2SDouglas Gregor << Tok.getString(); 2582f0b11de2SDouglas Gregor } 2583f0b11de2SDouglas Gregor } 2584f0b11de2SDouglas Gregor 2585adcd0268SBenjamin Kramer ActiveModule->ExportAsModule = std::string(Tok.getString()); 2586a3b5f71eSBruno Cardoso Lopes Map.addLinkAsDependency(ActiveModule); 2587a3b5f71eSBruno Cardoso Lopes 2588f0b11de2SDouglas Gregor consumeToken(); 2589f0b11de2SDouglas Gregor } 2590f0b11de2SDouglas Gregor 25919fc8faf9SAdrian Prantl /// Parse a module use declaration. 2592ba7f2f71SDaniel Jasper /// 25938f4d3ff1SRichard Smith /// use-declaration: 25948f4d3ff1SRichard Smith /// 'use' wildcard-module-id 2595ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() { 2596ba7f2f71SDaniel Jasper assert(Tok.is(MMToken::UseKeyword)); 25978f4d3ff1SRichard Smith auto KWLoc = consumeToken(); 2598ba7f2f71SDaniel Jasper // Parse the module-id. 2599ba7f2f71SDaniel Jasper ModuleId ParsedModuleId; 26003cd34c76SDaniel Jasper parseModuleId(ParsedModuleId); 2601ba7f2f71SDaniel Jasper 26028f4d3ff1SRichard Smith if (ActiveModule->Parent) 26038f4d3ff1SRichard Smith Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule); 26048f4d3ff1SRichard Smith else 2605ba7f2f71SDaniel Jasper ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId); 2606ba7f2f71SDaniel Jasper } 2607ba7f2f71SDaniel Jasper 26089fc8faf9SAdrian Prantl /// Parse a link declaration. 26096ddfca91SDouglas Gregor /// 26106ddfca91SDouglas Gregor /// module-declaration: 26116ddfca91SDouglas Gregor /// 'link' 'framework'[opt] string-literal 26126ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() { 26136ddfca91SDouglas Gregor assert(Tok.is(MMToken::LinkKeyword)); 26146ddfca91SDouglas Gregor SourceLocation LinkLoc = consumeToken(); 26156ddfca91SDouglas Gregor 26166ddfca91SDouglas Gregor // Parse the optional 'framework' keyword. 26176ddfca91SDouglas Gregor bool IsFramework = false; 26186ddfca91SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 26196ddfca91SDouglas Gregor consumeToken(); 26206ddfca91SDouglas Gregor IsFramework = true; 26216ddfca91SDouglas Gregor } 26226ddfca91SDouglas Gregor 26236ddfca91SDouglas Gregor // Parse the library name 26246ddfca91SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 26256ddfca91SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name) 26266ddfca91SDouglas Gregor << IsFramework << SourceRange(LinkLoc); 26276ddfca91SDouglas Gregor HadError = true; 26286ddfca91SDouglas Gregor return; 26296ddfca91SDouglas Gregor } 26306ddfca91SDouglas Gregor 2631adcd0268SBenjamin Kramer std::string LibraryName = std::string(Tok.getString()); 26326ddfca91SDouglas Gregor consumeToken(); 26336ddfca91SDouglas Gregor ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName, 26346ddfca91SDouglas Gregor IsFramework)); 26356ddfca91SDouglas Gregor } 26366ddfca91SDouglas Gregor 26379fc8faf9SAdrian Prantl /// Parse a configuration macro declaration. 263835b13eceSDouglas Gregor /// 263935b13eceSDouglas Gregor /// module-declaration: 264035b13eceSDouglas Gregor /// 'config_macros' attributes[opt] config-macro-list? 264135b13eceSDouglas Gregor /// 264235b13eceSDouglas Gregor /// config-macro-list: 264335b13eceSDouglas Gregor /// identifier (',' identifier)? 264435b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() { 264535b13eceSDouglas Gregor assert(Tok.is(MMToken::ConfigMacros)); 264635b13eceSDouglas Gregor SourceLocation ConfigMacrosLoc = consumeToken(); 264735b13eceSDouglas Gregor 264835b13eceSDouglas Gregor // Only top-level modules can have configuration macros. 264935b13eceSDouglas Gregor if (ActiveModule->Parent) { 265035b13eceSDouglas Gregor Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule); 265135b13eceSDouglas Gregor } 265235b13eceSDouglas Gregor 265335b13eceSDouglas Gregor // Parse the optional attributes. 265435b13eceSDouglas Gregor Attributes Attrs; 26555d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 26565d29dee0SDavide Italiano return; 26575d29dee0SDavide Italiano 265835b13eceSDouglas Gregor if (Attrs.IsExhaustive && !ActiveModule->Parent) { 265935b13eceSDouglas Gregor ActiveModule->ConfigMacrosExhaustive = true; 266035b13eceSDouglas Gregor } 266135b13eceSDouglas Gregor 266235b13eceSDouglas Gregor // If we don't have an identifier, we're done. 2663306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 266435b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) 266535b13eceSDouglas Gregor return; 266635b13eceSDouglas Gregor 266735b13eceSDouglas Gregor // Consume the first identifier. 266835b13eceSDouglas Gregor if (!ActiveModule->Parent) { 266935b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 267035b13eceSDouglas Gregor } 267135b13eceSDouglas Gregor consumeToken(); 267235b13eceSDouglas Gregor 267335b13eceSDouglas Gregor do { 267435b13eceSDouglas Gregor // If there's a comma, consume it. 267535b13eceSDouglas Gregor if (!Tok.is(MMToken::Comma)) 267635b13eceSDouglas Gregor break; 267735b13eceSDouglas Gregor consumeToken(); 267835b13eceSDouglas Gregor 267935b13eceSDouglas Gregor // We expect to see a macro name here. 2680306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 268135b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 268235b13eceSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro); 268335b13eceSDouglas Gregor break; 268435b13eceSDouglas Gregor } 268535b13eceSDouglas Gregor 268635b13eceSDouglas Gregor // Consume the macro name. 268735b13eceSDouglas Gregor if (!ActiveModule->Parent) { 268835b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 268935b13eceSDouglas Gregor } 269035b13eceSDouglas Gregor consumeToken(); 269135b13eceSDouglas Gregor } while (true); 269235b13eceSDouglas Gregor } 269335b13eceSDouglas Gregor 26949fc8faf9SAdrian Prantl /// Format a module-id into a string. 2695fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) { 2696fb912657SDouglas Gregor std::string result; 2697fb912657SDouglas Gregor { 2698fb912657SDouglas Gregor llvm::raw_string_ostream OS(result); 2699fb912657SDouglas Gregor 2700fb912657SDouglas Gregor for (unsigned I = 0, N = Id.size(); I != N; ++I) { 2701fb912657SDouglas Gregor if (I) 2702fb912657SDouglas Gregor OS << "."; 2703fb912657SDouglas Gregor OS << Id[I].first; 2704fb912657SDouglas Gregor } 2705fb912657SDouglas Gregor } 2706fb912657SDouglas Gregor 2707fb912657SDouglas Gregor return result; 2708fb912657SDouglas Gregor } 2709fb912657SDouglas Gregor 27109fc8faf9SAdrian Prantl /// Parse a conflict declaration. 2711fb912657SDouglas Gregor /// 2712fb912657SDouglas Gregor /// module-declaration: 2713fb912657SDouglas Gregor /// 'conflict' module-id ',' string-literal 2714fb912657SDouglas Gregor void ModuleMapParser::parseConflict() { 2715fb912657SDouglas Gregor assert(Tok.is(MMToken::Conflict)); 2716fb912657SDouglas Gregor SourceLocation ConflictLoc = consumeToken(); 2717fb912657SDouglas Gregor Module::UnresolvedConflict Conflict; 2718fb912657SDouglas Gregor 2719fb912657SDouglas Gregor // Parse the module-id. 2720fb912657SDouglas Gregor if (parseModuleId(Conflict.Id)) 2721fb912657SDouglas Gregor return; 2722fb912657SDouglas Gregor 2723fb912657SDouglas Gregor // Parse the ','. 2724fb912657SDouglas Gregor if (!Tok.is(MMToken::Comma)) { 2725fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma) 2726fb912657SDouglas Gregor << SourceRange(ConflictLoc); 2727fb912657SDouglas Gregor return; 2728fb912657SDouglas Gregor } 2729fb912657SDouglas Gregor consumeToken(); 2730fb912657SDouglas Gregor 2731fb912657SDouglas Gregor // Parse the message. 2732fb912657SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2733fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message) 2734fb912657SDouglas Gregor << formatModuleId(Conflict.Id); 2735fb912657SDouglas Gregor return; 2736fb912657SDouglas Gregor } 2737fb912657SDouglas Gregor Conflict.Message = Tok.getString().str(); 2738fb912657SDouglas Gregor consumeToken(); 2739fb912657SDouglas Gregor 2740fb912657SDouglas Gregor // Add this unresolved conflict. 2741fb912657SDouglas Gregor ActiveModule->UnresolvedConflicts.push_back(Conflict); 2742fb912657SDouglas Gregor } 2743fb912657SDouglas Gregor 27449fc8faf9SAdrian Prantl /// Parse an inferred module declaration (wildcard modules). 27459194a91dSDouglas Gregor /// 27469194a91dSDouglas Gregor /// module-declaration: 27479194a91dSDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt] 27489194a91dSDouglas Gregor /// { inferred-module-member* } 27499194a91dSDouglas Gregor /// 27509194a91dSDouglas Gregor /// inferred-module-member: 27519194a91dSDouglas Gregor /// 'export' '*' 27529194a91dSDouglas Gregor /// 'exclude' identifier 27539194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { 275473441091SDouglas Gregor assert(Tok.is(MMToken::Star)); 275573441091SDouglas Gregor SourceLocation StarLoc = consumeToken(); 275673441091SDouglas Gregor bool Failed = false; 275773441091SDouglas Gregor 275873441091SDouglas Gregor // Inferred modules must be submodules. 27599194a91dSDouglas Gregor if (!ActiveModule && !Framework) { 276073441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule); 276173441091SDouglas Gregor Failed = true; 276273441091SDouglas Gregor } 276373441091SDouglas Gregor 27649194a91dSDouglas Gregor if (ActiveModule) { 2765524e33e1SDouglas Gregor // Inferred modules must have umbrella directories. 27664898cde4SBen Langmuir if (!Failed && ActiveModule->IsAvailable && 27674898cde4SBen Langmuir !ActiveModule->getUmbrellaDir()) { 276873441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); 276973441091SDouglas Gregor Failed = true; 277073441091SDouglas Gregor } 277173441091SDouglas Gregor 277273441091SDouglas Gregor // Check for redefinition of an inferred module. 2773dd005f69SDouglas Gregor if (!Failed && ActiveModule->InferSubmodules) { 277473441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_redef); 2775dd005f69SDouglas Gregor if (ActiveModule->InferredSubmoduleLoc.isValid()) 2776dd005f69SDouglas Gregor Diags.Report(ActiveModule->InferredSubmoduleLoc, 277773441091SDouglas Gregor diag::note_mmap_prev_definition); 277873441091SDouglas Gregor Failed = true; 277973441091SDouglas Gregor } 278073441091SDouglas Gregor 27819194a91dSDouglas Gregor // Check for the 'framework' keyword, which is not permitted here. 27829194a91dSDouglas Gregor if (Framework) { 27839194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule); 27849194a91dSDouglas Gregor Framework = false; 27859194a91dSDouglas Gregor } 27869194a91dSDouglas Gregor } else if (Explicit) { 27879194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework); 27889194a91dSDouglas Gregor Explicit = false; 27899194a91dSDouglas Gregor } 27909194a91dSDouglas Gregor 279173441091SDouglas Gregor // If there were any problems with this inferred submodule, skip its body. 279273441091SDouglas Gregor if (Failed) { 279373441091SDouglas Gregor if (Tok.is(MMToken::LBrace)) { 279473441091SDouglas Gregor consumeToken(); 279573441091SDouglas Gregor skipUntil(MMToken::RBrace); 279673441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 279773441091SDouglas Gregor consumeToken(); 279873441091SDouglas Gregor } 279973441091SDouglas Gregor HadError = true; 280073441091SDouglas Gregor return; 280173441091SDouglas Gregor } 280273441091SDouglas Gregor 28039194a91dSDouglas Gregor // Parse optional attributes. 28044442605fSBill Wendling Attributes Attrs; 28055d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 28065d29dee0SDavide Italiano return; 28079194a91dSDouglas Gregor 28089194a91dSDouglas Gregor if (ActiveModule) { 280973441091SDouglas Gregor // Note that we have an inferred submodule. 2810dd005f69SDouglas Gregor ActiveModule->InferSubmodules = true; 2811dd005f69SDouglas Gregor ActiveModule->InferredSubmoduleLoc = StarLoc; 2812dd005f69SDouglas Gregor ActiveModule->InferExplicitSubmodules = Explicit; 28139194a91dSDouglas Gregor } else { 28149194a91dSDouglas Gregor // We'll be inferring framework modules for this directory. 28159194a91dSDouglas Gregor Map.InferredDirectories[Directory].InferModules = true; 2816c1d88ea5SBen Langmuir Map.InferredDirectories[Directory].Attrs = Attrs; 2817beee15e7SBen Langmuir Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile; 2818131daca0SRichard Smith // FIXME: Handle the 'framework' keyword. 28199194a91dSDouglas Gregor } 282073441091SDouglas Gregor 282173441091SDouglas Gregor // Parse the opening brace. 282273441091SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 282373441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard); 282473441091SDouglas Gregor HadError = true; 282573441091SDouglas Gregor return; 282673441091SDouglas Gregor } 282773441091SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 282873441091SDouglas Gregor 282973441091SDouglas Gregor // Parse the body of the inferred submodule. 283073441091SDouglas Gregor bool Done = false; 283173441091SDouglas Gregor do { 283273441091SDouglas Gregor switch (Tok.Kind) { 283373441091SDouglas Gregor case MMToken::EndOfFile: 283473441091SDouglas Gregor case MMToken::RBrace: 283573441091SDouglas Gregor Done = true; 283673441091SDouglas Gregor break; 283773441091SDouglas Gregor 2838afd1b1c9SEugene Zelenko case MMToken::ExcludeKeyword: 28399194a91dSDouglas Gregor if (ActiveModule) { 28409194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2841d2d442caSCraig Topper << (ActiveModule != nullptr); 28429194a91dSDouglas Gregor consumeToken(); 28439194a91dSDouglas Gregor break; 28449194a91dSDouglas Gregor } 28459194a91dSDouglas Gregor 28469194a91dSDouglas Gregor consumeToken(); 2847306d8920SRichard Smith // FIXME: Support string-literal module names here. 28489194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 28499194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name); 28509194a91dSDouglas Gregor break; 28519194a91dSDouglas Gregor } 28529194a91dSDouglas Gregor 2853adcd0268SBenjamin Kramer Map.InferredDirectories[Directory].ExcludedModules.push_back( 2854adcd0268SBenjamin Kramer std::string(Tok.getString())); 28559194a91dSDouglas Gregor consumeToken(); 28569194a91dSDouglas Gregor break; 28579194a91dSDouglas Gregor 28589194a91dSDouglas Gregor case MMToken::ExportKeyword: 28599194a91dSDouglas Gregor if (!ActiveModule) { 28609194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2861d2d442caSCraig Topper << (ActiveModule != nullptr); 28629194a91dSDouglas Gregor consumeToken(); 28639194a91dSDouglas Gregor break; 28649194a91dSDouglas Gregor } 28659194a91dSDouglas Gregor 286673441091SDouglas Gregor consumeToken(); 286773441091SDouglas Gregor if (Tok.is(MMToken::Star)) 2868dd005f69SDouglas Gregor ActiveModule->InferExportWildcard = true; 286973441091SDouglas Gregor else 287073441091SDouglas Gregor Diags.Report(Tok.getLocation(), 287173441091SDouglas Gregor diag::err_mmap_expected_export_wildcard); 287273441091SDouglas Gregor consumeToken(); 287373441091SDouglas Gregor break; 287473441091SDouglas Gregor 287573441091SDouglas Gregor case MMToken::ExplicitKeyword: 287673441091SDouglas Gregor case MMToken::ModuleKeyword: 287773441091SDouglas Gregor case MMToken::HeaderKeyword: 2878b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 287973441091SDouglas Gregor case MMToken::UmbrellaKeyword: 288073441091SDouglas Gregor default: 28819194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2882d2d442caSCraig Topper << (ActiveModule != nullptr); 288373441091SDouglas Gregor consumeToken(); 288473441091SDouglas Gregor break; 288573441091SDouglas Gregor } 288673441091SDouglas Gregor } while (!Done); 288773441091SDouglas Gregor 288873441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 288973441091SDouglas Gregor consumeToken(); 289073441091SDouglas Gregor else { 289173441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 289273441091SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 289373441091SDouglas Gregor HadError = true; 289473441091SDouglas Gregor } 289573441091SDouglas Gregor } 289673441091SDouglas Gregor 28979fc8faf9SAdrian Prantl /// Parse optional attributes. 28989194a91dSDouglas Gregor /// 28999194a91dSDouglas Gregor /// attributes: 29009194a91dSDouglas Gregor /// attribute attributes 29019194a91dSDouglas Gregor /// attribute 29029194a91dSDouglas Gregor /// 29039194a91dSDouglas Gregor /// attribute: 29049194a91dSDouglas Gregor /// [ identifier ] 29059194a91dSDouglas Gregor /// 29069194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes. 29079194a91dSDouglas Gregor /// 29089194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise. 29094442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { 29109194a91dSDouglas Gregor bool HadError = false; 29119194a91dSDouglas Gregor 29129194a91dSDouglas Gregor while (Tok.is(MMToken::LSquare)) { 29139194a91dSDouglas Gregor // Consume the '['. 29149194a91dSDouglas Gregor SourceLocation LSquareLoc = consumeToken(); 29159194a91dSDouglas Gregor 29169194a91dSDouglas Gregor // Check whether we have an attribute name here. 29179194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 29189194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute); 29199194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 29209194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 29219194a91dSDouglas Gregor consumeToken(); 29229194a91dSDouglas Gregor HadError = true; 29239194a91dSDouglas Gregor } 29249194a91dSDouglas Gregor 29259194a91dSDouglas Gregor // Decode the attribute name. 29269194a91dSDouglas Gregor AttributeKind Attribute 29279194a91dSDouglas Gregor = llvm::StringSwitch<AttributeKind>(Tok.getString()) 292835b13eceSDouglas Gregor .Case("exhaustive", AT_exhaustive) 292977944868SRichard Smith .Case("extern_c", AT_extern_c) 2930ed84df00SBruno Cardoso Lopes .Case("no_undeclared_includes", AT_no_undeclared_includes) 29319194a91dSDouglas Gregor .Case("system", AT_system) 29329194a91dSDouglas Gregor .Default(AT_unknown); 29339194a91dSDouglas Gregor switch (Attribute) { 29349194a91dSDouglas Gregor case AT_unknown: 29359194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute) 29369194a91dSDouglas Gregor << Tok.getString(); 29379194a91dSDouglas Gregor break; 29389194a91dSDouglas Gregor 29399194a91dSDouglas Gregor case AT_system: 29409194a91dSDouglas Gregor Attrs.IsSystem = true; 29419194a91dSDouglas Gregor break; 294235b13eceSDouglas Gregor 294377944868SRichard Smith case AT_extern_c: 294477944868SRichard Smith Attrs.IsExternC = true; 294577944868SRichard Smith break; 294677944868SRichard Smith 294735b13eceSDouglas Gregor case AT_exhaustive: 294835b13eceSDouglas Gregor Attrs.IsExhaustive = true; 294935b13eceSDouglas Gregor break; 2950ed84df00SBruno Cardoso Lopes 2951ed84df00SBruno Cardoso Lopes case AT_no_undeclared_includes: 2952ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes = true; 2953ed84df00SBruno Cardoso Lopes break; 29549194a91dSDouglas Gregor } 29559194a91dSDouglas Gregor consumeToken(); 29569194a91dSDouglas Gregor 29579194a91dSDouglas Gregor // Consume the ']'. 29589194a91dSDouglas Gregor if (!Tok.is(MMToken::RSquare)) { 29599194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare); 29609194a91dSDouglas Gregor Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match); 29619194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 29629194a91dSDouglas Gregor HadError = true; 29639194a91dSDouglas Gregor } 29649194a91dSDouglas Gregor 29659194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 29669194a91dSDouglas Gregor consumeToken(); 29679194a91dSDouglas Gregor } 29689194a91dSDouglas Gregor 29699194a91dSDouglas Gregor return HadError; 29709194a91dSDouglas Gregor } 29719194a91dSDouglas Gregor 29729fc8faf9SAdrian Prantl /// Parse a module map file. 2973718292f2SDouglas Gregor /// 2974718292f2SDouglas Gregor /// module-map-file: 2975718292f2SDouglas Gregor /// module-declaration* 2976718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 2977718292f2SDouglas Gregor do { 2978718292f2SDouglas Gregor switch (Tok.Kind) { 2979718292f2SDouglas Gregor case MMToken::EndOfFile: 2980718292f2SDouglas Gregor return HadError; 2981718292f2SDouglas Gregor 2982e7ab3669SDouglas Gregor case MMToken::ExplicitKeyword: 298397292843SDaniel Jasper case MMToken::ExternKeyword: 2984718292f2SDouglas Gregor case MMToken::ModuleKeyword: 2985755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 2986718292f2SDouglas Gregor parseModuleDecl(); 2987718292f2SDouglas Gregor break; 2988718292f2SDouglas Gregor 29891fb5c3a6SDouglas Gregor case MMToken::Comma: 299035b13eceSDouglas Gregor case MMToken::ConfigMacros: 2991fb912657SDouglas Gregor case MMToken::Conflict: 2992a3feee2aSRichard Smith case MMToken::Exclaim: 299359527666SDouglas Gregor case MMToken::ExcludeKeyword: 29942b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 2995f0b11de2SDouglas Gregor case MMToken::ExportAsKeyword: 2996718292f2SDouglas Gregor case MMToken::HeaderKeyword: 2997718292f2SDouglas Gregor case MMToken::Identifier: 2998718292f2SDouglas Gregor case MMToken::LBrace: 29996ddfca91SDouglas Gregor case MMToken::LinkKeyword: 3000a686e1b0SDouglas Gregor case MMToken::LSquare: 30012b82c2a5SDouglas Gregor case MMToken::Period: 3002b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 3003718292f2SDouglas Gregor case MMToken::RBrace: 3004a686e1b0SDouglas Gregor case MMToken::RSquare: 30051fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 30062b82c2a5SDouglas Gregor case MMToken::Star: 3007718292f2SDouglas Gregor case MMToken::StringLiteral: 3008040e1266SRichard Smith case MMToken::IntegerLiteral: 3009b8afebe2SRichard Smith case MMToken::TextualKeyword: 3010718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 3011ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 3012718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 3013718292f2SDouglas Gregor HadError = true; 3014718292f2SDouglas Gregor consumeToken(); 3015718292f2SDouglas Gregor break; 3016718292f2SDouglas Gregor } 3017718292f2SDouglas Gregor } while (true); 3018718292f2SDouglas Gregor } 3019718292f2SDouglas Gregor 30207799ef71SNico Weber bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem, 3021c192d194SBruno Cardoso Lopes const DirectoryEntry *Dir, FileID ID, 30228128f332SRichard Smith unsigned *Offset, 3023ae6df27eSRichard Smith SourceLocation ExternModuleLoc) { 30248128f332SRichard Smith assert(Target && "Missing target information"); 30254ddf2221SDouglas Gregor llvm::DenseMap<const FileEntry *, bool>::iterator Known 30264ddf2221SDouglas Gregor = ParsedModuleMap.find(File); 30274ddf2221SDouglas Gregor if (Known != ParsedModuleMap.end()) 30284ddf2221SDouglas Gregor return Known->second; 30294ddf2221SDouglas Gregor 30308128f332SRichard Smith // If the module map file wasn't already entered, do so now. 30318128f332SRichard Smith if (ID.isInvalid()) { 3032f3f84616SRichard Smith auto FileCharacter = 3033f3f84616SRichard Smith IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap; 30348128f332SRichard Smith ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter); 30358128f332SRichard Smith } 30368128f332SRichard Smith 30378128f332SRichard Smith assert(Target && "Missing target information"); 3038b03ae743SDuncan P. N. Exon Smith llvm::Optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID); 3039718292f2SDouglas Gregor if (!Buffer) 30404ddf2221SDouglas Gregor return ParsedModuleMap[File] = true; 30418128f332SRichard Smith assert((!Offset || *Offset <= Buffer->getBufferSize()) && 30428128f332SRichard Smith "invalid buffer offset"); 3043718292f2SDouglas Gregor 3044718292f2SDouglas Gregor // Parse this module map file. 30458128f332SRichard Smith Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts, 30468128f332SRichard Smith Buffer->getBufferStart(), 30478128f332SRichard Smith Buffer->getBufferStart() + (Offset ? *Offset : 0), 30488128f332SRichard Smith Buffer->getBufferEnd()); 30492a6edb30SRichard Smith SourceLocation Start = L.getSourceLocation(); 3050beee15e7SBen Langmuir ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir, 3051c192d194SBruno Cardoso Lopes IsSystem); 3052718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 30534ddf2221SDouglas Gregor ParsedModuleMap[File] = Result; 30542a6edb30SRichard Smith 30558128f332SRichard Smith if (Offset) { 30568128f332SRichard Smith auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation()); 30578128f332SRichard Smith assert(Loc.first == ID && "stopped in a different file?"); 30588128f332SRichard Smith *Offset = Loc.second; 30598128f332SRichard Smith } 30608128f332SRichard Smith 30612a6edb30SRichard Smith // Notify callbacks that we parsed it. 30622a6edb30SRichard Smith for (const auto &Cb : Callbacks) 30632a6edb30SRichard Smith Cb->moduleMapFileRead(Start, *File, IsSystem); 30648587dfd9SBruno Cardoso Lopes 3065718292f2SDouglas Gregor return Result; 3066718292f2SDouglas Gregor } 3067