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. 1701d60987fSRichard Smith for (unsigned I = Paths.size() - 1; I != 0; --I) 1711d60987fSRichard Smith llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework"); 1721d60987fSRichard Smith } 1731d60987fSRichard Smith 174*f85db7f7SDuncan 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 181*f85db7f7SDuncan P. N. Exon Smith auto GetFile = [&](StringRef Filename) -> Optional<FileEntryRef> { 182*f85db7f7SDuncan P. N. Exon Smith auto File = 183*f85db7f7SDuncan P. N. Exon Smith expectedToOptional(SourceMgr.getFileManager().getFileRef(Filename)); 184*f85db7f7SDuncan P. N. Exon Smith if (!File || (Header.Size && File->getSize() != *Header.Size) || 185*f85db7f7SDuncan P. N. Exon Smith (Header.ModTime && File->getModificationTime() != *Header.ModTime)) 186*f85db7f7SDuncan P. N. Exon Smith return None; 1878d323d15SHarlan Haskins return *File; 188040e1266SRichard Smith }; 189040e1266SRichard Smith 190*f85db7f7SDuncan 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); 198*f85db7f7SDuncan 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); 230*f85db7f7SDuncan 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 } 244*f85db7f7SDuncan 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; 254*f85db7f7SDuncan P. N. Exon Smith if (Optional<FileEntryRef> File = 2559f6020bcSBruno Cardoso Lopes findHeader(Mod, Header, RelativePathName, NeedsFramework)) { 256040e1266SRichard Smith if (Header.IsUmbrella) { 257*f85db7f7SDuncan 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. 263*f85db7f7SDuncan P. N. Exon Smith setUmbrellaHeader(Mod, *File, RelativePathName.str()); 264040e1266SRichard Smith } else { 265*f85db7f7SDuncan P. N. Exon Smith Module::Header H = {std::string(RelativePathName.str()), *File}; 266040e1266SRichard Smith if (Header.Kind == Module::HK_Excluded) 267040e1266SRichard Smith excludeHeader(Mod, H); 268040e1266SRichard Smith else 269040e1266SRichard Smith addHeader(Mod, H, headerKindToRole(Header.Kind)); 270040e1266SRichard Smith } 271040e1266SRichard Smith } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) { 272040e1266SRichard Smith // There's a builtin header but no corresponding on-disk header. Assume 273040e1266SRichard Smith // this was supposed to modularize the builtin header alone. 274040e1266SRichard Smith } else if (Header.Kind == Module::HK_Excluded) { 275040e1266SRichard Smith // Ignore missing excluded header files. They're optional anyway. 276040e1266SRichard Smith } else { 277040e1266SRichard Smith // If we find a module that has a missing header, we mark this module as 278040e1266SRichard Smith // unavailable and store the header directive for displaying diagnostics. 279040e1266SRichard Smith Mod->MissingHeaders.push_back(Header); 280040e1266SRichard Smith // A missing header with stat information doesn't make the module 281040e1266SRichard Smith // unavailable; this keeps our behavior consistent as headers are lazily 282040e1266SRichard Smith // resolved. (Such a module still can't be built though, except from 283040e1266SRichard Smith // preprocessed source.) 284040e1266SRichard Smith if (!Header.Size && !Header.ModTime) 285fc76b4adSRichard Smith Mod->markUnavailable(/*Unimportable=*/false); 286040e1266SRichard Smith } 287040e1266SRichard Smith } 288040e1266SRichard Smith 289040e1266SRichard Smith bool ModuleMap::resolveAsBuiltinHeader( 290040e1266SRichard Smith Module *Mod, const Module::UnresolvedHeaderDirective &Header) { 291040e1266SRichard Smith if (Header.Kind == Module::HK_Excluded || 292040e1266SRichard Smith llvm::sys::path::is_absolute(Header.FileName) || 293040e1266SRichard Smith Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella || 294040e1266SRichard Smith !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory || 295040e1266SRichard Smith !isBuiltinHeader(Header.FileName)) 296040e1266SRichard Smith return false; 2971d60987fSRichard Smith 2981d60987fSRichard Smith // This is a system module with a top-level header. This header 2991d60987fSRichard Smith // may have a counterpart (or replacement) in the set of headers 3001d60987fSRichard Smith // supplied by Clang. Find that builtin header. 301040e1266SRichard Smith SmallString<128> Path; 302040e1266SRichard Smith llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName); 3038d323d15SHarlan Haskins auto File = SourceMgr.getFileManager().getFile(Path); 304040e1266SRichard Smith if (!File) 305040e1266SRichard Smith return false; 306040e1266SRichard Smith 307040e1266SRichard Smith auto Role = headerKindToRole(Header.Kind); 308adcd0268SBenjamin Kramer Module::Header H = {std::string(Path.str()), *File}; 309040e1266SRichard Smith addHeader(Mod, H, Role); 310040e1266SRichard Smith return true; 3111d60987fSRichard Smith } 3121d60987fSRichard Smith 3130761a8a0SDaniel Jasper ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags, 314b146baabSArgyrios Kyrtzidis const LangOptions &LangOpts, const TargetInfo *Target, 315b146baabSArgyrios Kyrtzidis HeaderSearch &HeaderInfo) 3160761a8a0SDaniel Jasper : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target), 317056bf77fSRichard Smith HeaderInfo(HeaderInfo) { 3180414b857SRichard Smith MMapLangOpts.LineComment = true; 3190414b857SRichard Smith } 320718292f2SDouglas Gregor 321718292f2SDouglas Gregor ModuleMap::~ModuleMap() { 32221668754SDavide Italiano for (auto &M : Modules) 32321668754SDavide Italiano delete M.getValue(); 3248587dfd9SBruno Cardoso Lopes for (auto *M : ShadowModules) 3258587dfd9SBruno Cardoso Lopes delete M; 326718292f2SDouglas Gregor } 327718292f2SDouglas Gregor 32889929282SDouglas Gregor void ModuleMap::setTarget(const TargetInfo &Target) { 32989929282SDouglas Gregor assert((!this->Target || this->Target == &Target) && 33089929282SDouglas Gregor "Improper target override"); 33189929282SDouglas Gregor this->Target = &Target; 33289929282SDouglas Gregor } 33389929282SDouglas Gregor 3349fc8faf9SAdrian Prantl /// "Sanitize" a filename so that it can be used as an identifier. 335056396aeSDouglas Gregor static StringRef sanitizeFilenameAsIdentifier(StringRef Name, 336056396aeSDouglas Gregor SmallVectorImpl<char> &Buffer) { 337056396aeSDouglas Gregor if (Name.empty()) 338056396aeSDouglas Gregor return Name; 339056396aeSDouglas Gregor 340a7d03840SJordan Rose if (!isValidIdentifier(Name)) { 341056396aeSDouglas Gregor // If we don't already have something with the form of an identifier, 342056396aeSDouglas Gregor // create a buffer with the sanitized name. 343056396aeSDouglas Gregor Buffer.clear(); 344a7d03840SJordan Rose if (isDigit(Name[0])) 345056396aeSDouglas Gregor Buffer.push_back('_'); 346056396aeSDouglas Gregor Buffer.reserve(Buffer.size() + Name.size()); 347056396aeSDouglas Gregor for (unsigned I = 0, N = Name.size(); I != N; ++I) { 348a7d03840SJordan Rose if (isIdentifierBody(Name[I])) 349056396aeSDouglas Gregor Buffer.push_back(Name[I]); 350056396aeSDouglas Gregor else 351056396aeSDouglas Gregor Buffer.push_back('_'); 352056396aeSDouglas Gregor } 353056396aeSDouglas Gregor 354056396aeSDouglas Gregor Name = StringRef(Buffer.data(), Buffer.size()); 355056396aeSDouglas Gregor } 356056396aeSDouglas Gregor 357056396aeSDouglas Gregor while (llvm::StringSwitch<bool>(Name) 358056396aeSDouglas Gregor #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true) 359056396aeSDouglas Gregor #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true) 360056396aeSDouglas Gregor #include "clang/Basic/TokenKinds.def" 361056396aeSDouglas Gregor .Default(false)) { 362056396aeSDouglas Gregor if (Name.data() != Buffer.data()) 363056396aeSDouglas Gregor Buffer.append(Name.begin(), Name.end()); 364056396aeSDouglas Gregor Buffer.push_back('_'); 365056396aeSDouglas Gregor Name = StringRef(Buffer.data(), Buffer.size()); 366056396aeSDouglas Gregor } 367056396aeSDouglas Gregor 368056396aeSDouglas Gregor return Name; 369056396aeSDouglas Gregor } 370056396aeSDouglas Gregor 3719fc8faf9SAdrian Prantl /// Determine whether the given file name is the name of a builtin 37234d52749SDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system 37334d52749SDouglas Gregor /// headers. 374ba1b5c98SBruno Cardoso Lopes bool ModuleMap::isBuiltinHeader(StringRef FileName) { 37534d52749SDouglas Gregor return llvm::StringSwitch<bool>(FileName) 37634d52749SDouglas Gregor .Case("float.h", true) 37734d52749SDouglas Gregor .Case("iso646.h", true) 37834d52749SDouglas Gregor .Case("limits.h", true) 37934d52749SDouglas Gregor .Case("stdalign.h", true) 38034d52749SDouglas Gregor .Case("stdarg.h", true) 3813c4b1290SBen Langmuir .Case("stdatomic.h", true) 38234d52749SDouglas Gregor .Case("stdbool.h", true) 38334d52749SDouglas Gregor .Case("stddef.h", true) 38434d52749SDouglas Gregor .Case("stdint.h", true) 38534d52749SDouglas Gregor .Case("tgmath.h", true) 38634d52749SDouglas Gregor .Case("unwind.h", true) 38734d52749SDouglas Gregor .Default(false); 38834d52749SDouglas Gregor } 38934d52749SDouglas Gregor 3908d74de9dSMartin Boehme bool ModuleMap::isBuiltinHeader(const FileEntry *File) { 3918d74de9dSMartin Boehme return File->getDir() == BuiltinIncludeDir && 3928d74de9dSMartin Boehme ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName())); 3938d74de9dSMartin Boehme } 3948d74de9dSMartin Boehme 39592669ee4SDaniel Jasper ModuleMap::HeadersMap::iterator 39692669ee4SDaniel Jasper ModuleMap::findKnownHeader(const FileEntry *File) { 397040e1266SRichard Smith resolveHeaderDirectives(File); 39859527666SDouglas Gregor HeadersMap::iterator Known = Headers.find(File); 39947972afdSRichard Smith if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && 4008d74de9dSMartin Boehme Known == Headers.end() && ModuleMap::isBuiltinHeader(File)) { 4014eaf0a6cSDaniel Jasper HeaderInfo.loadTopLevelSystemModules(); 40292669ee4SDaniel Jasper return Headers.find(File); 4034eaf0a6cSDaniel Jasper } 40492669ee4SDaniel Jasper return Known; 40592669ee4SDaniel Jasper } 40692669ee4SDaniel Jasper 4074469138eSBen Langmuir ModuleMap::KnownHeader 4084469138eSBen Langmuir ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File, 4094469138eSBen Langmuir SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) { 41047972afdSRichard Smith if (UmbrellaDirs.empty()) 411afd1b1c9SEugene Zelenko return {}; 41247972afdSRichard Smith 4134469138eSBen Langmuir const DirectoryEntry *Dir = File->getDir(); 4144469138eSBen Langmuir assert(Dir && "file in no directory"); 4154469138eSBen Langmuir 4164469138eSBen Langmuir // Note: as an egregious but useful hack we use the real path here, because 4174469138eSBen Langmuir // frameworks moving from top-level frameworks to embedded frameworks tend 4184469138eSBen Langmuir // to be symlinked from the top-level location to the embedded location, 4194469138eSBen Langmuir // and we need to resolve lookups as if we had found the embedded location. 4204469138eSBen Langmuir StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir); 4214469138eSBen Langmuir 4224469138eSBen Langmuir // Keep walking up the directory hierarchy, looking for a directory with 4234469138eSBen Langmuir // an umbrella header. 4244469138eSBen Langmuir do { 4254469138eSBen Langmuir auto KnownDir = UmbrellaDirs.find(Dir); 4264469138eSBen Langmuir if (KnownDir != UmbrellaDirs.end()) 4274469138eSBen Langmuir return KnownHeader(KnownDir->second, NormalHeader); 4284469138eSBen Langmuir 4294469138eSBen Langmuir IntermediateDirs.push_back(Dir); 4304469138eSBen Langmuir 4314469138eSBen Langmuir // Retrieve our parent path. 4324469138eSBen Langmuir DirName = llvm::sys::path::parent_path(DirName); 4334469138eSBen Langmuir if (DirName.empty()) 4344469138eSBen Langmuir break; 4354469138eSBen Langmuir 4364469138eSBen Langmuir // Resolve the parent path to a directory entry. 4378d323d15SHarlan Haskins if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName)) 4388d323d15SHarlan Haskins Dir = *DirEntry; 4398d323d15SHarlan Haskins else 4408d323d15SHarlan Haskins Dir = nullptr; 4414469138eSBen Langmuir } while (Dir); 442afd1b1c9SEugene Zelenko return {}; 4434469138eSBen Langmuir } 4444469138eSBen Langmuir 44592669ee4SDaniel Jasper static bool violatesPrivateInclude(Module *RequestingModule, 44692669ee4SDaniel Jasper const FileEntry *IncFileEnt, 4474eb8393cSRichard Smith ModuleMap::KnownHeader Header) { 44892669ee4SDaniel Jasper #ifndef NDEBUG 4494eb8393cSRichard Smith if (Header.getRole() & ModuleMap::PrivateHeader) { 45092669ee4SDaniel Jasper // Check for consistency between the module header role 45192669ee4SDaniel Jasper // as obtained from the lookup and as obtained from the module. 45292669ee4SDaniel Jasper // This check is not cheap, so enable it only for debugging. 4532708e520SRichard Smith bool IsPrivate = false; 4542708e520SRichard Smith SmallVectorImpl<Module::Header> *HeaderList[] = { 4554eb8393cSRichard Smith &Header.getModule()->Headers[Module::HK_Private], 4564eb8393cSRichard Smith &Header.getModule()->Headers[Module::HK_PrivateTextual]}; 4572708e520SRichard Smith for (auto *Hs : HeaderList) 4582708e520SRichard Smith IsPrivate |= 4592708e520SRichard Smith std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) { 4603c1a41adSRichard Smith return H.Entry == IncFileEnt; 4612708e520SRichard Smith }) != Hs->end(); 4624eb8393cSRichard Smith assert(IsPrivate && "inconsistent headers and roles"); 46300bc95ecSRichard Smith } 46492669ee4SDaniel Jasper #endif 4654eb8393cSRichard Smith return !Header.isAccessibleFrom(RequestingModule); 46692669ee4SDaniel Jasper } 46792669ee4SDaniel Jasper 46871e1a64fSBen Langmuir static Module *getTopLevelOrNull(Module *M) { 46971e1a64fSBen Langmuir return M ? M->getTopLevelModule() : nullptr; 47071e1a64fSBen Langmuir } 47171e1a64fSBen Langmuir 47292669ee4SDaniel Jasper void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, 4738d4e90b3SRichard Smith bool RequestingModuleIsModuleInterface, 47492669ee4SDaniel Jasper SourceLocation FilenameLoc, 47592669ee4SDaniel Jasper StringRef Filename, 47692669ee4SDaniel Jasper const FileEntry *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); 484040e1266SRichard Smith resolveHeaderDirectives(RequestingModule); 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() 54470a7738fSManman Ren << 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 6207033127bSDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 621a89c5ac4SDouglas Gregor // Find or create the module that corresponds to this directory name. 622056396aeSDouglas Gregor SmallString<32> NameBuf; 623056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 6244469138eSBen Langmuir llvm::sys::path::stem(SkippedDirs[I-1]->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. 631a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I-1]] = 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) { 7471fb5c3a6SDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 7481fb5c3a6SDouglas Gregor // Find or create the module that corresponds to this directory name. 749056396aeSDouglas Gregor SmallString<32> NameBuf; 750056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 751056396aeSDouglas Gregor llvm::sys::path::stem(SkippedDirs[I-1]->getName()), 752056396aeSDouglas Gregor NameBuf); 7531fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 7541fb5c3a6SDouglas Gregor if (!Found) 7551fb5c3a6SDouglas Gregor return false; 75650996ce1SRichard Smith if (IsUnavailable(Found)) 7571fb5c3a6SDouglas Gregor return true; 7581fb5c3a6SDouglas Gregor } 7591fb5c3a6SDouglas Gregor 7601fb5c3a6SDouglas Gregor // Infer a submodule with the same name as this header file. 761056396aeSDouglas Gregor SmallString<32> NameBuf; 762056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 763056396aeSDouglas Gregor llvm::sys::path::stem(Header->getName()), 764056396aeSDouglas Gregor NameBuf); 7651fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 7661fb5c3a6SDouglas Gregor if (!Found) 7671fb5c3a6SDouglas Gregor return false; 7681fb5c3a6SDouglas Gregor } 7691fb5c3a6SDouglas Gregor 77050996ce1SRichard Smith return IsUnavailable(Found); 7711fb5c3a6SDouglas Gregor } 7721fb5c3a6SDouglas Gregor 7731fb5c3a6SDouglas Gregor SkippedDirs.push_back(Dir); 7741fb5c3a6SDouglas Gregor 7751fb5c3a6SDouglas Gregor // Retrieve our parent path. 7761fb5c3a6SDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 7771fb5c3a6SDouglas Gregor if (DirName.empty()) 7781fb5c3a6SDouglas Gregor break; 7791fb5c3a6SDouglas Gregor 7801fb5c3a6SDouglas Gregor // Resolve the parent path to a directory entry. 7818d323d15SHarlan Haskins if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName)) 7828d323d15SHarlan Haskins Dir = *DirEntry; 7838d323d15SHarlan Haskins else 7848d323d15SHarlan Haskins Dir = nullptr; 7851fb5c3a6SDouglas Gregor } while (Dir); 7861fb5c3a6SDouglas Gregor 7871fb5c3a6SDouglas Gregor return false; 7881fb5c3a6SDouglas Gregor } 7891fb5c3a6SDouglas Gregor 790e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const { 791e4412640SArgyrios Kyrtzidis llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name); 79288bdfb0eSDouglas Gregor if (Known != Modules.end()) 79388bdfb0eSDouglas Gregor return Known->getValue(); 79488bdfb0eSDouglas Gregor 795d2d442caSCraig Topper return nullptr; 79688bdfb0eSDouglas Gregor } 79788bdfb0eSDouglas Gregor 798e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name, 799e4412640SArgyrios Kyrtzidis Module *Context) const { 8002b82c2a5SDouglas Gregor for(; Context; Context = Context->Parent) { 8012b82c2a5SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Context)) 8022b82c2a5SDouglas Gregor return Sub; 8032b82c2a5SDouglas Gregor } 8042b82c2a5SDouglas Gregor 8052b82c2a5SDouglas Gregor return findModule(Name); 8062b82c2a5SDouglas Gregor } 8072b82c2a5SDouglas Gregor 808e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{ 8092b82c2a5SDouglas Gregor if (!Context) 8102b82c2a5SDouglas Gregor return findModule(Name); 8112b82c2a5SDouglas Gregor 812eb90e830SDouglas Gregor return Context->findSubmodule(Name); 8132b82c2a5SDouglas Gregor } 8142b82c2a5SDouglas Gregor 815c192d194SBruno Cardoso Lopes std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name, 816c192d194SBruno Cardoso Lopes Module *Parent, 817c192d194SBruno Cardoso Lopes bool IsFramework, 818c192d194SBruno Cardoso Lopes bool IsExplicit) { 81969021974SDouglas Gregor // Try to find an existing module with this name. 820eb90e830SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Parent)) 821eb90e830SDouglas Gregor return std::make_pair(Sub, false); 82269021974SDouglas Gregor 82369021974SDouglas Gregor // Create a new module with this name. 8249ffe5a35SDavid Blaikie Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, 8259ffe5a35SDavid Blaikie IsExplicit, NumCreatedModules++); 8266f722b4eSArgyrios Kyrtzidis if (!Parent) { 8277e82e019SRichard Smith if (LangOpts.CurrentModule == Name) 8287e82e019SRichard Smith SourceModule = Result; 82969021974SDouglas Gregor Modules[Name] = Result; 830c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID; 8316f722b4eSArgyrios Kyrtzidis } 83269021974SDouglas Gregor return std::make_pair(Result, true); 83369021974SDouglas Gregor } 83469021974SDouglas Gregor 835a5bbbfefSRichard Smith Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc) { 836d6509cf2SRichard Smith PendingSubmodules.emplace_back( 837056bf77fSRichard Smith new Module("<global>", Loc, nullptr, /*IsFramework*/ false, 838056bf77fSRichard Smith /*IsExplicit*/ true, NumCreatedModules++)); 839d6509cf2SRichard Smith PendingSubmodules.back()->Kind = Module::GlobalModuleFragment; 840d6509cf2SRichard Smith return PendingSubmodules.back().get(); 841dd8b5337SRichard Smith } 842dd8b5337SRichard Smith 843a5bbbfefSRichard Smith Module * 844a5bbbfefSRichard Smith ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent, 845a5bbbfefSRichard Smith SourceLocation Loc) { 846a5bbbfefSRichard Smith auto *Result = 847a5bbbfefSRichard Smith new Module("<private>", Loc, Parent, /*IsFramework*/ false, 848a5bbbfefSRichard Smith /*IsExplicit*/ true, NumCreatedModules++); 849a5bbbfefSRichard Smith Result->Kind = Module::PrivateModuleFragment; 850a5bbbfefSRichard Smith return Result; 851a5bbbfefSRichard Smith } 852a5bbbfefSRichard Smith 853bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc, 854dd8b5337SRichard Smith StringRef Name, 855dd8b5337SRichard Smith Module *GlobalModule) { 856bbcc9f04SRichard Smith assert(LangOpts.CurrentModule == Name && "module name mismatch"); 857bbcc9f04SRichard Smith assert(!Modules[Name] && "redefining existing module"); 858bbcc9f04SRichard Smith 859bbcc9f04SRichard Smith auto *Result = 860bbcc9f04SRichard Smith new Module(Name, Loc, nullptr, /*IsFramework*/ false, 861bbcc9f04SRichard Smith /*IsExplicit*/ false, NumCreatedModules++); 862145e15a3SRichard Smith Result->Kind = Module::ModuleInterfaceUnit; 863bbcc9f04SRichard Smith Modules[Name] = SourceModule = Result; 864bbcc9f04SRichard Smith 865dd8b5337SRichard Smith // Reparent the current global module fragment as a submodule of this module. 866d6509cf2SRichard Smith for (auto &Submodule : PendingSubmodules) { 867d6509cf2SRichard Smith Submodule->setParent(Result); 868d6509cf2SRichard Smith Submodule.release(); // now owned by parent 869d6509cf2SRichard Smith } 870d6509cf2SRichard Smith PendingSubmodules.clear(); 871dd8b5337SRichard Smith 872bbcc9f04SRichard Smith // Mark the main source file as being within the newly-created module so that 873bbcc9f04SRichard Smith // declarations and macros are properly visibility-restricted to it. 874bbcc9f04SRichard Smith auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()); 875bbcc9f04SRichard Smith assert(MainFile && "no input file for module interface"); 876bbcc9f04SRichard Smith Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader)); 877bbcc9f04SRichard Smith 878bbcc9f04SRichard Smith return Result; 879bbcc9f04SRichard Smith } 880bbcc9f04SRichard Smith 881d6509cf2SRichard Smith Module *ModuleMap::createHeaderModule(StringRef Name, 882d6509cf2SRichard Smith ArrayRef<Module::Header> Headers) { 883d6509cf2SRichard Smith assert(LangOpts.CurrentModule == Name && "module name mismatch"); 884d6509cf2SRichard Smith assert(!Modules[Name] && "redefining existing module"); 885d6509cf2SRichard Smith 886d6509cf2SRichard Smith auto *Result = 887d6509cf2SRichard Smith new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false, 888d6509cf2SRichard Smith /*IsExplicit*/ false, NumCreatedModules++); 889d6509cf2SRichard Smith Result->Kind = Module::ModuleInterfaceUnit; 890d6509cf2SRichard Smith Modules[Name] = SourceModule = Result; 891d6509cf2SRichard Smith 892d6509cf2SRichard Smith for (const Module::Header &H : Headers) { 893d6509cf2SRichard Smith auto *M = new Module(H.NameAsWritten, SourceLocation(), Result, 894d6509cf2SRichard Smith /*IsFramework*/ false, 895d6509cf2SRichard Smith /*IsExplicit*/ true, NumCreatedModules++); 896d6509cf2SRichard Smith // Header modules are implicitly 'export *'. 897d6509cf2SRichard Smith M->Exports.push_back(Module::ExportDecl(nullptr, true)); 898d6509cf2SRichard Smith addHeader(M, H, NormalHeader); 899d6509cf2SRichard Smith } 900d6509cf2SRichard Smith 901d6509cf2SRichard Smith return Result; 902d6509cf2SRichard Smith } 903d6509cf2SRichard Smith 9049fc8faf9SAdrian Prantl /// For a framework module, infer the framework against which we 90511dfe6feSDouglas Gregor /// should link. 90611dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir, 90711dfe6feSDouglas Gregor FileManager &FileMgr) { 90811dfe6feSDouglas Gregor assert(Mod->IsFramework && "Can only infer linking for framework modules"); 90911dfe6feSDouglas Gregor assert(!Mod->isSubFramework() && 91011dfe6feSDouglas Gregor "Can only infer linking for top-level frameworks"); 91111dfe6feSDouglas Gregor 91211dfe6feSDouglas Gregor SmallString<128> LibName; 91311dfe6feSDouglas Gregor LibName += FrameworkDir->getName(); 91411dfe6feSDouglas Gregor llvm::sys::path::append(LibName, Mod->Name); 9158aaae5a9SJuergen Ributzka 9168aaae5a9SJuergen Ributzka // The library name of a framework has more than one possible extension since 9178aaae5a9SJuergen Ributzka // the introduction of the text-based dynamic library format. We need to check 9188aaae5a9SJuergen Ributzka // for both before we give up. 9198013e81dSBenjamin Kramer for (const char *extension : {"", ".tbd"}) { 9208aaae5a9SJuergen Ributzka llvm::sys::path::replace_extension(LibName, extension); 92111dfe6feSDouglas Gregor if (FileMgr.getFile(LibName)) { 92211dfe6feSDouglas Gregor Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name, 92311dfe6feSDouglas Gregor /*IsFramework=*/true)); 9248aaae5a9SJuergen Ributzka return; 9258aaae5a9SJuergen Ributzka } 92611dfe6feSDouglas Gregor } 92711dfe6feSDouglas Gregor } 92811dfe6feSDouglas Gregor 929a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 930a525400dSBen Langmuir bool IsSystem, Module *Parent) { 931c1d88ea5SBen Langmuir Attributes Attrs; 932c1d88ea5SBen Langmuir Attrs.IsSystem = IsSystem; 933a525400dSBen Langmuir return inferFrameworkModule(FrameworkDir, Attrs, Parent); 934c1d88ea5SBen Langmuir } 935c1d88ea5SBen Langmuir 936a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 937c1d88ea5SBen Langmuir Attributes Attrs, Module *Parent) { 938a525400dSBen Langmuir // Note: as an egregious but useful hack we use the real path here, because 939a525400dSBen Langmuir // we might be looking at an embedded framework that symlinks out to a 940a525400dSBen Langmuir // top-level framework, and we need to infer as if we were naming the 941a525400dSBen Langmuir // top-level framework. 942a525400dSBen Langmuir StringRef FrameworkDirName = 943a525400dSBen Langmuir SourceMgr.getFileManager().getCanonicalName(FrameworkDir); 944a525400dSBen Langmuir 945a525400dSBen Langmuir // In case this is a case-insensitive filesystem, use the canonical 946a525400dSBen Langmuir // directory name as the ModuleName, since modules are case-sensitive. 947a525400dSBen Langmuir // FIXME: we should be able to give a fix-it hint for the correct spelling. 948a525400dSBen Langmuir SmallString<32> ModuleNameStorage; 949a525400dSBen Langmuir StringRef ModuleName = sanitizeFilenameAsIdentifier( 950a525400dSBen Langmuir llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage); 951c1d88ea5SBen Langmuir 95256c64013SDouglas Gregor // Check whether we've already found this module. 953e89dbc1dSDouglas Gregor if (Module *Mod = lookupModuleQualified(ModuleName, Parent)) 954e89dbc1dSDouglas Gregor return Mod; 955e89dbc1dSDouglas Gregor 9561f76c4e8SManuel Klimek FileManager &FileMgr = SourceMgr.getFileManager(); 95756c64013SDouglas Gregor 9589194a91dSDouglas Gregor // If the framework has a parent path from which we're allowed to infer 9599194a91dSDouglas Gregor // a framework module, do so. 960beee15e7SBen Langmuir const FileEntry *ModuleMapFile = nullptr; 9619194a91dSDouglas Gregor if (!Parent) { 9624ddf2221SDouglas Gregor // Determine whether we're allowed to infer a module map. 9639194a91dSDouglas Gregor bool canInfer = false; 9644ddf2221SDouglas Gregor if (llvm::sys::path::has_parent_path(FrameworkDirName)) { 9659194a91dSDouglas Gregor // Figure out the parent path. 9664ddf2221SDouglas Gregor StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName); 9678d323d15SHarlan Haskins if (auto ParentDir = FileMgr.getDirectory(Parent)) { 9689194a91dSDouglas Gregor // Check whether we have already looked into the parent directory 9699194a91dSDouglas Gregor // for a module map. 970e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator 9718d323d15SHarlan Haskins inferred = InferredDirectories.find(*ParentDir); 9729194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) { 9739194a91dSDouglas Gregor // We haven't looked here before. Load a module map, if there is 9749194a91dSDouglas Gregor // one. 975984e1df7SBen Langmuir bool IsFrameworkDir = Parent.endswith(".framework"); 976984e1df7SBen Langmuir if (const FileEntry *ModMapFile = 9778d323d15SHarlan Haskins HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) { 9788d323d15SHarlan Haskins parseModuleMapFile(ModMapFile, Attrs.IsSystem, *ParentDir); 9798d323d15SHarlan Haskins inferred = InferredDirectories.find(*ParentDir); 9809194a91dSDouglas Gregor } 9819194a91dSDouglas Gregor 9829194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) 9839194a91dSDouglas Gregor inferred = InferredDirectories.insert( 9848d323d15SHarlan Haskins std::make_pair(*ParentDir, InferredDirectory())).first; 9859194a91dSDouglas Gregor } 9869194a91dSDouglas Gregor 9879194a91dSDouglas Gregor if (inferred->second.InferModules) { 9889194a91dSDouglas Gregor // We're allowed to infer for this directory, but make sure it's okay 9899194a91dSDouglas Gregor // to infer this particular module. 9904ddf2221SDouglas Gregor StringRef Name = llvm::sys::path::stem(FrameworkDirName); 9919194a91dSDouglas Gregor canInfer = std::find(inferred->second.ExcludedModules.begin(), 9929194a91dSDouglas Gregor inferred->second.ExcludedModules.end(), 9939194a91dSDouglas Gregor Name) == inferred->second.ExcludedModules.end(); 9949194a91dSDouglas Gregor 995c1d88ea5SBen Langmuir Attrs.IsSystem |= inferred->second.Attrs.IsSystem; 996c1d88ea5SBen Langmuir Attrs.IsExternC |= inferred->second.Attrs.IsExternC; 997c1d88ea5SBen Langmuir Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive; 998ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes |= 999ed84df00SBruno Cardoso Lopes inferred->second.Attrs.NoUndeclaredIncludes; 1000beee15e7SBen Langmuir ModuleMapFile = inferred->second.ModuleMapFile; 10019194a91dSDouglas Gregor } 10029194a91dSDouglas Gregor } 10039194a91dSDouglas Gregor } 10049194a91dSDouglas Gregor 10059194a91dSDouglas Gregor // If we're not allowed to infer a framework module, don't. 10069194a91dSDouglas Gregor if (!canInfer) 1007d2d442caSCraig Topper return nullptr; 1008beee15e7SBen Langmuir } else 10099d6448b1SBen Langmuir ModuleMapFile = getModuleMapFileForUniquing(Parent); 10109194a91dSDouglas Gregor 10119194a91dSDouglas Gregor 101256c64013SDouglas Gregor // Look for an umbrella header. 10132c1dd271SDylan Noblesmith SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 101417381a06SBenjamin Kramer llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h"); 10158d323d15SHarlan Haskins auto UmbrellaHeader = FileMgr.getFile(UmbrellaName); 101656c64013SDouglas Gregor 101756c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the 101856c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good 101956c64013SDouglas Gregor // idea. 102056c64013SDouglas Gregor if (!UmbrellaHeader) 1021d2d442caSCraig Topper return nullptr; 102256c64013SDouglas Gregor 10239d6448b1SBen Langmuir Module *Result = new Module(ModuleName, SourceLocation(), Parent, 1024a7e2cc68SRichard Smith /*IsFramework=*/true, /*IsExplicit=*/false, 1025a7e2cc68SRichard Smith NumCreatedModules++); 10269d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = ModuleMapFile; 10279d6448b1SBen Langmuir Result->IsInferred = true; 10287e82e019SRichard Smith if (!Parent) { 10297e82e019SRichard Smith if (LangOpts.CurrentModule == ModuleName) 1030ba7f2f71SDaniel Jasper SourceModule = Result; 10317e82e019SRichard Smith Modules[ModuleName] = Result; 1032c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID; 1033ba7f2f71SDaniel Jasper } 1034c1d88ea5SBen Langmuir 1035c1d88ea5SBen Langmuir Result->IsSystem |= Attrs.IsSystem; 1036c1d88ea5SBen Langmuir Result->IsExternC |= Attrs.IsExternC; 1037c1d88ea5SBen Langmuir Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive; 1038ed84df00SBruno Cardoso Lopes Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes; 10392b63d15fSRichard Smith Result->Directory = FrameworkDir; 1040a686e1b0SDouglas Gregor 1041322f633cSDouglas Gregor // umbrella header "umbrella-header-name" 10422b63d15fSRichard Smith // 10432b63d15fSRichard Smith // The "Headers/" component of the name is implied because this is 10442b63d15fSRichard Smith // a framework module. 10458d323d15SHarlan Haskins setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h"); 1046d8bd7537SDouglas Gregor 1047d8bd7537SDouglas Gregor // export * 1048d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 1049d8bd7537SDouglas Gregor 1050a89c5ac4SDouglas Gregor // module * { export * } 1051a89c5ac4SDouglas Gregor Result->InferSubmodules = true; 1052a89c5ac4SDouglas Gregor Result->InferExportWildcard = true; 1053a89c5ac4SDouglas Gregor 1054e89dbc1dSDouglas Gregor // Look for subframeworks. 1055c080917eSRafael Espindola std::error_code EC; 10562c1dd271SDylan Noblesmith SmallString<128> SubframeworksDirName 1057ddaa69cbSDouglas Gregor = StringRef(FrameworkDir->getName()); 1058e89dbc1dSDouglas Gregor llvm::sys::path::append(SubframeworksDirName, "Frameworks"); 10592d4d8cb3SBenjamin Kramer llvm::sys::path::native(SubframeworksDirName); 1060db8a7422SDuncan P. N. Exon Smith llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); 1061fc51490bSJonas Devlieghere for (llvm::vfs::directory_iterator 1062fc51490bSJonas Devlieghere Dir = FS.dir_begin(SubframeworksDirName, EC), 1063b171a59bSBruno Cardoso Lopes DirEnd; 1064e89dbc1dSDouglas Gregor Dir != DirEnd && !EC; Dir.increment(EC)) { 10650ae00567SSam McCall if (!StringRef(Dir->path()).endswith(".framework")) 1066e89dbc1dSDouglas Gregor continue; 1067f2161a70SDouglas Gregor 10688d323d15SHarlan Haskins if (auto SubframeworkDir = 10690ae00567SSam McCall FileMgr.getDirectory(Dir->path())) { 107007c22b78SDouglas Gregor // Note: as an egregious but useful hack, we use the real path here and 107107c22b78SDouglas Gregor // check whether it is actually a subdirectory of the parent directory. 107207c22b78SDouglas Gregor // This will not be the case if the 'subframework' is actually a symlink 107307c22b78SDouglas Gregor // out to a top-level framework. 10748d323d15SHarlan Haskins StringRef SubframeworkDirName = 10758d323d15SHarlan Haskins FileMgr.getCanonicalName(*SubframeworkDir); 107607c22b78SDouglas Gregor bool FoundParent = false; 107707c22b78SDouglas Gregor do { 107807c22b78SDouglas Gregor // Get the parent directory name. 107907c22b78SDouglas Gregor SubframeworkDirName 108007c22b78SDouglas Gregor = llvm::sys::path::parent_path(SubframeworkDirName); 108107c22b78SDouglas Gregor if (SubframeworkDirName.empty()) 108207c22b78SDouglas Gregor break; 108307c22b78SDouglas Gregor 10848d323d15SHarlan Haskins if (auto SubDir = FileMgr.getDirectory(SubframeworkDirName)) { 10858d323d15SHarlan Haskins if (*SubDir == FrameworkDir) { 108607c22b78SDouglas Gregor FoundParent = true; 108707c22b78SDouglas Gregor break; 108807c22b78SDouglas Gregor } 10898d323d15SHarlan Haskins } 109007c22b78SDouglas Gregor } while (true); 109107c22b78SDouglas Gregor 109207c22b78SDouglas Gregor if (!FoundParent) 109307c22b78SDouglas Gregor continue; 109407c22b78SDouglas Gregor 1095e89dbc1dSDouglas Gregor // FIXME: Do we want to warn about subframeworks without umbrella headers? 10968d323d15SHarlan Haskins inferFrameworkModule(*SubframeworkDir, Attrs, Result); 1097e89dbc1dSDouglas Gregor } 1098e89dbc1dSDouglas Gregor } 1099e89dbc1dSDouglas Gregor 110011dfe6feSDouglas Gregor // If the module is a top-level framework, automatically link against the 110111dfe6feSDouglas Gregor // framework. 110211dfe6feSDouglas Gregor if (!Result->isSubFramework()) { 110311dfe6feSDouglas Gregor inferFrameworkLink(Result, FrameworkDir, FileMgr); 110411dfe6feSDouglas Gregor } 110511dfe6feSDouglas Gregor 110656c64013SDouglas Gregor return Result; 110756c64013SDouglas Gregor } 110856c64013SDouglas Gregor 11098587dfd9SBruno Cardoso Lopes Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework, 11108587dfd9SBruno Cardoso Lopes Module *ShadowingModule) { 11118587dfd9SBruno Cardoso Lopes 11128587dfd9SBruno Cardoso Lopes // Create a new module with this name. 11138587dfd9SBruno Cardoso Lopes Module *Result = 11148587dfd9SBruno Cardoso Lopes new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework, 11158587dfd9SBruno Cardoso Lopes /*IsExplicit=*/false, NumCreatedModules++); 11168587dfd9SBruno Cardoso Lopes Result->ShadowingModule = ShadowingModule; 1117fc76b4adSRichard Smith Result->markUnavailable(/*Unimportable*/true); 1118c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID; 11198587dfd9SBruno Cardoso Lopes ShadowModules.push_back(Result); 11208587dfd9SBruno Cardoso Lopes 11218587dfd9SBruno Cardoso Lopes return Result; 11228587dfd9SBruno Cardoso Lopes } 11238587dfd9SBruno Cardoso Lopes 11242b63d15fSRichard Smith void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader, 11252b63d15fSRichard Smith Twine NameAsWritten) { 112697da9178SDaniel Jasper Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader)); 112773141fa9SDouglas Gregor Mod->Umbrella = UmbrellaHeader; 11282b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 11297033127bSDouglas Gregor UmbrellaDirs[UmbrellaHeader->getDir()] = Mod; 1130b3a0fa48SBruno Cardoso Lopes 1131b3a0fa48SBruno Cardoso Lopes // Notify callbacks that we just added a new header. 1132b3a0fa48SBruno Cardoso Lopes for (const auto &Cb : Callbacks) 1133b3a0fa48SBruno Cardoso Lopes Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader); 1134a89c5ac4SDouglas Gregor } 1135a89c5ac4SDouglas Gregor 11362b63d15fSRichard Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, 11372b63d15fSRichard Smith Twine NameAsWritten) { 1138524e33e1SDouglas Gregor Mod->Umbrella = UmbrellaDir; 11392b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 1140524e33e1SDouglas Gregor UmbrellaDirs[UmbrellaDir] = Mod; 1141524e33e1SDouglas Gregor } 1142524e33e1SDouglas Gregor 1143040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod, 11449f6020bcSBruno Cardoso Lopes Module::UnresolvedHeaderDirective Header, 11459f6020bcSBruno Cardoso Lopes bool &NeedsFramework) { 1146040e1266SRichard Smith // If there is a builtin counterpart to this file, add it now so it can 1147040e1266SRichard Smith // wrap the system header. 1148040e1266SRichard Smith if (resolveAsBuiltinHeader(Mod, Header)) { 1149040e1266SRichard Smith // If we have both a builtin and system version of the file, the 1150040e1266SRichard Smith // builtin version may want to inject macros into the system header, so 1151040e1266SRichard Smith // force the system header to be treated as a textual header in this 1152040e1266SRichard Smith // case. 1153040e1266SRichard Smith Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole( 1154040e1266SRichard Smith headerKindToRole(Header.Kind) | ModuleMap::TextualHeader)); 1155040e1266SRichard Smith Header.HasBuiltinHeader = true; 11563c1a41adSRichard Smith } 1157040e1266SRichard Smith 1158040e1266SRichard Smith // If possible, don't stat the header until we need to. This requires the 1159040e1266SRichard Smith // user to have provided us with some stat information about the file. 1160040e1266SRichard Smith // FIXME: Add support for lazily stat'ing umbrella headers and excluded 1161040e1266SRichard Smith // headers. 1162040e1266SRichard Smith if ((Header.Size || Header.ModTime) && !Header.IsUmbrella && 1163040e1266SRichard Smith Header.Kind != Module::HK_Excluded) { 1164040e1266SRichard Smith // We expect more variation in mtime than size, so if we're given both, 1165040e1266SRichard Smith // use the mtime as the key. 1166040e1266SRichard Smith if (Header.ModTime) 1167040e1266SRichard Smith LazyHeadersByModTime[*Header.ModTime].push_back(Mod); 1168040e1266SRichard Smith else 1169040e1266SRichard Smith LazyHeadersBySize[*Header.Size].push_back(Mod); 1170040e1266SRichard Smith Mod->UnresolvedHeaders.push_back(Header); 1171040e1266SRichard Smith return; 1172040e1266SRichard Smith } 1173040e1266SRichard Smith 1174040e1266SRichard Smith // We don't have stat information or can't defer looking this file up. 1175040e1266SRichard Smith // Perform the lookup now. 11769f6020bcSBruno Cardoso Lopes resolveHeader(Mod, Header, NeedsFramework); 1177040e1266SRichard Smith } 1178040e1266SRichard Smith 1179040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const { 1180040e1266SRichard Smith auto BySize = LazyHeadersBySize.find(File->getSize()); 1181040e1266SRichard Smith if (BySize != LazyHeadersBySize.end()) { 1182040e1266SRichard Smith for (auto *M : BySize->second) 1183040e1266SRichard Smith resolveHeaderDirectives(M); 1184040e1266SRichard Smith LazyHeadersBySize.erase(BySize); 1185040e1266SRichard Smith } 1186040e1266SRichard Smith 1187040e1266SRichard Smith auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime()); 1188040e1266SRichard Smith if (ByModTime != LazyHeadersByModTime.end()) { 1189040e1266SRichard Smith for (auto *M : ByModTime->second) 1190040e1266SRichard Smith resolveHeaderDirectives(M); 1191040e1266SRichard Smith LazyHeadersByModTime.erase(ByModTime); 1192040e1266SRichard Smith } 1193040e1266SRichard Smith } 1194040e1266SRichard Smith 1195040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(Module *Mod) const { 11969f6020bcSBruno Cardoso Lopes bool NeedsFramework = false; 1197040e1266SRichard Smith for (auto &Header : Mod->UnresolvedHeaders) 1198040e1266SRichard Smith // This operation is logically const; we're just changing how we represent 1199040e1266SRichard Smith // the header information for this file. 12009f6020bcSBruno Cardoso Lopes const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework); 1201040e1266SRichard Smith Mod->UnresolvedHeaders.clear(); 12020e98d938SNAKAMURA Takumi } 1203202210b3SRichard Smith 12043c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header, 1205d8879c85SRichard Smith ModuleHeaderRole Role, bool Imported) { 1206386bb073SRichard Smith KnownHeader KH(Mod, Role); 12073c1a41adSRichard Smith 1208386bb073SRichard Smith // Only add each header to the headers list once. 1209386bb073SRichard Smith // FIXME: Should we diagnose if a header is listed twice in the 1210386bb073SRichard Smith // same module definition? 1211386bb073SRichard Smith auto &HeaderList = Headers[Header.Entry]; 1212386bb073SRichard Smith for (auto H : HeaderList) 1213386bb073SRichard Smith if (H == KH) 1214386bb073SRichard Smith return; 1215386bb073SRichard Smith 1216386bb073SRichard Smith HeaderList.push_back(KH); 12171ec383c7SPiotr Padlewski Mod->Headers[headerRoleToKind(Role)].push_back(Header); 1218386bb073SRichard Smith 12197e82e019SRichard Smith bool isCompilingModuleHeader = 1220bbcc9f04SRichard Smith LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule; 1221d8879c85SRichard Smith if (!Imported || isCompilingModuleHeader) { 1222d8879c85SRichard Smith // When we import HeaderFileInfo, the external source is expected to 1223d8879c85SRichard Smith // set the isModuleHeader flag itself. 1224d8879c85SRichard Smith HeaderInfo.MarkFileModuleHeader(Header.Entry, Role, 1225d8879c85SRichard Smith isCompilingModuleHeader); 1226d8879c85SRichard Smith } 1227e62cfd7cSBruno Cardoso Lopes 1228e62cfd7cSBruno Cardoso Lopes // Notify callbacks that we just added a new header. 1229e62cfd7cSBruno Cardoso Lopes for (const auto &Cb : Callbacks) 1230f0841790SBruno Cardoso Lopes Cb->moduleMapAddHeader(Header.Entry->getName()); 1231a89c5ac4SDouglas Gregor } 1232a89c5ac4SDouglas Gregor 12333c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) { 1234feb54b6dSRichard Smith // Add this as a known header so we won't implicitly add it to any 1235feb54b6dSRichard Smith // umbrella directory module. 1236feb54b6dSRichard Smith // FIXME: Should we only exclude it from umbrella modules within the 1237feb54b6dSRichard Smith // specified module? 12383c1a41adSRichard Smith (void) Headers[Header.Entry]; 12393c1a41adSRichard Smith 12403c1a41adSRichard Smith Mod->Headers[Module::HK_Excluded].push_back(std::move(Header)); 1241feb54b6dSRichard Smith } 1242feb54b6dSRichard Smith 1243514b636aSDouglas Gregor const FileEntry * 12444b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const { 12451f76c4e8SManuel Klimek if (Module->DefinitionLoc.isInvalid()) 1246d2d442caSCraig Topper return nullptr; 1247514b636aSDouglas Gregor 12481f76c4e8SManuel Klimek return SourceMgr.getFileEntryForID( 12491f76c4e8SManuel Klimek SourceMgr.getFileID(Module->DefinitionLoc)); 1250514b636aSDouglas Gregor } 1251514b636aSDouglas Gregor 12524b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const { 12539d6448b1SBen Langmuir if (M->IsInferred) { 12549d6448b1SBen Langmuir assert(InferredModuleAllowedBy.count(M) && "missing inferred module map"); 12559d6448b1SBen Langmuir return InferredModuleAllowedBy.find(M)->second; 12569d6448b1SBen Langmuir } 12579d6448b1SBen Langmuir return getContainingModuleMapFile(M); 12589d6448b1SBen Langmuir } 12599d6448b1SBen Langmuir 12609d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) { 12619d6448b1SBen Langmuir assert(M->IsInferred && "module not inferred"); 12629d6448b1SBen Langmuir InferredModuleAllowedBy[M] = ModMap; 12639d6448b1SBen Langmuir } 12649d6448b1SBen Langmuir 1265e08464fbSReid Kleckner void ModuleMap::addAdditionalModuleMapFile(const Module *M, 1266e08464fbSReid Kleckner const FileEntry *ModuleMap) { 1267e08464fbSReid Kleckner AdditionalModMaps[M].insert(ModuleMap); 1268e08464fbSReid Kleckner } 1269e08464fbSReid Kleckner 1270cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() { 1271718292f2SDouglas Gregor llvm::errs() << "Modules:"; 1272718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 1273718292f2SDouglas Gregor MEnd = Modules.end(); 1274718292f2SDouglas Gregor M != MEnd; ++M) 1275d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 1276718292f2SDouglas Gregor 1277718292f2SDouglas Gregor llvm::errs() << "Headers:"; 127859527666SDouglas Gregor for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end(); 1279718292f2SDouglas Gregor H != HEnd; ++H) { 128097da9178SDaniel Jasper llvm::errs() << " \"" << H->first->getName() << "\" -> "; 128197da9178SDaniel Jasper for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(), 128297da9178SDaniel Jasper E = H->second.end(); 128397da9178SDaniel Jasper I != E; ++I) { 128497da9178SDaniel Jasper if (I != H->second.begin()) 128597da9178SDaniel Jasper llvm::errs() << ","; 128697da9178SDaniel Jasper llvm::errs() << I->getModule()->getFullModuleName(); 128797da9178SDaniel Jasper } 128897da9178SDaniel Jasper llvm::errs() << "\n"; 1289718292f2SDouglas Gregor } 1290718292f2SDouglas Gregor } 1291718292f2SDouglas Gregor 12922b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) { 129342413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedExports); 129442413141SRichard Smith Mod->UnresolvedExports.clear(); 129542413141SRichard Smith for (auto &UE : Unresolved) { 129642413141SRichard Smith Module::ExportDecl Export = resolveExport(Mod, UE, Complain); 1297f5eedd05SDouglas Gregor if (Export.getPointer() || Export.getInt()) 12982b82c2a5SDouglas Gregor Mod->Exports.push_back(Export); 12992b82c2a5SDouglas Gregor else 130042413141SRichard Smith Mod->UnresolvedExports.push_back(UE); 13012b82c2a5SDouglas Gregor } 130242413141SRichard Smith return !Mod->UnresolvedExports.empty(); 13032b82c2a5SDouglas Gregor } 13042b82c2a5SDouglas Gregor 1305ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) { 130642413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedDirectUses); 130742413141SRichard Smith Mod->UnresolvedDirectUses.clear(); 130842413141SRichard Smith for (auto &UDU : Unresolved) { 130942413141SRichard Smith Module *DirectUse = resolveModuleId(UDU, Mod, Complain); 1310ba7f2f71SDaniel Jasper if (DirectUse) 1311ba7f2f71SDaniel Jasper Mod->DirectUses.push_back(DirectUse); 1312ba7f2f71SDaniel Jasper else 131342413141SRichard Smith Mod->UnresolvedDirectUses.push_back(UDU); 1314ba7f2f71SDaniel Jasper } 131542413141SRichard Smith return !Mod->UnresolvedDirectUses.empty(); 1316ba7f2f71SDaniel Jasper } 1317ba7f2f71SDaniel Jasper 1318fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) { 131942413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedConflicts); 132042413141SRichard Smith Mod->UnresolvedConflicts.clear(); 132142413141SRichard Smith for (auto &UC : Unresolved) { 132242413141SRichard Smith if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) { 1323fb912657SDouglas Gregor Module::Conflict Conflict; 1324fb912657SDouglas Gregor Conflict.Other = OtherMod; 132542413141SRichard Smith Conflict.Message = UC.Message; 1326fb912657SDouglas Gregor Mod->Conflicts.push_back(Conflict); 132742413141SRichard Smith } else 132842413141SRichard Smith Mod->UnresolvedConflicts.push_back(UC); 1329fb912657SDouglas Gregor } 133042413141SRichard Smith return !Mod->UnresolvedConflicts.empty(); 1331fb912657SDouglas Gregor } 1332fb912657SDouglas Gregor 1333718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1334718292f2SDouglas Gregor // Module map file parser 1335718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1336718292f2SDouglas Gregor 1337718292f2SDouglas Gregor namespace clang { 1338afd1b1c9SEugene Zelenko 13399fc8faf9SAdrian Prantl /// A token in a module map file. 1340718292f2SDouglas Gregor struct MMToken { 1341718292f2SDouglas Gregor enum TokenKind { 13421fb5c3a6SDouglas Gregor Comma, 134335b13eceSDouglas Gregor ConfigMacros, 1344fb912657SDouglas Gregor Conflict, 1345718292f2SDouglas Gregor EndOfFile, 1346718292f2SDouglas Gregor HeaderKeyword, 1347718292f2SDouglas Gregor Identifier, 1348a3feee2aSRichard Smith Exclaim, 134959527666SDouglas Gregor ExcludeKeyword, 1350718292f2SDouglas Gregor ExplicitKeyword, 13512b82c2a5SDouglas Gregor ExportKeyword, 1352f0b11de2SDouglas Gregor ExportAsKeyword, 135397292843SDaniel Jasper ExternKeyword, 1354755b2055SDouglas Gregor FrameworkKeyword, 13556ddfca91SDouglas Gregor LinkKeyword, 1356718292f2SDouglas Gregor ModuleKeyword, 13572b82c2a5SDouglas Gregor Period, 1358b53e5483SLawrence Crowl PrivateKeyword, 1359718292f2SDouglas Gregor UmbrellaKeyword, 1360ba7f2f71SDaniel Jasper UseKeyword, 13611fb5c3a6SDouglas Gregor RequiresKeyword, 13622b82c2a5SDouglas Gregor Star, 1363718292f2SDouglas Gregor StringLiteral, 1364040e1266SRichard Smith IntegerLiteral, 1365306d8920SRichard Smith TextualKeyword, 1366718292f2SDouglas Gregor LBrace, 1367a686e1b0SDouglas Gregor RBrace, 1368a686e1b0SDouglas Gregor LSquare, 1369a686e1b0SDouglas Gregor RSquare 1370718292f2SDouglas Gregor } Kind; 1371718292f2SDouglas Gregor 1372718292f2SDouglas Gregor unsigned Location; 1373718292f2SDouglas Gregor unsigned StringLength; 1374040e1266SRichard Smith union { 1375040e1266SRichard Smith // If Kind != IntegerLiteral. 1376718292f2SDouglas Gregor const char *StringData; 1377afd1b1c9SEugene Zelenko 1378040e1266SRichard Smith // If Kind == IntegerLiteral. 1379040e1266SRichard Smith uint64_t IntegerValue; 1380040e1266SRichard Smith }; 1381718292f2SDouglas Gregor 1382718292f2SDouglas Gregor void clear() { 1383718292f2SDouglas Gregor Kind = EndOfFile; 1384718292f2SDouglas Gregor Location = 0; 1385718292f2SDouglas Gregor StringLength = 0; 1386d2d442caSCraig Topper StringData = nullptr; 1387718292f2SDouglas Gregor } 1388718292f2SDouglas Gregor 1389718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 1390718292f2SDouglas Gregor 1391718292f2SDouglas Gregor SourceLocation getLocation() const { 1392718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 1393718292f2SDouglas Gregor } 1394718292f2SDouglas Gregor 1395040e1266SRichard Smith uint64_t getInteger() const { 1396040e1266SRichard Smith return Kind == IntegerLiteral ? IntegerValue : 0; 1397040e1266SRichard Smith } 1398040e1266SRichard Smith 1399718292f2SDouglas Gregor StringRef getString() const { 1400040e1266SRichard Smith return Kind == IntegerLiteral ? StringRef() 1401040e1266SRichard Smith : StringRef(StringData, StringLength); 1402718292f2SDouglas Gregor } 1403718292f2SDouglas Gregor }; 1404718292f2SDouglas Gregor 1405718292f2SDouglas Gregor class ModuleMapParser { 1406718292f2SDouglas Gregor Lexer &L; 1407718292f2SDouglas Gregor SourceManager &SourceMgr; 1408bc10b9fbSDouglas Gregor 14099fc8faf9SAdrian Prantl /// Default target information, used only for string literal 1410bc10b9fbSDouglas Gregor /// parsing. 1411bc10b9fbSDouglas Gregor const TargetInfo *Target; 1412bc10b9fbSDouglas Gregor 1413718292f2SDouglas Gregor DiagnosticsEngine &Diags; 1414718292f2SDouglas Gregor ModuleMap ⤅ 1415718292f2SDouglas Gregor 14169fc8faf9SAdrian Prantl /// The current module map file. 1417beee15e7SBen Langmuir const FileEntry *ModuleMapFile; 1418beee15e7SBen Langmuir 14199f6020bcSBruno Cardoso Lopes /// Source location of most recent parsed module declaration 14209f6020bcSBruno Cardoso Lopes SourceLocation CurrModuleDeclLoc; 14219f6020bcSBruno Cardoso Lopes 14229fc8faf9SAdrian Prantl /// The directory that file names in this module map file should 14239acb99e3SRichard Smith /// be resolved relative to. 14245257fc63SDouglas Gregor const DirectoryEntry *Directory; 14255257fc63SDouglas Gregor 14269fc8faf9SAdrian Prantl /// Whether this module map is in a system header directory. 1427963c5535SDouglas Gregor bool IsSystem; 1428963c5535SDouglas Gregor 14299fc8faf9SAdrian Prantl /// Whether an error occurred. 1430afd1b1c9SEugene Zelenko bool HadError = false; 1431718292f2SDouglas Gregor 14329fc8faf9SAdrian Prantl /// Stores string data for the various string literals referenced 1433718292f2SDouglas Gregor /// during parsing. 1434718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 1435718292f2SDouglas Gregor 14369fc8faf9SAdrian Prantl /// The current token. 1437718292f2SDouglas Gregor MMToken Tok; 1438718292f2SDouglas Gregor 14399fc8faf9SAdrian Prantl /// The active module. 1440afd1b1c9SEugene Zelenko Module *ActiveModule = nullptr; 1441718292f2SDouglas Gregor 14429fc8faf9SAdrian Prantl /// Whether a module uses the 'requires excluded' hack to mark its 14437ff29148SBen Langmuir /// contents as 'textual'. 14447ff29148SBen Langmuir /// 14457ff29148SBen Langmuir /// On older Darwin SDK versions, 'requires excluded' is used to mark the 14467ff29148SBen Langmuir /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as 14477ff29148SBen Langmuir /// non-modular headers. For backwards compatibility, we continue to 14487ff29148SBen Langmuir /// support this idiom for just these modules, and map the headers to 14497ff29148SBen Langmuir /// 'textual' to match the original intent. 14507ff29148SBen Langmuir llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack; 14517ff29148SBen Langmuir 14529fc8faf9SAdrian Prantl /// Consume the current token and return its location. 1453718292f2SDouglas Gregor SourceLocation consumeToken(); 1454718292f2SDouglas Gregor 14559fc8faf9SAdrian Prantl /// Skip tokens until we reach the a token with the given kind 1456718292f2SDouglas Gregor /// (or the end of the file). 1457718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 1458718292f2SDouglas Gregor 1459afd1b1c9SEugene Zelenko using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>; 1460afd1b1c9SEugene Zelenko 1461e7ab3669SDouglas Gregor bool parseModuleId(ModuleId &Id); 1462718292f2SDouglas Gregor void parseModuleDecl(); 146397292843SDaniel Jasper void parseExternModuleDecl(); 14641fb5c3a6SDouglas Gregor void parseRequiresDecl(); 1465afd1b1c9SEugene Zelenko void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc); 1466524e33e1SDouglas Gregor void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc); 14672b82c2a5SDouglas Gregor void parseExportDecl(); 1468f0b11de2SDouglas Gregor void parseExportAsDecl(); 1469ba7f2f71SDaniel Jasper void parseUseDecl(); 14706ddfca91SDouglas Gregor void parseLinkDecl(); 147135b13eceSDouglas Gregor void parseConfigMacros(); 1472fb912657SDouglas Gregor void parseConflict(); 14739194a91dSDouglas Gregor void parseInferredModuleDecl(bool Framework, bool Explicit); 1474c1d88ea5SBen Langmuir 14755f11e128SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra 14765f11e128SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH 14775f11e128SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written 14785f11e128SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits. 14795f11e128SBruno Cardoso Lopes void diagnosePrivateModules(SourceLocation ExplicitLoc, 14805f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc); 14815f11e128SBruno Cardoso Lopes 1482afd1b1c9SEugene Zelenko using Attributes = ModuleMap::Attributes; 1483afd1b1c9SEugene Zelenko 14844442605fSBill Wendling bool parseOptionalAttributes(Attributes &Attrs); 1485718292f2SDouglas Gregor 1486718292f2SDouglas Gregor public: 1487718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 14888587dfd9SBruno Cardoso Lopes const TargetInfo *Target, DiagnosticsEngine &Diags, 14898587dfd9SBruno Cardoso Lopes ModuleMap &Map, const FileEntry *ModuleMapFile, 1490c192d194SBruno Cardoso Lopes const DirectoryEntry *Directory, bool IsSystem) 1491bc10b9fbSDouglas Gregor : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map), 1492beee15e7SBen Langmuir ModuleMapFile(ModuleMapFile), Directory(Directory), 1493c192d194SBruno Cardoso Lopes IsSystem(IsSystem) { 1494718292f2SDouglas Gregor Tok.clear(); 1495718292f2SDouglas Gregor consumeToken(); 1496718292f2SDouglas Gregor } 1497718292f2SDouglas Gregor 1498718292f2SDouglas Gregor bool parseModuleMapFile(); 14998128f332SRichard Smith 15008128f332SRichard Smith bool terminatedByDirective() { return false; } 15018128f332SRichard Smith SourceLocation getLocation() { return Tok.getLocation(); } 1502718292f2SDouglas Gregor }; 1503afd1b1c9SEugene Zelenko 1504afd1b1c9SEugene Zelenko } // namespace clang 1505718292f2SDouglas Gregor 1506718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 1507718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 1508718292f2SDouglas Gregor 15098128f332SRichard Smith retry: 15108128f332SRichard Smith Tok.clear(); 1511718292f2SDouglas Gregor Token LToken; 1512718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 1513718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 1514718292f2SDouglas Gregor switch (LToken.getKind()) { 15152d57cea2SAlp Toker case tok::raw_identifier: { 15162d57cea2SAlp Toker StringRef RI = LToken.getRawIdentifier(); 15172d57cea2SAlp Toker Tok.StringData = RI.data(); 15182d57cea2SAlp Toker Tok.StringLength = RI.size(); 15192d57cea2SAlp Toker Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI) 152035b13eceSDouglas Gregor .Case("config_macros", MMToken::ConfigMacros) 1521fb912657SDouglas Gregor .Case("conflict", MMToken::Conflict) 152259527666SDouglas Gregor .Case("exclude", MMToken::ExcludeKeyword) 1523718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 15242b82c2a5SDouglas Gregor .Case("export", MMToken::ExportKeyword) 1525f0b11de2SDouglas Gregor .Case("export_as", MMToken::ExportAsKeyword) 152697292843SDaniel Jasper .Case("extern", MMToken::ExternKeyword) 1527755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 152835b13eceSDouglas Gregor .Case("header", MMToken::HeaderKeyword) 15296ddfca91SDouglas Gregor .Case("link", MMToken::LinkKeyword) 1530718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 1531b53e5483SLawrence Crowl .Case("private", MMToken::PrivateKeyword) 15321fb5c3a6SDouglas Gregor .Case("requires", MMToken::RequiresKeyword) 1533306d8920SRichard Smith .Case("textual", MMToken::TextualKeyword) 1534718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 1535ba7f2f71SDaniel Jasper .Case("use", MMToken::UseKeyword) 1536718292f2SDouglas Gregor .Default(MMToken::Identifier); 1537718292f2SDouglas Gregor break; 15382d57cea2SAlp Toker } 1539718292f2SDouglas Gregor 15401fb5c3a6SDouglas Gregor case tok::comma: 15411fb5c3a6SDouglas Gregor Tok.Kind = MMToken::Comma; 15421fb5c3a6SDouglas Gregor break; 15431fb5c3a6SDouglas Gregor 1544718292f2SDouglas Gregor case tok::eof: 1545718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 1546718292f2SDouglas Gregor break; 1547718292f2SDouglas Gregor 1548718292f2SDouglas Gregor case tok::l_brace: 1549718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 1550718292f2SDouglas Gregor break; 1551718292f2SDouglas Gregor 1552a686e1b0SDouglas Gregor case tok::l_square: 1553a686e1b0SDouglas Gregor Tok.Kind = MMToken::LSquare; 1554a686e1b0SDouglas Gregor break; 1555a686e1b0SDouglas Gregor 15562b82c2a5SDouglas Gregor case tok::period: 15572b82c2a5SDouglas Gregor Tok.Kind = MMToken::Period; 15582b82c2a5SDouglas Gregor break; 15592b82c2a5SDouglas Gregor 1560718292f2SDouglas Gregor case tok::r_brace: 1561718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 1562718292f2SDouglas Gregor break; 1563718292f2SDouglas Gregor 1564a686e1b0SDouglas Gregor case tok::r_square: 1565a686e1b0SDouglas Gregor Tok.Kind = MMToken::RSquare; 1566a686e1b0SDouglas Gregor break; 1567a686e1b0SDouglas Gregor 15682b82c2a5SDouglas Gregor case tok::star: 15692b82c2a5SDouglas Gregor Tok.Kind = MMToken::Star; 15702b82c2a5SDouglas Gregor break; 15712b82c2a5SDouglas Gregor 1572a3feee2aSRichard Smith case tok::exclaim: 1573a3feee2aSRichard Smith Tok.Kind = MMToken::Exclaim; 1574a3feee2aSRichard Smith break; 1575a3feee2aSRichard Smith 1576718292f2SDouglas Gregor case tok::string_literal: { 1577d67aea28SRichard Smith if (LToken.hasUDSuffix()) { 1578d67aea28SRichard Smith Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl); 1579d67aea28SRichard Smith HadError = true; 1580d67aea28SRichard Smith goto retry; 1581d67aea28SRichard Smith } 1582d67aea28SRichard Smith 1583718292f2SDouglas Gregor // Parse the string literal. 1584718292f2SDouglas Gregor LangOptions LangOpts; 15859d5583efSCraig Topper StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target); 1586718292f2SDouglas Gregor if (StringLiteral.hadError) 1587718292f2SDouglas Gregor goto retry; 1588718292f2SDouglas Gregor 1589718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 1590718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 1591718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 1592718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 1593718292f2SDouglas Gregor Saved[Length] = 0; 1594718292f2SDouglas Gregor 1595718292f2SDouglas Gregor // Form the token. 1596718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 1597718292f2SDouglas Gregor Tok.StringData = Saved; 1598718292f2SDouglas Gregor Tok.StringLength = Length; 1599718292f2SDouglas Gregor break; 1600718292f2SDouglas Gregor } 1601718292f2SDouglas Gregor 1602040e1266SRichard Smith case tok::numeric_constant: { 1603040e1266SRichard Smith // We don't support any suffixes or other complications. 1604040e1266SRichard Smith SmallString<32> SpellingBuffer; 1605040e1266SRichard Smith SpellingBuffer.resize(LToken.getLength() + 1); 1606040e1266SRichard Smith const char *Start = SpellingBuffer.data(); 1607040e1266SRichard Smith unsigned Length = 1608040e1266SRichard Smith Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts()); 1609040e1266SRichard Smith uint64_t Value; 1610040e1266SRichard Smith if (StringRef(Start, Length).getAsInteger(0, Value)) { 1611040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1612040e1266SRichard Smith HadError = true; 1613040e1266SRichard Smith goto retry; 1614040e1266SRichard Smith } 1615040e1266SRichard Smith 1616040e1266SRichard Smith Tok.Kind = MMToken::IntegerLiteral; 1617040e1266SRichard Smith Tok.IntegerValue = Value; 1618040e1266SRichard Smith break; 1619040e1266SRichard Smith } 1620040e1266SRichard Smith 1621718292f2SDouglas Gregor case tok::comment: 1622718292f2SDouglas Gregor goto retry; 1623718292f2SDouglas Gregor 16248128f332SRichard Smith case tok::hash: 16258128f332SRichard Smith // A module map can be terminated prematurely by 16268128f332SRichard Smith // #pragma clang module contents 16278128f332SRichard Smith // When building the module, we'll treat the rest of the file as the 16288128f332SRichard Smith // contents of the module. 16298128f332SRichard Smith { 16308128f332SRichard Smith auto NextIsIdent = [&](StringRef Str) -> bool { 16318128f332SRichard Smith L.LexFromRawLexer(LToken); 16328128f332SRichard Smith return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) && 16338128f332SRichard Smith LToken.getRawIdentifier() == Str; 16348128f332SRichard Smith }; 16358128f332SRichard Smith if (NextIsIdent("pragma") && NextIsIdent("clang") && 16368128f332SRichard Smith NextIsIdent("module") && NextIsIdent("contents")) { 16378128f332SRichard Smith Tok.Kind = MMToken::EndOfFile; 16388128f332SRichard Smith break; 16398128f332SRichard Smith } 16408128f332SRichard Smith } 16418128f332SRichard Smith LLVM_FALLTHROUGH; 16428128f332SRichard Smith 1643718292f2SDouglas Gregor default: 16448128f332SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1645718292f2SDouglas Gregor HadError = true; 1646718292f2SDouglas Gregor goto retry; 1647718292f2SDouglas Gregor } 1648718292f2SDouglas Gregor 1649718292f2SDouglas Gregor return Result; 1650718292f2SDouglas Gregor } 1651718292f2SDouglas Gregor 1652718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 1653718292f2SDouglas Gregor unsigned braceDepth = 0; 1654a686e1b0SDouglas Gregor unsigned squareDepth = 0; 1655718292f2SDouglas Gregor do { 1656718292f2SDouglas Gregor switch (Tok.Kind) { 1657718292f2SDouglas Gregor case MMToken::EndOfFile: 1658718292f2SDouglas Gregor return; 1659718292f2SDouglas Gregor 1660718292f2SDouglas Gregor case MMToken::LBrace: 1661a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1662718292f2SDouglas Gregor return; 1663718292f2SDouglas Gregor 1664718292f2SDouglas Gregor ++braceDepth; 1665718292f2SDouglas Gregor break; 1666718292f2SDouglas Gregor 1667a686e1b0SDouglas Gregor case MMToken::LSquare: 1668a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1669a686e1b0SDouglas Gregor return; 1670a686e1b0SDouglas Gregor 1671a686e1b0SDouglas Gregor ++squareDepth; 1672a686e1b0SDouglas Gregor break; 1673a686e1b0SDouglas Gregor 1674718292f2SDouglas Gregor case MMToken::RBrace: 1675718292f2SDouglas Gregor if (braceDepth > 0) 1676718292f2SDouglas Gregor --braceDepth; 1677718292f2SDouglas Gregor else if (Tok.is(K)) 1678718292f2SDouglas Gregor return; 1679718292f2SDouglas Gregor break; 1680718292f2SDouglas Gregor 1681a686e1b0SDouglas Gregor case MMToken::RSquare: 1682a686e1b0SDouglas Gregor if (squareDepth > 0) 1683a686e1b0SDouglas Gregor --squareDepth; 1684a686e1b0SDouglas Gregor else if (Tok.is(K)) 1685a686e1b0SDouglas Gregor return; 1686a686e1b0SDouglas Gregor break; 1687a686e1b0SDouglas Gregor 1688718292f2SDouglas Gregor default: 1689a686e1b0SDouglas Gregor if (braceDepth == 0 && squareDepth == 0 && Tok.is(K)) 1690718292f2SDouglas Gregor return; 1691718292f2SDouglas Gregor break; 1692718292f2SDouglas Gregor } 1693718292f2SDouglas Gregor 1694718292f2SDouglas Gregor consumeToken(); 1695718292f2SDouglas Gregor } while (true); 1696718292f2SDouglas Gregor } 1697718292f2SDouglas Gregor 16989fc8faf9SAdrian Prantl /// Parse a module-id. 1699e7ab3669SDouglas Gregor /// 1700e7ab3669SDouglas Gregor /// module-id: 1701e7ab3669SDouglas Gregor /// identifier 1702e7ab3669SDouglas Gregor /// identifier '.' module-id 1703e7ab3669SDouglas Gregor /// 1704e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise. 1705e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) { 1706e7ab3669SDouglas Gregor Id.clear(); 1707e7ab3669SDouglas Gregor do { 17083cd34c76SDaniel Jasper if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) { 1709adcd0268SBenjamin Kramer Id.push_back( 1710adcd0268SBenjamin Kramer std::make_pair(std::string(Tok.getString()), Tok.getLocation())); 1711e7ab3669SDouglas Gregor consumeToken(); 1712e7ab3669SDouglas Gregor } else { 1713e7ab3669SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 1714e7ab3669SDouglas Gregor return true; 1715e7ab3669SDouglas Gregor } 1716e7ab3669SDouglas Gregor 1717e7ab3669SDouglas Gregor if (!Tok.is(MMToken::Period)) 1718e7ab3669SDouglas Gregor break; 1719e7ab3669SDouglas Gregor 1720e7ab3669SDouglas Gregor consumeToken(); 1721e7ab3669SDouglas Gregor } while (true); 1722e7ab3669SDouglas Gregor 1723e7ab3669SDouglas Gregor return false; 1724e7ab3669SDouglas Gregor } 1725e7ab3669SDouglas Gregor 1726a686e1b0SDouglas Gregor namespace { 1727afd1b1c9SEugene Zelenko 17289fc8faf9SAdrian Prantl /// Enumerates the known attributes. 1729a686e1b0SDouglas Gregor enum AttributeKind { 17309fc8faf9SAdrian Prantl /// An unknown attribute. 1731a686e1b0SDouglas Gregor AT_unknown, 1732afd1b1c9SEugene Zelenko 17339fc8faf9SAdrian Prantl /// The 'system' attribute. 173435b13eceSDouglas Gregor AT_system, 1735afd1b1c9SEugene Zelenko 17369fc8faf9SAdrian Prantl /// The 'extern_c' attribute. 173777944868SRichard Smith AT_extern_c, 1738afd1b1c9SEugene Zelenko 17399fc8faf9SAdrian Prantl /// The 'exhaustive' attribute. 1740ed84df00SBruno Cardoso Lopes AT_exhaustive, 1741afd1b1c9SEugene Zelenko 17429fc8faf9SAdrian Prantl /// The 'no_undeclared_includes' attribute. 1743ed84df00SBruno Cardoso Lopes AT_no_undeclared_includes 1744a686e1b0SDouglas Gregor }; 1745afd1b1c9SEugene Zelenko 1746afd1b1c9SEugene Zelenko } // namespace 1747a686e1b0SDouglas Gregor 174829729919SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra 174929729919SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH 175029729919SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written 175129729919SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits. 17525f11e128SBruno Cardoso Lopes void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc, 17535f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc) { 175429729919SBruno Cardoso Lopes auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical, 17557d29486dSBruno Cardoso Lopes const Module *M, SourceRange ReplLoc) { 175629729919SBruno Cardoso Lopes auto D = Diags.Report(ActiveModule->DefinitionLoc, 175729729919SBruno Cardoso Lopes diag::note_mmap_rename_top_level_private_module); 175829729919SBruno Cardoso Lopes D << BadName << M->Name; 17597d29486dSBruno Cardoso Lopes D << FixItHint::CreateReplacement(ReplLoc, Canonical); 176029729919SBruno Cardoso Lopes }; 176129729919SBruno Cardoso Lopes 176229729919SBruno Cardoso Lopes for (auto E = Map.module_begin(); E != Map.module_end(); ++E) { 176329729919SBruno Cardoso Lopes auto const *M = E->getValue(); 176429729919SBruno Cardoso Lopes if (M->Directory != ActiveModule->Directory) 176529729919SBruno Cardoso Lopes continue; 176629729919SBruno Cardoso Lopes 176729729919SBruno Cardoso Lopes SmallString<128> FullName(ActiveModule->getFullModuleName()); 176829729919SBruno Cardoso Lopes if (!FullName.startswith(M->Name) && !FullName.endswith("Private")) 176929729919SBruno Cardoso Lopes continue; 17705f11e128SBruno Cardoso Lopes SmallString<128> FixedPrivModDecl; 177129729919SBruno Cardoso Lopes SmallString<128> Canonical(M->Name); 177229729919SBruno Cardoso Lopes Canonical.append("_Private"); 177329729919SBruno Cardoso Lopes 177429729919SBruno Cardoso Lopes // Foo.Private -> Foo_Private 177529729919SBruno Cardoso Lopes if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent && 177629729919SBruno Cardoso Lopes M->Name == ActiveModule->Parent->Name) { 177729729919SBruno Cardoso Lopes Diags.Report(ActiveModule->DefinitionLoc, 177829729919SBruno Cardoso Lopes diag::warn_mmap_mismatched_private_submodule) 177929729919SBruno Cardoso Lopes << FullName; 17805f11e128SBruno Cardoso Lopes 17815f11e128SBruno Cardoso Lopes SourceLocation FixItInitBegin = CurrModuleDeclLoc; 17825f11e128SBruno Cardoso Lopes if (FrameworkLoc.isValid()) 17835f11e128SBruno Cardoso Lopes FixItInitBegin = FrameworkLoc; 17845f11e128SBruno Cardoso Lopes if (ExplicitLoc.isValid()) 17855f11e128SBruno Cardoso Lopes FixItInitBegin = ExplicitLoc; 17865f11e128SBruno Cardoso Lopes 17875f11e128SBruno Cardoso Lopes if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework) 17885f11e128SBruno Cardoso Lopes FixedPrivModDecl.append("framework "); 17895f11e128SBruno Cardoso Lopes FixedPrivModDecl.append("module "); 17905f11e128SBruno Cardoso Lopes FixedPrivModDecl.append(Canonical); 17915f11e128SBruno Cardoso Lopes 17925f11e128SBruno Cardoso Lopes GenNoteAndFixIt(FullName, FixedPrivModDecl, M, 17935f11e128SBruno Cardoso Lopes SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc)); 179429729919SBruno Cardoso Lopes continue; 179529729919SBruno Cardoso Lopes } 179629729919SBruno Cardoso Lopes 179729729919SBruno Cardoso Lopes // FooPrivate and whatnots -> Foo_Private 179829729919SBruno Cardoso Lopes if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name && 179929729919SBruno Cardoso Lopes ActiveModule->Name != Canonical) { 180029729919SBruno Cardoso Lopes Diags.Report(ActiveModule->DefinitionLoc, 180129729919SBruno Cardoso Lopes diag::warn_mmap_mismatched_private_module_name) 180229729919SBruno Cardoso Lopes << ActiveModule->Name; 18037d29486dSBruno Cardoso Lopes GenNoteAndFixIt(ActiveModule->Name, Canonical, M, 18047d29486dSBruno Cardoso Lopes SourceRange(ActiveModule->DefinitionLoc)); 180529729919SBruno Cardoso Lopes } 180629729919SBruno Cardoso Lopes } 180729729919SBruno Cardoso Lopes } 180829729919SBruno Cardoso Lopes 18099fc8faf9SAdrian Prantl /// Parse a module declaration. 1810718292f2SDouglas Gregor /// 1811718292f2SDouglas Gregor /// module-declaration: 181297292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 1813a686e1b0SDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt] 1814a686e1b0SDouglas Gregor /// { module-member* } 1815a686e1b0SDouglas Gregor /// 1816718292f2SDouglas Gregor /// module-member: 18171fb5c3a6SDouglas Gregor /// requires-declaration 1818718292f2SDouglas Gregor /// header-declaration 1819e7ab3669SDouglas Gregor /// submodule-declaration 18202b82c2a5SDouglas Gregor /// export-declaration 1821f0b11de2SDouglas Gregor /// export-as-declaration 18226ddfca91SDouglas Gregor /// link-declaration 182373441091SDouglas Gregor /// 182473441091SDouglas Gregor /// submodule-declaration: 182573441091SDouglas Gregor /// module-declaration 182673441091SDouglas Gregor /// inferred-submodule-declaration 1827718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 1828755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 182997292843SDaniel Jasper Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword)); 183097292843SDaniel Jasper if (Tok.is(MMToken::ExternKeyword)) { 183197292843SDaniel Jasper parseExternModuleDecl(); 183297292843SDaniel Jasper return; 183397292843SDaniel Jasper } 183497292843SDaniel Jasper 1835f2161a70SDouglas Gregor // Parse 'explicit' or 'framework' keyword, if present. 1836e7ab3669SDouglas Gregor SourceLocation ExplicitLoc; 18375f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc; 1838718292f2SDouglas Gregor bool Explicit = false; 1839f2161a70SDouglas Gregor bool Framework = false; 1840755b2055SDouglas Gregor 1841f2161a70SDouglas Gregor // Parse 'explicit' keyword, if present. 1842f2161a70SDouglas Gregor if (Tok.is(MMToken::ExplicitKeyword)) { 1843e7ab3669SDouglas Gregor ExplicitLoc = consumeToken(); 1844f2161a70SDouglas Gregor Explicit = true; 1845f2161a70SDouglas Gregor } 1846f2161a70SDouglas Gregor 1847f2161a70SDouglas Gregor // Parse 'framework' keyword, if present. 1848755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 18495f11e128SBruno Cardoso Lopes FrameworkLoc = consumeToken(); 1850755b2055SDouglas Gregor Framework = true; 1851755b2055SDouglas Gregor } 1852718292f2SDouglas Gregor 1853718292f2SDouglas Gregor // Parse 'module' keyword. 1854718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 1855d6343c99SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 1856718292f2SDouglas Gregor consumeToken(); 1857718292f2SDouglas Gregor HadError = true; 1858718292f2SDouglas Gregor return; 1859718292f2SDouglas Gregor } 18609f6020bcSBruno Cardoso Lopes CurrModuleDeclLoc = consumeToken(); // 'module' keyword 1861718292f2SDouglas Gregor 186273441091SDouglas Gregor // If we have a wildcard for the module name, this is an inferred submodule. 186373441091SDouglas Gregor // Parse it. 186473441091SDouglas Gregor if (Tok.is(MMToken::Star)) 18659194a91dSDouglas Gregor return parseInferredModuleDecl(Framework, Explicit); 186673441091SDouglas Gregor 1867718292f2SDouglas Gregor // Parse the module name. 1868e7ab3669SDouglas Gregor ModuleId Id; 1869e7ab3669SDouglas Gregor if (parseModuleId(Id)) { 1870718292f2SDouglas Gregor HadError = true; 1871718292f2SDouglas Gregor return; 1872718292f2SDouglas Gregor } 1873e7ab3669SDouglas Gregor 1874e7ab3669SDouglas Gregor if (ActiveModule) { 1875e7ab3669SDouglas Gregor if (Id.size() > 1) { 1876e7ab3669SDouglas Gregor Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id) 1877e7ab3669SDouglas Gregor << SourceRange(Id.front().second, Id.back().second); 1878e7ab3669SDouglas Gregor 1879e7ab3669SDouglas Gregor HadError = true; 1880e7ab3669SDouglas Gregor return; 1881e7ab3669SDouglas Gregor } 1882e7ab3669SDouglas Gregor } else if (Id.size() == 1 && Explicit) { 1883e7ab3669SDouglas Gregor // Top-level modules can't be explicit. 1884e7ab3669SDouglas Gregor Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level); 1885e7ab3669SDouglas Gregor Explicit = false; 1886e7ab3669SDouglas Gregor ExplicitLoc = SourceLocation(); 1887e7ab3669SDouglas Gregor HadError = true; 1888e7ab3669SDouglas Gregor } 1889e7ab3669SDouglas Gregor 1890e7ab3669SDouglas Gregor Module *PreviousActiveModule = ActiveModule; 1891e7ab3669SDouglas Gregor if (Id.size() > 1) { 1892e7ab3669SDouglas Gregor // This module map defines a submodule. Go find the module of which it 1893e7ab3669SDouglas Gregor // is a submodule. 1894d2d442caSCraig Topper ActiveModule = nullptr; 18954b8a9e95SBen Langmuir const Module *TopLevelModule = nullptr; 1896e7ab3669SDouglas Gregor for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) { 1897e7ab3669SDouglas Gregor if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) { 18984b8a9e95SBen Langmuir if (I == 0) 18994b8a9e95SBen Langmuir TopLevelModule = Next; 1900e7ab3669SDouglas Gregor ActiveModule = Next; 1901e7ab3669SDouglas Gregor continue; 1902e7ab3669SDouglas Gregor } 1903e7ab3669SDouglas Gregor 19048839e278SVolodymyr Sapsai Diags.Report(Id[I].second, diag::err_mmap_missing_parent_module) 19058839e278SVolodymyr Sapsai << Id[I].first << (ActiveModule != nullptr) 19068839e278SVolodymyr Sapsai << (ActiveModule 19078839e278SVolodymyr Sapsai ? ActiveModule->getTopLevelModule()->getFullModuleName() 19088839e278SVolodymyr Sapsai : ""); 1909e7ab3669SDouglas Gregor HadError = true; 1910e7ab3669SDouglas Gregor } 19114b8a9e95SBen Langmuir 19128839e278SVolodymyr Sapsai if (TopLevelModule && 19138839e278SVolodymyr Sapsai ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) { 19144b8a9e95SBen Langmuir assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) && 19154b8a9e95SBen Langmuir "submodule defined in same file as 'module *' that allowed its " 19164b8a9e95SBen Langmuir "top-level module"); 19174b8a9e95SBen Langmuir Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile); 19184b8a9e95SBen Langmuir } 1919e7ab3669SDouglas Gregor } 1920e7ab3669SDouglas Gregor 1921e7ab3669SDouglas Gregor StringRef ModuleName = Id.back().first; 1922e7ab3669SDouglas Gregor SourceLocation ModuleNameLoc = Id.back().second; 1923718292f2SDouglas Gregor 1924a686e1b0SDouglas Gregor // Parse the optional attribute list. 19254442605fSBill Wendling Attributes Attrs; 19265d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 19275d29dee0SDavide Italiano return; 19285d29dee0SDavide Italiano 1929718292f2SDouglas Gregor // Parse the opening brace. 1930718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 1931718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 1932718292f2SDouglas Gregor << ModuleName; 1933718292f2SDouglas Gregor HadError = true; 1934718292f2SDouglas Gregor return; 1935718292f2SDouglas Gregor } 1936718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 1937718292f2SDouglas Gregor 1938718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 19398587dfd9SBruno Cardoso Lopes Module *ShadowingModule = nullptr; 1940eb90e830SDouglas Gregor if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { 19414a3751ffSRichard Smith // We might see a (re)definition of a module that we already have a 19424a3751ffSRichard Smith // definition for in two cases: 19434a3751ffSRichard Smith // - If we loaded one definition from an AST file and we've just found a 19444a3751ffSRichard Smith // corresponding definition in a module map file, or 19454a3751ffSRichard Smith bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid(); 19464a3751ffSRichard Smith // - If we're building a (preprocessed) module and we've just loaded the 19474a3751ffSRichard Smith // module map file from which it was created. 19484a3751ffSRichard Smith bool ParsedAsMainInput = 19494a3751ffSRichard Smith Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap && 19504a3751ffSRichard Smith Map.LangOpts.CurrentModule == ModuleName && 19514a3751ffSRichard Smith SourceMgr.getDecomposedLoc(ModuleNameLoc).first != 19524a3751ffSRichard Smith SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first; 19534a3751ffSRichard Smith if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) { 1954fcc54a3bSDouglas Gregor // Skip the module definition. 1955fcc54a3bSDouglas Gregor skipUntil(MMToken::RBrace); 1956fcc54a3bSDouglas Gregor if (Tok.is(MMToken::RBrace)) 1957fcc54a3bSDouglas Gregor consumeToken(); 1958fcc54a3bSDouglas Gregor else { 1959fcc54a3bSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 1960fcc54a3bSDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 1961fcc54a3bSDouglas Gregor HadError = true; 1962fcc54a3bSDouglas Gregor } 1963fcc54a3bSDouglas Gregor return; 1964fcc54a3bSDouglas Gregor } 1965fcc54a3bSDouglas Gregor 1966c192d194SBruno Cardoso Lopes if (!Existing->Parent && Map.mayShadowNewModule(Existing)) { 19678587dfd9SBruno Cardoso Lopes ShadowingModule = Existing; 19688587dfd9SBruno Cardoso Lopes } else { 19698587dfd9SBruno Cardoso Lopes // This is not a shawdowed module decl, it is an illegal redefinition. 1970718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 1971718292f2SDouglas Gregor << ModuleName; 1972eb90e830SDouglas Gregor Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition); 1973718292f2SDouglas Gregor 1974718292f2SDouglas Gregor // Skip the module definition. 1975718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 1976718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 1977718292f2SDouglas Gregor consumeToken(); 1978718292f2SDouglas Gregor 1979718292f2SDouglas Gregor HadError = true; 1980718292f2SDouglas Gregor return; 1981718292f2SDouglas Gregor } 19828587dfd9SBruno Cardoso Lopes } 1983718292f2SDouglas Gregor 1984718292f2SDouglas Gregor // Start defining this module. 19858587dfd9SBruno Cardoso Lopes if (ShadowingModule) { 19868587dfd9SBruno Cardoso Lopes ActiveModule = 19878587dfd9SBruno Cardoso Lopes Map.createShadowedModule(ModuleName, Framework, ShadowingModule); 19888587dfd9SBruno Cardoso Lopes } else { 1989c192d194SBruno Cardoso Lopes ActiveModule = 1990c192d194SBruno Cardoso Lopes Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit) 19918587dfd9SBruno Cardoso Lopes .first; 19928587dfd9SBruno Cardoso Lopes } 19938587dfd9SBruno Cardoso Lopes 1994eb90e830SDouglas Gregor ActiveModule->DefinitionLoc = ModuleNameLoc; 1995963c5535SDouglas Gregor if (Attrs.IsSystem || IsSystem) 1996a686e1b0SDouglas Gregor ActiveModule->IsSystem = true; 199777944868SRichard Smith if (Attrs.IsExternC) 199877944868SRichard Smith ActiveModule->IsExternC = true; 1999ed84df00SBruno Cardoso Lopes if (Attrs.NoUndeclaredIncludes || 2000ed84df00SBruno Cardoso Lopes (!ActiveModule->Parent && ModuleName == "Darwin")) 2001ed84df00SBruno Cardoso Lopes ActiveModule->NoUndeclaredIncludes = true; 20023c1a41adSRichard Smith ActiveModule->Directory = Directory; 2003718292f2SDouglas Gregor 200490b0a1fcSJordan Rose StringRef MapFileName(ModuleMapFile->getName()); 200590b0a1fcSJordan Rose if (MapFileName.endswith("module.private.modulemap") || 200690b0a1fcSJordan Rose MapFileName.endswith("module_private.map")) { 200790b0a1fcSJordan Rose ActiveModule->ModuleMapIsPrivate = true; 200890b0a1fcSJordan Rose } 200929729919SBruno Cardoso Lopes 201029729919SBruno Cardoso Lopes // Private modules named as FooPrivate, Foo.Private or similar are likely a 201129729919SBruno Cardoso Lopes // user error; provide warnings, notes and fixits to direct users to use 201229729919SBruno Cardoso Lopes // Foo_Private instead. 201329729919SBruno Cardoso Lopes SourceLocation StartLoc = 201429729919SBruno Cardoso Lopes SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()); 201529729919SBruno Cardoso Lopes if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && 201629729919SBruno Cardoso Lopes !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule, 201729729919SBruno Cardoso Lopes StartLoc) && 201829729919SBruno Cardoso Lopes !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name, 201929729919SBruno Cardoso Lopes StartLoc) && 202090b0a1fcSJordan Rose ActiveModule->ModuleMapIsPrivate) 20215f11e128SBruno Cardoso Lopes diagnosePrivateModules(ExplicitLoc, FrameworkLoc); 20224d867640SGraydon Hoare 2023718292f2SDouglas Gregor bool Done = false; 2024718292f2SDouglas Gregor do { 2025718292f2SDouglas Gregor switch (Tok.Kind) { 2026718292f2SDouglas Gregor case MMToken::EndOfFile: 2027718292f2SDouglas Gregor case MMToken::RBrace: 2028718292f2SDouglas Gregor Done = true; 2029718292f2SDouglas Gregor break; 2030718292f2SDouglas Gregor 203135b13eceSDouglas Gregor case MMToken::ConfigMacros: 203235b13eceSDouglas Gregor parseConfigMacros(); 203335b13eceSDouglas Gregor break; 203435b13eceSDouglas Gregor 2035fb912657SDouglas Gregor case MMToken::Conflict: 2036fb912657SDouglas Gregor parseConflict(); 2037fb912657SDouglas Gregor break; 2038fb912657SDouglas Gregor 2039718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 204097292843SDaniel Jasper case MMToken::ExternKeyword: 2041f2161a70SDouglas Gregor case MMToken::FrameworkKeyword: 2042718292f2SDouglas Gregor case MMToken::ModuleKeyword: 2043718292f2SDouglas Gregor parseModuleDecl(); 2044718292f2SDouglas Gregor break; 2045718292f2SDouglas Gregor 20462b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 20472b82c2a5SDouglas Gregor parseExportDecl(); 20482b82c2a5SDouglas Gregor break; 20492b82c2a5SDouglas Gregor 2050f0b11de2SDouglas Gregor case MMToken::ExportAsKeyword: 2051f0b11de2SDouglas Gregor parseExportAsDecl(); 2052f0b11de2SDouglas Gregor break; 2053f0b11de2SDouglas Gregor 2054ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 2055ba7f2f71SDaniel Jasper parseUseDecl(); 2056ba7f2f71SDaniel Jasper break; 2057ba7f2f71SDaniel Jasper 20581fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 20591fb5c3a6SDouglas Gregor parseRequiresDecl(); 20601fb5c3a6SDouglas Gregor break; 20611fb5c3a6SDouglas Gregor 2062202210b3SRichard Smith case MMToken::TextualKeyword: 2063202210b3SRichard Smith parseHeaderDecl(MMToken::TextualKeyword, consumeToken()); 2064306d8920SRichard Smith break; 2065306d8920SRichard Smith 2066524e33e1SDouglas Gregor case MMToken::UmbrellaKeyword: { 2067524e33e1SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 2068524e33e1SDouglas Gregor if (Tok.is(MMToken::HeaderKeyword)) 2069b53e5483SLawrence Crowl parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc); 2070524e33e1SDouglas Gregor else 2071524e33e1SDouglas Gregor parseUmbrellaDirDecl(UmbrellaLoc); 2072718292f2SDouglas Gregor break; 2073524e33e1SDouglas Gregor } 2074718292f2SDouglas Gregor 2075202210b3SRichard Smith case MMToken::ExcludeKeyword: 2076202210b3SRichard Smith parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken()); 207759527666SDouglas Gregor break; 207859527666SDouglas Gregor 2079202210b3SRichard Smith case MMToken::PrivateKeyword: 2080202210b3SRichard Smith parseHeaderDecl(MMToken::PrivateKeyword, consumeToken()); 2081b53e5483SLawrence Crowl break; 2082b53e5483SLawrence Crowl 2083322f633cSDouglas Gregor case MMToken::HeaderKeyword: 2084202210b3SRichard Smith parseHeaderDecl(MMToken::HeaderKeyword, consumeToken()); 2085718292f2SDouglas Gregor break; 2086718292f2SDouglas Gregor 20876ddfca91SDouglas Gregor case MMToken::LinkKeyword: 20886ddfca91SDouglas Gregor parseLinkDecl(); 20896ddfca91SDouglas Gregor break; 20906ddfca91SDouglas Gregor 2091718292f2SDouglas Gregor default: 2092718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 2093718292f2SDouglas Gregor consumeToken(); 2094718292f2SDouglas Gregor break; 2095718292f2SDouglas Gregor } 2096718292f2SDouglas Gregor } while (!Done); 2097718292f2SDouglas Gregor 2098718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 2099718292f2SDouglas Gregor consumeToken(); 2100718292f2SDouglas Gregor else { 2101718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 2102718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 2103718292f2SDouglas Gregor HadError = true; 2104718292f2SDouglas Gregor } 2105718292f2SDouglas Gregor 210611dfe6feSDouglas Gregor // If the active module is a top-level framework, and there are no link 210711dfe6feSDouglas Gregor // libraries, automatically link against the framework. 210811dfe6feSDouglas Gregor if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() && 210911dfe6feSDouglas Gregor ActiveModule->LinkLibraries.empty()) { 211011dfe6feSDouglas Gregor inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager()); 211111dfe6feSDouglas Gregor } 211211dfe6feSDouglas Gregor 2113ec8c9752SBen Langmuir // If the module meets all requirements but is still unavailable, mark the 2114ec8c9752SBen Langmuir // whole tree as unavailable to prevent it from building. 2115fc76b4adSRichard Smith if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable && 2116ec8c9752SBen Langmuir ActiveModule->Parent) { 2117fc76b4adSRichard Smith ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false); 2118ec8c9752SBen Langmuir ActiveModule->getTopLevelModule()->MissingHeaders.append( 2119ec8c9752SBen Langmuir ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end()); 2120ec8c9752SBen Langmuir } 2121ec8c9752SBen Langmuir 2122e7ab3669SDouglas Gregor // We're done parsing this module. Pop back to the previous module. 2123e7ab3669SDouglas Gregor ActiveModule = PreviousActiveModule; 2124718292f2SDouglas Gregor } 2125718292f2SDouglas Gregor 21269fc8faf9SAdrian Prantl /// Parse an extern module declaration. 212797292843SDaniel Jasper /// 212897292843SDaniel Jasper /// extern module-declaration: 212997292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 213097292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() { 213197292843SDaniel Jasper assert(Tok.is(MMToken::ExternKeyword)); 2132ae6df27eSRichard Smith SourceLocation ExternLoc = consumeToken(); // 'extern' keyword 213397292843SDaniel Jasper 213497292843SDaniel Jasper // Parse 'module' keyword. 213597292843SDaniel Jasper if (!Tok.is(MMToken::ModuleKeyword)) { 213697292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 213797292843SDaniel Jasper consumeToken(); 213897292843SDaniel Jasper HadError = true; 213997292843SDaniel Jasper return; 214097292843SDaniel Jasper } 214197292843SDaniel Jasper consumeToken(); // 'module' keyword 214297292843SDaniel Jasper 214397292843SDaniel Jasper // Parse the module name. 214497292843SDaniel Jasper ModuleId Id; 214597292843SDaniel Jasper if (parseModuleId(Id)) { 214697292843SDaniel Jasper HadError = true; 214797292843SDaniel Jasper return; 214897292843SDaniel Jasper } 214997292843SDaniel Jasper 215097292843SDaniel Jasper // Parse the referenced module map file name. 215197292843SDaniel Jasper if (!Tok.is(MMToken::StringLiteral)) { 215297292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file); 215397292843SDaniel Jasper HadError = true; 215497292843SDaniel Jasper return; 215597292843SDaniel Jasper } 2156adcd0268SBenjamin Kramer std::string FileName = std::string(Tok.getString()); 215797292843SDaniel Jasper consumeToken(); // filename 215897292843SDaniel Jasper 215997292843SDaniel Jasper StringRef FileNameRef = FileName; 216097292843SDaniel Jasper SmallString<128> ModuleMapFileName; 216197292843SDaniel Jasper if (llvm::sys::path::is_relative(FileNameRef)) { 216297292843SDaniel Jasper ModuleMapFileName += Directory->getName(); 216397292843SDaniel Jasper llvm::sys::path::append(ModuleMapFileName, FileName); 216492e1b62dSYaron Keren FileNameRef = ModuleMapFileName; 216597292843SDaniel Jasper } 21668d323d15SHarlan Haskins if (auto File = SourceMgr.getFileManager().getFile(FileNameRef)) 21679acb99e3SRichard Smith Map.parseModuleMapFile( 21688d323d15SHarlan Haskins *File, /*IsSystem=*/false, 21699acb99e3SRichard Smith Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd 21709acb99e3SRichard Smith ? Directory 21718d323d15SHarlan Haskins : (*File)->getDir(), 2172c192d194SBruno Cardoso Lopes FileID(), nullptr, ExternLoc); 217397292843SDaniel Jasper } 217497292843SDaniel Jasper 21757ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M. 21767ff29148SBen Langmuir /// 21777ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system 21787ff29148SBen Langmuir /// module map files: 21797ff29148SBen Langmuir /// 21807ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which 21817ff29148SBen Langmuir /// should really be mapped to 'textual' now that we have this feature. We 21827ff29148SBen Langmuir /// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to 21837ff29148SBen Langmuir /// true. Later, this bit will be used to map all the headers inside this 21847ff29148SBen Langmuir /// module to 'textual'. 21857ff29148SBen Langmuir /// 21867ff29148SBen Langmuir /// This affects Darwin.C.excluded (for assert.h) and Tcl.Private. 21877ff29148SBen Langmuir /// 21887ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement 21897ff29148SBen Langmuir /// was never correct and causes issues now that we check it, so drop it. 21907ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature, 21917ff29148SBen Langmuir bool &IsRequiresExcludedHack) { 21928013e81dSBenjamin Kramer if (Feature == "excluded" && 21938013e81dSBenjamin Kramer (M->fullModuleNameIs({"Darwin", "C", "excluded"}) || 21948013e81dSBenjamin Kramer M->fullModuleNameIs({"Tcl", "Private"}))) { 21957ff29148SBen Langmuir IsRequiresExcludedHack = true; 21967ff29148SBen Langmuir return false; 21978013e81dSBenjamin Kramer } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) { 21987ff29148SBen Langmuir return false; 21997ff29148SBen Langmuir } 22007ff29148SBen Langmuir 22017ff29148SBen Langmuir return true; 22027ff29148SBen Langmuir } 22037ff29148SBen Langmuir 22049fc8faf9SAdrian Prantl /// Parse a requires declaration. 22051fb5c3a6SDouglas Gregor /// 22061fb5c3a6SDouglas Gregor /// requires-declaration: 22071fb5c3a6SDouglas Gregor /// 'requires' feature-list 22081fb5c3a6SDouglas Gregor /// 22091fb5c3a6SDouglas Gregor /// feature-list: 2210a3feee2aSRichard Smith /// feature ',' feature-list 2211a3feee2aSRichard Smith /// feature 2212a3feee2aSRichard Smith /// 2213a3feee2aSRichard Smith /// feature: 2214a3feee2aSRichard Smith /// '!'[opt] identifier 22151fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() { 22161fb5c3a6SDouglas Gregor assert(Tok.is(MMToken::RequiresKeyword)); 22171fb5c3a6SDouglas Gregor 22181fb5c3a6SDouglas Gregor // Parse 'requires' keyword. 22191fb5c3a6SDouglas Gregor consumeToken(); 22201fb5c3a6SDouglas Gregor 22211fb5c3a6SDouglas Gregor // Parse the feature-list. 22221fb5c3a6SDouglas Gregor do { 2223a3feee2aSRichard Smith bool RequiredState = true; 2224a3feee2aSRichard Smith if (Tok.is(MMToken::Exclaim)) { 2225a3feee2aSRichard Smith RequiredState = false; 2226a3feee2aSRichard Smith consumeToken(); 2227a3feee2aSRichard Smith } 2228a3feee2aSRichard Smith 22291fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 22301fb5c3a6SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature); 22311fb5c3a6SDouglas Gregor HadError = true; 22321fb5c3a6SDouglas Gregor return; 22331fb5c3a6SDouglas Gregor } 22341fb5c3a6SDouglas Gregor 22351fb5c3a6SDouglas Gregor // Consume the feature name. 2236adcd0268SBenjamin Kramer std::string Feature = std::string(Tok.getString()); 22371fb5c3a6SDouglas Gregor consumeToken(); 22381fb5c3a6SDouglas Gregor 22397ff29148SBen Langmuir bool IsRequiresExcludedHack = false; 22407ff29148SBen Langmuir bool ShouldAddRequirement = 22417ff29148SBen Langmuir shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack); 22427ff29148SBen Langmuir 22437ff29148SBen Langmuir if (IsRequiresExcludedHack) 22447ff29148SBen Langmuir UsesRequiresExcludedHack.insert(ActiveModule); 22457ff29148SBen Langmuir 22467ff29148SBen Langmuir if (ShouldAddRequirement) { 22471fb5c3a6SDouglas Gregor // Add this feature. 22487ff29148SBen Langmuir ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts, 22497ff29148SBen Langmuir *Map.Target); 22507ff29148SBen Langmuir } 22511fb5c3a6SDouglas Gregor 22521fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Comma)) 22531fb5c3a6SDouglas Gregor break; 22541fb5c3a6SDouglas Gregor 22551fb5c3a6SDouglas Gregor // Consume the comma. 22561fb5c3a6SDouglas Gregor consumeToken(); 22571fb5c3a6SDouglas Gregor } while (true); 22581fb5c3a6SDouglas Gregor } 22591fb5c3a6SDouglas Gregor 22609fc8faf9SAdrian Prantl /// Parse a header declaration. 2261718292f2SDouglas Gregor /// 2262718292f2SDouglas Gregor /// header-declaration: 2263306d8920SRichard Smith /// 'textual'[opt] 'header' string-literal 2264202210b3SRichard Smith /// 'private' 'textual'[opt] 'header' string-literal 2265202210b3SRichard Smith /// 'exclude' 'header' string-literal 2266202210b3SRichard Smith /// 'umbrella' 'header' string-literal 2267306d8920SRichard Smith /// 2268306d8920SRichard Smith /// FIXME: Support 'private textual header'. 2269b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, 2270b53e5483SLawrence Crowl SourceLocation LeadingLoc) { 2271202210b3SRichard Smith // We've already consumed the first token. 2272202210b3SRichard Smith ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader; 2273202210b3SRichard Smith if (LeadingToken == MMToken::PrivateKeyword) { 2274202210b3SRichard Smith Role = ModuleMap::PrivateHeader; 2275202210b3SRichard Smith // 'private' may optionally be followed by 'textual'. 2276202210b3SRichard Smith if (Tok.is(MMToken::TextualKeyword)) { 2277202210b3SRichard Smith LeadingToken = Tok.Kind; 22781871ed3dSBenjamin Kramer consumeToken(); 2279202210b3SRichard Smith } 2280202210b3SRichard Smith } 22817ff29148SBen Langmuir 2282202210b3SRichard Smith if (LeadingToken == MMToken::TextualKeyword) 2283202210b3SRichard Smith Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 2284202210b3SRichard Smith 22857ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 22867ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 22877ff29148SBen Langmuir // Module::UsesRequiresExcludedHack). 22887ff29148SBen Langmuir Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 22897ff29148SBen Langmuir } 22907ff29148SBen Langmuir 2291202210b3SRichard Smith if (LeadingToken != MMToken::HeaderKeyword) { 2292202210b3SRichard Smith if (!Tok.is(MMToken::HeaderKeyword)) { 2293202210b3SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2294202210b3SRichard Smith << (LeadingToken == MMToken::PrivateKeyword ? "private" : 2295202210b3SRichard Smith LeadingToken == MMToken::ExcludeKeyword ? "exclude" : 2296202210b3SRichard Smith LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella"); 2297202210b3SRichard Smith return; 2298202210b3SRichard Smith } 2299202210b3SRichard Smith consumeToken(); 2300202210b3SRichard Smith } 2301718292f2SDouglas Gregor 2302718292f2SDouglas Gregor // Parse the header name. 2303718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2304718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2305718292f2SDouglas Gregor << "header"; 2306718292f2SDouglas Gregor HadError = true; 2307718292f2SDouglas Gregor return; 2308718292f2SDouglas Gregor } 23093c1a41adSRichard Smith Module::UnresolvedHeaderDirective Header; 2310adcd0268SBenjamin Kramer Header.FileName = std::string(Tok.getString()); 23110761a8a0SDaniel Jasper Header.FileNameLoc = consumeToken(); 23121d60987fSRichard Smith Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword; 2313040e1266SRichard Smith Header.Kind = 2314040e1266SRichard Smith (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded 2315040e1266SRichard Smith : Map.headerRoleToKind(Role)); 2316718292f2SDouglas Gregor 2317524e33e1SDouglas Gregor // Check whether we already have an umbrella. 23181d60987fSRichard Smith if (Header.IsUmbrella && ActiveModule->Umbrella) { 23190761a8a0SDaniel Jasper Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) 2320524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2321322f633cSDouglas Gregor HadError = true; 2322322f633cSDouglas Gregor return; 2323322f633cSDouglas Gregor } 2324322f633cSDouglas Gregor 2325040e1266SRichard Smith // If we were given stat information, parse it so we can skip looking for 2326040e1266SRichard Smith // the file. 2327040e1266SRichard Smith if (Tok.is(MMToken::LBrace)) { 2328040e1266SRichard Smith SourceLocation LBraceLoc = consumeToken(); 23293ec6663bSDouglas Gregor 2330040e1266SRichard Smith while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) { 2331040e1266SRichard Smith enum Attribute { Size, ModTime, Unknown }; 2332040e1266SRichard Smith StringRef Str = Tok.getString(); 2333040e1266SRichard Smith SourceLocation Loc = consumeToken(); 2334040e1266SRichard Smith switch (llvm::StringSwitch<Attribute>(Str) 2335040e1266SRichard Smith .Case("size", Size) 2336040e1266SRichard Smith .Case("mtime", ModTime) 2337040e1266SRichard Smith .Default(Unknown)) { 2338040e1266SRichard Smith case Size: 2339040e1266SRichard Smith if (Header.Size) 2340040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2341040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2342040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2343040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2344040e1266SRichard Smith skipUntil(MMToken::RBrace); 2345040e1266SRichard Smith break; 2346040e1266SRichard Smith } 2347040e1266SRichard Smith Header.Size = Tok.getInteger(); 2348040e1266SRichard Smith consumeToken(); 2349040e1266SRichard Smith break; 2350040e1266SRichard Smith 2351040e1266SRichard Smith case ModTime: 2352040e1266SRichard Smith if (Header.ModTime) 2353040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2354040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2355040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2356040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2357040e1266SRichard Smith skipUntil(MMToken::RBrace); 2358040e1266SRichard Smith break; 2359040e1266SRichard Smith } 2360040e1266SRichard Smith Header.ModTime = Tok.getInteger(); 2361040e1266SRichard Smith consumeToken(); 2362040e1266SRichard Smith break; 2363040e1266SRichard Smith 2364040e1266SRichard Smith case Unknown: 2365040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_expected_header_attribute); 2366040e1266SRichard Smith skipUntil(MMToken::RBrace); 2367040e1266SRichard Smith break; 2368040e1266SRichard Smith } 23693ec6663bSDouglas Gregor } 23705257fc63SDouglas Gregor 2371040e1266SRichard Smith if (Tok.is(MMToken::RBrace)) 2372040e1266SRichard Smith consumeToken(); 2373040e1266SRichard Smith else { 2374040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 2375040e1266SRichard Smith Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 2376322f633cSDouglas Gregor HadError = true; 2377322f633cSDouglas Gregor } 23780101b540SHans Wennborg } 237925d50758SRichard Smith 23809f6020bcSBruno Cardoso Lopes bool NeedsFramework = false; 23819f6020bcSBruno Cardoso Lopes Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework); 23829f6020bcSBruno Cardoso Lopes 23839f6020bcSBruno Cardoso Lopes if (NeedsFramework && ActiveModule) 23849f6020bcSBruno Cardoso Lopes Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword) 23859f6020bcSBruno Cardoso Lopes << ActiveModule->getFullModuleName() 23869f6020bcSBruno Cardoso Lopes << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module"); 2387718292f2SDouglas Gregor } 2388718292f2SDouglas Gregor 238941f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A, 239041f81994SBen Langmuir const Module::Header *B) { 239141f81994SBen Langmuir return A->NameAsWritten.compare(B->NameAsWritten); 239241f81994SBen Langmuir } 239341f81994SBen Langmuir 23949fc8faf9SAdrian Prantl /// Parse an umbrella directory declaration. 2395524e33e1SDouglas Gregor /// 2396524e33e1SDouglas Gregor /// umbrella-dir-declaration: 2397524e33e1SDouglas Gregor /// umbrella string-literal 2398524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { 2399524e33e1SDouglas Gregor // Parse the directory name. 2400524e33e1SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2401524e33e1SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2402524e33e1SDouglas Gregor << "umbrella"; 2403524e33e1SDouglas Gregor HadError = true; 2404524e33e1SDouglas Gregor return; 2405524e33e1SDouglas Gregor } 2406524e33e1SDouglas Gregor 2407adcd0268SBenjamin Kramer std::string DirName = std::string(Tok.getString()); 2408524e33e1SDouglas Gregor SourceLocation DirNameLoc = consumeToken(); 2409524e33e1SDouglas Gregor 2410524e33e1SDouglas Gregor // Check whether we already have an umbrella. 2411524e33e1SDouglas Gregor if (ActiveModule->Umbrella) { 2412524e33e1SDouglas Gregor Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash) 2413524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2414524e33e1SDouglas Gregor HadError = true; 2415524e33e1SDouglas Gregor return; 2416524e33e1SDouglas Gregor } 2417524e33e1SDouglas Gregor 2418524e33e1SDouglas Gregor // Look for this file. 2419d2d442caSCraig Topper const DirectoryEntry *Dir = nullptr; 24208d323d15SHarlan Haskins if (llvm::sys::path::is_absolute(DirName)) { 24218d323d15SHarlan Haskins if (auto D = SourceMgr.getFileManager().getDirectory(DirName)) 24228d323d15SHarlan Haskins Dir = *D; 24238d323d15SHarlan Haskins } else { 24242c1dd271SDylan Noblesmith SmallString<128> PathName; 2425524e33e1SDouglas Gregor PathName = Directory->getName(); 2426524e33e1SDouglas Gregor llvm::sys::path::append(PathName, DirName); 24278d323d15SHarlan Haskins if (auto D = SourceMgr.getFileManager().getDirectory(PathName)) 24288d323d15SHarlan Haskins Dir = *D; 2429524e33e1SDouglas Gregor } 2430524e33e1SDouglas Gregor 2431524e33e1SDouglas Gregor if (!Dir) { 2432a0320b97SVassil Vassilev Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found) 2433524e33e1SDouglas Gregor << DirName; 2434524e33e1SDouglas Gregor return; 2435524e33e1SDouglas Gregor } 2436524e33e1SDouglas Gregor 24377ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 24387ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 24397ff29148SBen Langmuir // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the 24407ff29148SBen Langmuir // directory is relatively expensive, in practice this only applies to the 24417ff29148SBen Langmuir // uncommonly used Tcl module on Darwin platforms. 24427ff29148SBen Langmuir std::error_code EC; 24437ff29148SBen Langmuir SmallVector<Module::Header, 6> Headers; 2444fc51490bSJonas Devlieghere llvm::vfs::FileSystem &FS = 2445db8a7422SDuncan P. N. Exon Smith SourceMgr.getFileManager().getVirtualFileSystem(); 2446fc51490bSJonas Devlieghere for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E; 24477ff29148SBen Langmuir I != E && !EC; I.increment(EC)) { 24488d323d15SHarlan Haskins if (auto FE = SourceMgr.getFileManager().getFile(I->path())) { 2449adcd0268SBenjamin Kramer Module::Header Header = {std::string(I->path()), *FE}; 24507ff29148SBen Langmuir Headers.push_back(std::move(Header)); 24517ff29148SBen Langmuir } 24527ff29148SBen Langmuir } 24537ff29148SBen Langmuir 24547ff29148SBen Langmuir // Sort header paths so that the pcm doesn't depend on iteration order. 245541f81994SBen Langmuir llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders); 245641f81994SBen Langmuir 24577ff29148SBen Langmuir for (auto &Header : Headers) 24587ff29148SBen Langmuir Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader); 24597ff29148SBen Langmuir return; 24607ff29148SBen Langmuir } 24617ff29148SBen Langmuir 2462524e33e1SDouglas Gregor if (Module *OwningModule = Map.UmbrellaDirs[Dir]) { 2463524e33e1SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 2464524e33e1SDouglas Gregor << OwningModule->getFullModuleName(); 2465524e33e1SDouglas Gregor HadError = true; 2466524e33e1SDouglas Gregor return; 2467524e33e1SDouglas Gregor } 2468524e33e1SDouglas Gregor 2469524e33e1SDouglas Gregor // Record this umbrella directory. 24702b63d15fSRichard Smith Map.setUmbrellaDir(ActiveModule, Dir, DirName); 2471524e33e1SDouglas Gregor } 2472524e33e1SDouglas Gregor 24739fc8faf9SAdrian Prantl /// Parse a module export declaration. 24742b82c2a5SDouglas Gregor /// 24752b82c2a5SDouglas Gregor /// export-declaration: 24762b82c2a5SDouglas Gregor /// 'export' wildcard-module-id 24772b82c2a5SDouglas Gregor /// 24782b82c2a5SDouglas Gregor /// wildcard-module-id: 24792b82c2a5SDouglas Gregor /// identifier 24802b82c2a5SDouglas Gregor /// '*' 24812b82c2a5SDouglas Gregor /// identifier '.' wildcard-module-id 24822b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() { 24832b82c2a5SDouglas Gregor assert(Tok.is(MMToken::ExportKeyword)); 24842b82c2a5SDouglas Gregor SourceLocation ExportLoc = consumeToken(); 24852b82c2a5SDouglas Gregor 24862b82c2a5SDouglas Gregor // Parse the module-id with an optional wildcard at the end. 24872b82c2a5SDouglas Gregor ModuleId ParsedModuleId; 24882b82c2a5SDouglas Gregor bool Wildcard = false; 24892b82c2a5SDouglas Gregor do { 2490306d8920SRichard Smith // FIXME: Support string-literal module names here. 24912b82c2a5SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 2492adcd0268SBenjamin Kramer ParsedModuleId.push_back( 2493adcd0268SBenjamin Kramer std::make_pair(std::string(Tok.getString()), Tok.getLocation())); 24942b82c2a5SDouglas Gregor consumeToken(); 24952b82c2a5SDouglas Gregor 24962b82c2a5SDouglas Gregor if (Tok.is(MMToken::Period)) { 24972b82c2a5SDouglas Gregor consumeToken(); 24982b82c2a5SDouglas Gregor continue; 24992b82c2a5SDouglas Gregor } 25002b82c2a5SDouglas Gregor 25012b82c2a5SDouglas Gregor break; 25022b82c2a5SDouglas Gregor } 25032b82c2a5SDouglas Gregor 25042b82c2a5SDouglas Gregor if(Tok.is(MMToken::Star)) { 25052b82c2a5SDouglas Gregor Wildcard = true; 2506f5eedd05SDouglas Gregor consumeToken(); 25072b82c2a5SDouglas Gregor break; 25082b82c2a5SDouglas Gregor } 25092b82c2a5SDouglas Gregor 2510ba7f2f71SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_module_id); 25112b82c2a5SDouglas Gregor HadError = true; 25122b82c2a5SDouglas Gregor return; 25132b82c2a5SDouglas Gregor } while (true); 25142b82c2a5SDouglas Gregor 25152b82c2a5SDouglas Gregor Module::UnresolvedExportDecl Unresolved = { 25162b82c2a5SDouglas Gregor ExportLoc, ParsedModuleId, Wildcard 25172b82c2a5SDouglas Gregor }; 25182b82c2a5SDouglas Gregor ActiveModule->UnresolvedExports.push_back(Unresolved); 25192b82c2a5SDouglas Gregor } 25202b82c2a5SDouglas Gregor 25219fc8faf9SAdrian Prantl /// Parse a module export_as declaration. 2522f0b11de2SDouglas Gregor /// 2523f0b11de2SDouglas Gregor /// export-as-declaration: 2524f0b11de2SDouglas Gregor /// 'export_as' identifier 2525f0b11de2SDouglas Gregor void ModuleMapParser::parseExportAsDecl() { 2526f0b11de2SDouglas Gregor assert(Tok.is(MMToken::ExportAsKeyword)); 2527f0b11de2SDouglas Gregor consumeToken(); 2528f0b11de2SDouglas Gregor 2529f0b11de2SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 2530f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_module_id); 2531f0b11de2SDouglas Gregor HadError = true; 2532f0b11de2SDouglas Gregor return; 2533f0b11de2SDouglas Gregor } 2534f0b11de2SDouglas Gregor 2535f0b11de2SDouglas Gregor if (ActiveModule->Parent) { 2536f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as); 2537f0b11de2SDouglas Gregor consumeToken(); 2538f0b11de2SDouglas Gregor return; 2539f0b11de2SDouglas Gregor } 2540f0b11de2SDouglas Gregor 2541f0b11de2SDouglas Gregor if (!ActiveModule->ExportAsModule.empty()) { 2542f0b11de2SDouglas Gregor if (ActiveModule->ExportAsModule == Tok.getString()) { 2543f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as) 2544f0b11de2SDouglas Gregor << ActiveModule->Name << Tok.getString(); 2545f0b11de2SDouglas Gregor } else { 2546f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as) 2547f0b11de2SDouglas Gregor << ActiveModule->Name << ActiveModule->ExportAsModule 2548f0b11de2SDouglas Gregor << Tok.getString(); 2549f0b11de2SDouglas Gregor } 2550f0b11de2SDouglas Gregor } 2551f0b11de2SDouglas Gregor 2552adcd0268SBenjamin Kramer ActiveModule->ExportAsModule = std::string(Tok.getString()); 2553a3b5f71eSBruno Cardoso Lopes Map.addLinkAsDependency(ActiveModule); 2554a3b5f71eSBruno Cardoso Lopes 2555f0b11de2SDouglas Gregor consumeToken(); 2556f0b11de2SDouglas Gregor } 2557f0b11de2SDouglas Gregor 25589fc8faf9SAdrian Prantl /// Parse a module use declaration. 2559ba7f2f71SDaniel Jasper /// 25608f4d3ff1SRichard Smith /// use-declaration: 25618f4d3ff1SRichard Smith /// 'use' wildcard-module-id 2562ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() { 2563ba7f2f71SDaniel Jasper assert(Tok.is(MMToken::UseKeyword)); 25648f4d3ff1SRichard Smith auto KWLoc = consumeToken(); 2565ba7f2f71SDaniel Jasper // Parse the module-id. 2566ba7f2f71SDaniel Jasper ModuleId ParsedModuleId; 25673cd34c76SDaniel Jasper parseModuleId(ParsedModuleId); 2568ba7f2f71SDaniel Jasper 25698f4d3ff1SRichard Smith if (ActiveModule->Parent) 25708f4d3ff1SRichard Smith Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule); 25718f4d3ff1SRichard Smith else 2572ba7f2f71SDaniel Jasper ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId); 2573ba7f2f71SDaniel Jasper } 2574ba7f2f71SDaniel Jasper 25759fc8faf9SAdrian Prantl /// Parse a link declaration. 25766ddfca91SDouglas Gregor /// 25776ddfca91SDouglas Gregor /// module-declaration: 25786ddfca91SDouglas Gregor /// 'link' 'framework'[opt] string-literal 25796ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() { 25806ddfca91SDouglas Gregor assert(Tok.is(MMToken::LinkKeyword)); 25816ddfca91SDouglas Gregor SourceLocation LinkLoc = consumeToken(); 25826ddfca91SDouglas Gregor 25836ddfca91SDouglas Gregor // Parse the optional 'framework' keyword. 25846ddfca91SDouglas Gregor bool IsFramework = false; 25856ddfca91SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 25866ddfca91SDouglas Gregor consumeToken(); 25876ddfca91SDouglas Gregor IsFramework = true; 25886ddfca91SDouglas Gregor } 25896ddfca91SDouglas Gregor 25906ddfca91SDouglas Gregor // Parse the library name 25916ddfca91SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 25926ddfca91SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name) 25936ddfca91SDouglas Gregor << IsFramework << SourceRange(LinkLoc); 25946ddfca91SDouglas Gregor HadError = true; 25956ddfca91SDouglas Gregor return; 25966ddfca91SDouglas Gregor } 25976ddfca91SDouglas Gregor 2598adcd0268SBenjamin Kramer std::string LibraryName = std::string(Tok.getString()); 25996ddfca91SDouglas Gregor consumeToken(); 26006ddfca91SDouglas Gregor ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName, 26016ddfca91SDouglas Gregor IsFramework)); 26026ddfca91SDouglas Gregor } 26036ddfca91SDouglas Gregor 26049fc8faf9SAdrian Prantl /// Parse a configuration macro declaration. 260535b13eceSDouglas Gregor /// 260635b13eceSDouglas Gregor /// module-declaration: 260735b13eceSDouglas Gregor /// 'config_macros' attributes[opt] config-macro-list? 260835b13eceSDouglas Gregor /// 260935b13eceSDouglas Gregor /// config-macro-list: 261035b13eceSDouglas Gregor /// identifier (',' identifier)? 261135b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() { 261235b13eceSDouglas Gregor assert(Tok.is(MMToken::ConfigMacros)); 261335b13eceSDouglas Gregor SourceLocation ConfigMacrosLoc = consumeToken(); 261435b13eceSDouglas Gregor 261535b13eceSDouglas Gregor // Only top-level modules can have configuration macros. 261635b13eceSDouglas Gregor if (ActiveModule->Parent) { 261735b13eceSDouglas Gregor Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule); 261835b13eceSDouglas Gregor } 261935b13eceSDouglas Gregor 262035b13eceSDouglas Gregor // Parse the optional attributes. 262135b13eceSDouglas Gregor Attributes Attrs; 26225d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 26235d29dee0SDavide Italiano return; 26245d29dee0SDavide Italiano 262535b13eceSDouglas Gregor if (Attrs.IsExhaustive && !ActiveModule->Parent) { 262635b13eceSDouglas Gregor ActiveModule->ConfigMacrosExhaustive = true; 262735b13eceSDouglas Gregor } 262835b13eceSDouglas Gregor 262935b13eceSDouglas Gregor // If we don't have an identifier, we're done. 2630306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 263135b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) 263235b13eceSDouglas Gregor return; 263335b13eceSDouglas Gregor 263435b13eceSDouglas Gregor // Consume the first identifier. 263535b13eceSDouglas Gregor if (!ActiveModule->Parent) { 263635b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 263735b13eceSDouglas Gregor } 263835b13eceSDouglas Gregor consumeToken(); 263935b13eceSDouglas Gregor 264035b13eceSDouglas Gregor do { 264135b13eceSDouglas Gregor // If there's a comma, consume it. 264235b13eceSDouglas Gregor if (!Tok.is(MMToken::Comma)) 264335b13eceSDouglas Gregor break; 264435b13eceSDouglas Gregor consumeToken(); 264535b13eceSDouglas Gregor 264635b13eceSDouglas Gregor // We expect to see a macro name here. 2647306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 264835b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 264935b13eceSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro); 265035b13eceSDouglas Gregor break; 265135b13eceSDouglas Gregor } 265235b13eceSDouglas Gregor 265335b13eceSDouglas Gregor // Consume the macro name. 265435b13eceSDouglas Gregor if (!ActiveModule->Parent) { 265535b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 265635b13eceSDouglas Gregor } 265735b13eceSDouglas Gregor consumeToken(); 265835b13eceSDouglas Gregor } while (true); 265935b13eceSDouglas Gregor } 266035b13eceSDouglas Gregor 26619fc8faf9SAdrian Prantl /// Format a module-id into a string. 2662fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) { 2663fb912657SDouglas Gregor std::string result; 2664fb912657SDouglas Gregor { 2665fb912657SDouglas Gregor llvm::raw_string_ostream OS(result); 2666fb912657SDouglas Gregor 2667fb912657SDouglas Gregor for (unsigned I = 0, N = Id.size(); I != N; ++I) { 2668fb912657SDouglas Gregor if (I) 2669fb912657SDouglas Gregor OS << "."; 2670fb912657SDouglas Gregor OS << Id[I].first; 2671fb912657SDouglas Gregor } 2672fb912657SDouglas Gregor } 2673fb912657SDouglas Gregor 2674fb912657SDouglas Gregor return result; 2675fb912657SDouglas Gregor } 2676fb912657SDouglas Gregor 26779fc8faf9SAdrian Prantl /// Parse a conflict declaration. 2678fb912657SDouglas Gregor /// 2679fb912657SDouglas Gregor /// module-declaration: 2680fb912657SDouglas Gregor /// 'conflict' module-id ',' string-literal 2681fb912657SDouglas Gregor void ModuleMapParser::parseConflict() { 2682fb912657SDouglas Gregor assert(Tok.is(MMToken::Conflict)); 2683fb912657SDouglas Gregor SourceLocation ConflictLoc = consumeToken(); 2684fb912657SDouglas Gregor Module::UnresolvedConflict Conflict; 2685fb912657SDouglas Gregor 2686fb912657SDouglas Gregor // Parse the module-id. 2687fb912657SDouglas Gregor if (parseModuleId(Conflict.Id)) 2688fb912657SDouglas Gregor return; 2689fb912657SDouglas Gregor 2690fb912657SDouglas Gregor // Parse the ','. 2691fb912657SDouglas Gregor if (!Tok.is(MMToken::Comma)) { 2692fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma) 2693fb912657SDouglas Gregor << SourceRange(ConflictLoc); 2694fb912657SDouglas Gregor return; 2695fb912657SDouglas Gregor } 2696fb912657SDouglas Gregor consumeToken(); 2697fb912657SDouglas Gregor 2698fb912657SDouglas Gregor // Parse the message. 2699fb912657SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2700fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message) 2701fb912657SDouglas Gregor << formatModuleId(Conflict.Id); 2702fb912657SDouglas Gregor return; 2703fb912657SDouglas Gregor } 2704fb912657SDouglas Gregor Conflict.Message = Tok.getString().str(); 2705fb912657SDouglas Gregor consumeToken(); 2706fb912657SDouglas Gregor 2707fb912657SDouglas Gregor // Add this unresolved conflict. 2708fb912657SDouglas Gregor ActiveModule->UnresolvedConflicts.push_back(Conflict); 2709fb912657SDouglas Gregor } 2710fb912657SDouglas Gregor 27119fc8faf9SAdrian Prantl /// Parse an inferred module declaration (wildcard modules). 27129194a91dSDouglas Gregor /// 27139194a91dSDouglas Gregor /// module-declaration: 27149194a91dSDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt] 27159194a91dSDouglas Gregor /// { inferred-module-member* } 27169194a91dSDouglas Gregor /// 27179194a91dSDouglas Gregor /// inferred-module-member: 27189194a91dSDouglas Gregor /// 'export' '*' 27199194a91dSDouglas Gregor /// 'exclude' identifier 27209194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { 272173441091SDouglas Gregor assert(Tok.is(MMToken::Star)); 272273441091SDouglas Gregor SourceLocation StarLoc = consumeToken(); 272373441091SDouglas Gregor bool Failed = false; 272473441091SDouglas Gregor 272573441091SDouglas Gregor // Inferred modules must be submodules. 27269194a91dSDouglas Gregor if (!ActiveModule && !Framework) { 272773441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule); 272873441091SDouglas Gregor Failed = true; 272973441091SDouglas Gregor } 273073441091SDouglas Gregor 27319194a91dSDouglas Gregor if (ActiveModule) { 2732524e33e1SDouglas Gregor // Inferred modules must have umbrella directories. 27334898cde4SBen Langmuir if (!Failed && ActiveModule->IsAvailable && 27344898cde4SBen Langmuir !ActiveModule->getUmbrellaDir()) { 273573441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); 273673441091SDouglas Gregor Failed = true; 273773441091SDouglas Gregor } 273873441091SDouglas Gregor 273973441091SDouglas Gregor // Check for redefinition of an inferred module. 2740dd005f69SDouglas Gregor if (!Failed && ActiveModule->InferSubmodules) { 274173441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_redef); 2742dd005f69SDouglas Gregor if (ActiveModule->InferredSubmoduleLoc.isValid()) 2743dd005f69SDouglas Gregor Diags.Report(ActiveModule->InferredSubmoduleLoc, 274473441091SDouglas Gregor diag::note_mmap_prev_definition); 274573441091SDouglas Gregor Failed = true; 274673441091SDouglas Gregor } 274773441091SDouglas Gregor 27489194a91dSDouglas Gregor // Check for the 'framework' keyword, which is not permitted here. 27499194a91dSDouglas Gregor if (Framework) { 27509194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule); 27519194a91dSDouglas Gregor Framework = false; 27529194a91dSDouglas Gregor } 27539194a91dSDouglas Gregor } else if (Explicit) { 27549194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework); 27559194a91dSDouglas Gregor Explicit = false; 27569194a91dSDouglas Gregor } 27579194a91dSDouglas Gregor 275873441091SDouglas Gregor // If there were any problems with this inferred submodule, skip its body. 275973441091SDouglas Gregor if (Failed) { 276073441091SDouglas Gregor if (Tok.is(MMToken::LBrace)) { 276173441091SDouglas Gregor consumeToken(); 276273441091SDouglas Gregor skipUntil(MMToken::RBrace); 276373441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 276473441091SDouglas Gregor consumeToken(); 276573441091SDouglas Gregor } 276673441091SDouglas Gregor HadError = true; 276773441091SDouglas Gregor return; 276873441091SDouglas Gregor } 276973441091SDouglas Gregor 27709194a91dSDouglas Gregor // Parse optional attributes. 27714442605fSBill Wendling Attributes Attrs; 27725d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 27735d29dee0SDavide Italiano return; 27749194a91dSDouglas Gregor 27759194a91dSDouglas Gregor if (ActiveModule) { 277673441091SDouglas Gregor // Note that we have an inferred submodule. 2777dd005f69SDouglas Gregor ActiveModule->InferSubmodules = true; 2778dd005f69SDouglas Gregor ActiveModule->InferredSubmoduleLoc = StarLoc; 2779dd005f69SDouglas Gregor ActiveModule->InferExplicitSubmodules = Explicit; 27809194a91dSDouglas Gregor } else { 27819194a91dSDouglas Gregor // We'll be inferring framework modules for this directory. 27829194a91dSDouglas Gregor Map.InferredDirectories[Directory].InferModules = true; 2783c1d88ea5SBen Langmuir Map.InferredDirectories[Directory].Attrs = Attrs; 2784beee15e7SBen Langmuir Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile; 2785131daca0SRichard Smith // FIXME: Handle the 'framework' keyword. 27869194a91dSDouglas Gregor } 278773441091SDouglas Gregor 278873441091SDouglas Gregor // Parse the opening brace. 278973441091SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 279073441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard); 279173441091SDouglas Gregor HadError = true; 279273441091SDouglas Gregor return; 279373441091SDouglas Gregor } 279473441091SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 279573441091SDouglas Gregor 279673441091SDouglas Gregor // Parse the body of the inferred submodule. 279773441091SDouglas Gregor bool Done = false; 279873441091SDouglas Gregor do { 279973441091SDouglas Gregor switch (Tok.Kind) { 280073441091SDouglas Gregor case MMToken::EndOfFile: 280173441091SDouglas Gregor case MMToken::RBrace: 280273441091SDouglas Gregor Done = true; 280373441091SDouglas Gregor break; 280473441091SDouglas Gregor 2805afd1b1c9SEugene Zelenko case MMToken::ExcludeKeyword: 28069194a91dSDouglas Gregor if (ActiveModule) { 28079194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2808d2d442caSCraig Topper << (ActiveModule != nullptr); 28099194a91dSDouglas Gregor consumeToken(); 28109194a91dSDouglas Gregor break; 28119194a91dSDouglas Gregor } 28129194a91dSDouglas Gregor 28139194a91dSDouglas Gregor consumeToken(); 2814306d8920SRichard Smith // FIXME: Support string-literal module names here. 28159194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 28169194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name); 28179194a91dSDouglas Gregor break; 28189194a91dSDouglas Gregor } 28199194a91dSDouglas Gregor 2820adcd0268SBenjamin Kramer Map.InferredDirectories[Directory].ExcludedModules.push_back( 2821adcd0268SBenjamin Kramer std::string(Tok.getString())); 28229194a91dSDouglas Gregor consumeToken(); 28239194a91dSDouglas Gregor break; 28249194a91dSDouglas Gregor 28259194a91dSDouglas Gregor case MMToken::ExportKeyword: 28269194a91dSDouglas Gregor if (!ActiveModule) { 28279194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2828d2d442caSCraig Topper << (ActiveModule != nullptr); 28299194a91dSDouglas Gregor consumeToken(); 28309194a91dSDouglas Gregor break; 28319194a91dSDouglas Gregor } 28329194a91dSDouglas Gregor 283373441091SDouglas Gregor consumeToken(); 283473441091SDouglas Gregor if (Tok.is(MMToken::Star)) 2835dd005f69SDouglas Gregor ActiveModule->InferExportWildcard = true; 283673441091SDouglas Gregor else 283773441091SDouglas Gregor Diags.Report(Tok.getLocation(), 283873441091SDouglas Gregor diag::err_mmap_expected_export_wildcard); 283973441091SDouglas Gregor consumeToken(); 284073441091SDouglas Gregor break; 284173441091SDouglas Gregor 284273441091SDouglas Gregor case MMToken::ExplicitKeyword: 284373441091SDouglas Gregor case MMToken::ModuleKeyword: 284473441091SDouglas Gregor case MMToken::HeaderKeyword: 2845b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 284673441091SDouglas Gregor case MMToken::UmbrellaKeyword: 284773441091SDouglas Gregor default: 28489194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2849d2d442caSCraig Topper << (ActiveModule != nullptr); 285073441091SDouglas Gregor consumeToken(); 285173441091SDouglas Gregor break; 285273441091SDouglas Gregor } 285373441091SDouglas Gregor } while (!Done); 285473441091SDouglas Gregor 285573441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 285673441091SDouglas Gregor consumeToken(); 285773441091SDouglas Gregor else { 285873441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 285973441091SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 286073441091SDouglas Gregor HadError = true; 286173441091SDouglas Gregor } 286273441091SDouglas Gregor } 286373441091SDouglas Gregor 28649fc8faf9SAdrian Prantl /// Parse optional attributes. 28659194a91dSDouglas Gregor /// 28669194a91dSDouglas Gregor /// attributes: 28679194a91dSDouglas Gregor /// attribute attributes 28689194a91dSDouglas Gregor /// attribute 28699194a91dSDouglas Gregor /// 28709194a91dSDouglas Gregor /// attribute: 28719194a91dSDouglas Gregor /// [ identifier ] 28729194a91dSDouglas Gregor /// 28739194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes. 28749194a91dSDouglas Gregor /// 28759194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise. 28764442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { 28779194a91dSDouglas Gregor bool HadError = false; 28789194a91dSDouglas Gregor 28799194a91dSDouglas Gregor while (Tok.is(MMToken::LSquare)) { 28809194a91dSDouglas Gregor // Consume the '['. 28819194a91dSDouglas Gregor SourceLocation LSquareLoc = consumeToken(); 28829194a91dSDouglas Gregor 28839194a91dSDouglas Gregor // Check whether we have an attribute name here. 28849194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 28859194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute); 28869194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 28879194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 28889194a91dSDouglas Gregor consumeToken(); 28899194a91dSDouglas Gregor HadError = true; 28909194a91dSDouglas Gregor } 28919194a91dSDouglas Gregor 28929194a91dSDouglas Gregor // Decode the attribute name. 28939194a91dSDouglas Gregor AttributeKind Attribute 28949194a91dSDouglas Gregor = llvm::StringSwitch<AttributeKind>(Tok.getString()) 289535b13eceSDouglas Gregor .Case("exhaustive", AT_exhaustive) 289677944868SRichard Smith .Case("extern_c", AT_extern_c) 2897ed84df00SBruno Cardoso Lopes .Case("no_undeclared_includes", AT_no_undeclared_includes) 28989194a91dSDouglas Gregor .Case("system", AT_system) 28999194a91dSDouglas Gregor .Default(AT_unknown); 29009194a91dSDouglas Gregor switch (Attribute) { 29019194a91dSDouglas Gregor case AT_unknown: 29029194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute) 29039194a91dSDouglas Gregor << Tok.getString(); 29049194a91dSDouglas Gregor break; 29059194a91dSDouglas Gregor 29069194a91dSDouglas Gregor case AT_system: 29079194a91dSDouglas Gregor Attrs.IsSystem = true; 29089194a91dSDouglas Gregor break; 290935b13eceSDouglas Gregor 291077944868SRichard Smith case AT_extern_c: 291177944868SRichard Smith Attrs.IsExternC = true; 291277944868SRichard Smith break; 291377944868SRichard Smith 291435b13eceSDouglas Gregor case AT_exhaustive: 291535b13eceSDouglas Gregor Attrs.IsExhaustive = true; 291635b13eceSDouglas Gregor break; 2917ed84df00SBruno Cardoso Lopes 2918ed84df00SBruno Cardoso Lopes case AT_no_undeclared_includes: 2919ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes = true; 2920ed84df00SBruno Cardoso Lopes break; 29219194a91dSDouglas Gregor } 29229194a91dSDouglas Gregor consumeToken(); 29239194a91dSDouglas Gregor 29249194a91dSDouglas Gregor // Consume the ']'. 29259194a91dSDouglas Gregor if (!Tok.is(MMToken::RSquare)) { 29269194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare); 29279194a91dSDouglas Gregor Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match); 29289194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 29299194a91dSDouglas Gregor HadError = true; 29309194a91dSDouglas Gregor } 29319194a91dSDouglas Gregor 29329194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 29339194a91dSDouglas Gregor consumeToken(); 29349194a91dSDouglas Gregor } 29359194a91dSDouglas Gregor 29369194a91dSDouglas Gregor return HadError; 29379194a91dSDouglas Gregor } 29389194a91dSDouglas Gregor 29399fc8faf9SAdrian Prantl /// Parse a module map file. 2940718292f2SDouglas Gregor /// 2941718292f2SDouglas Gregor /// module-map-file: 2942718292f2SDouglas Gregor /// module-declaration* 2943718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 2944718292f2SDouglas Gregor do { 2945718292f2SDouglas Gregor switch (Tok.Kind) { 2946718292f2SDouglas Gregor case MMToken::EndOfFile: 2947718292f2SDouglas Gregor return HadError; 2948718292f2SDouglas Gregor 2949e7ab3669SDouglas Gregor case MMToken::ExplicitKeyword: 295097292843SDaniel Jasper case MMToken::ExternKeyword: 2951718292f2SDouglas Gregor case MMToken::ModuleKeyword: 2952755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 2953718292f2SDouglas Gregor parseModuleDecl(); 2954718292f2SDouglas Gregor break; 2955718292f2SDouglas Gregor 29561fb5c3a6SDouglas Gregor case MMToken::Comma: 295735b13eceSDouglas Gregor case MMToken::ConfigMacros: 2958fb912657SDouglas Gregor case MMToken::Conflict: 2959a3feee2aSRichard Smith case MMToken::Exclaim: 296059527666SDouglas Gregor case MMToken::ExcludeKeyword: 29612b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 2962f0b11de2SDouglas Gregor case MMToken::ExportAsKeyword: 2963718292f2SDouglas Gregor case MMToken::HeaderKeyword: 2964718292f2SDouglas Gregor case MMToken::Identifier: 2965718292f2SDouglas Gregor case MMToken::LBrace: 29666ddfca91SDouglas Gregor case MMToken::LinkKeyword: 2967a686e1b0SDouglas Gregor case MMToken::LSquare: 29682b82c2a5SDouglas Gregor case MMToken::Period: 2969b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 2970718292f2SDouglas Gregor case MMToken::RBrace: 2971a686e1b0SDouglas Gregor case MMToken::RSquare: 29721fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 29732b82c2a5SDouglas Gregor case MMToken::Star: 2974718292f2SDouglas Gregor case MMToken::StringLiteral: 2975040e1266SRichard Smith case MMToken::IntegerLiteral: 2976b8afebe2SRichard Smith case MMToken::TextualKeyword: 2977718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 2978ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 2979718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 2980718292f2SDouglas Gregor HadError = true; 2981718292f2SDouglas Gregor consumeToken(); 2982718292f2SDouglas Gregor break; 2983718292f2SDouglas Gregor } 2984718292f2SDouglas Gregor } while (true); 2985718292f2SDouglas Gregor } 2986718292f2SDouglas Gregor 29879acb99e3SRichard Smith bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem, 2988c192d194SBruno Cardoso Lopes const DirectoryEntry *Dir, FileID ID, 29898128f332SRichard Smith unsigned *Offset, 2990ae6df27eSRichard Smith SourceLocation ExternModuleLoc) { 29918128f332SRichard Smith assert(Target && "Missing target information"); 29924ddf2221SDouglas Gregor llvm::DenseMap<const FileEntry *, bool>::iterator Known 29934ddf2221SDouglas Gregor = ParsedModuleMap.find(File); 29944ddf2221SDouglas Gregor if (Known != ParsedModuleMap.end()) 29954ddf2221SDouglas Gregor return Known->second; 29964ddf2221SDouglas Gregor 29978128f332SRichard Smith // If the module map file wasn't already entered, do so now. 29988128f332SRichard Smith if (ID.isInvalid()) { 2999f3f84616SRichard Smith auto FileCharacter = 3000f3f84616SRichard Smith IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap; 30018128f332SRichard Smith ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter); 30028128f332SRichard Smith } 30038128f332SRichard Smith 30048128f332SRichard Smith assert(Target && "Missing target information"); 3005b03ae743SDuncan P. N. Exon Smith llvm::Optional<llvm::MemoryBufferRef> Buffer = SourceMgr.getBufferOrNone(ID); 3006718292f2SDouglas Gregor if (!Buffer) 30074ddf2221SDouglas Gregor return ParsedModuleMap[File] = true; 30088128f332SRichard Smith assert((!Offset || *Offset <= Buffer->getBufferSize()) && 30098128f332SRichard Smith "invalid buffer offset"); 3010718292f2SDouglas Gregor 3011718292f2SDouglas Gregor // Parse this module map file. 30128128f332SRichard Smith Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts, 30138128f332SRichard Smith Buffer->getBufferStart(), 30148128f332SRichard Smith Buffer->getBufferStart() + (Offset ? *Offset : 0), 30158128f332SRichard Smith Buffer->getBufferEnd()); 30162a6edb30SRichard Smith SourceLocation Start = L.getSourceLocation(); 3017beee15e7SBen Langmuir ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir, 3018c192d194SBruno Cardoso Lopes IsSystem); 3019718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 30204ddf2221SDouglas Gregor ParsedModuleMap[File] = Result; 30212a6edb30SRichard Smith 30228128f332SRichard Smith if (Offset) { 30238128f332SRichard Smith auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation()); 30248128f332SRichard Smith assert(Loc.first == ID && "stopped in a different file?"); 30258128f332SRichard Smith *Offset = Loc.second; 30268128f332SRichard Smith } 30278128f332SRichard Smith 30282a6edb30SRichard Smith // Notify callbacks that we parsed it. 30292a6edb30SRichard Smith for (const auto &Cb : Callbacks) 30302a6edb30SRichard Smith Cb->moduleMapFileRead(Start, *File, IsSystem); 30318587dfd9SBruno Cardoso Lopes 3032718292f2SDouglas Gregor return Result; 3033718292f2SDouglas Gregor } 3034