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 1749f6020bcSBruno Cardoso Lopes const FileEntry *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 181040e1266SRichard Smith auto GetFile = [&](StringRef Filename) -> const FileEntry * { 1828d323d15SHarlan Haskins auto File = SourceMgr.getFileManager().getFile(Filename); 183040e1266SRichard Smith if (!File || 1848d323d15SHarlan Haskins (Header.Size && (*File)->getSize() != *Header.Size) || 1858d323d15SHarlan Haskins (Header.ModTime && (*File)->getModificationTime() != *Header.ModTime)) 186040e1266SRichard Smith return nullptr; 1878d323d15SHarlan Haskins return *File; 188040e1266SRichard Smith }; 189040e1266SRichard Smith 1909f6020bcSBruno Cardoso Lopes auto GetFrameworkFile = [&]() -> const FileEntry * { 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); 198040e1266SRichard 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); 2309f6020bcSBruno Cardoso Lopes 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 } 2449f6020bcSBruno Cardoso Lopes return nullptr; 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; 2549f6020bcSBruno Cardoso Lopes if (const FileEntry *File = 2559f6020bcSBruno Cardoso Lopes findHeader(Mod, Header, RelativePathName, NeedsFramework)) { 256040e1266SRichard Smith if (Header.IsUmbrella) { 257040e1266SRichard Smith const DirectoryEntry *UmbrellaDir = File->getDir(); 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. 263040e1266SRichard Smith setUmbrellaHeader(Mod, File, RelativePathName.str()); 264040e1266SRichard Smith } else { 265adcd0268SBenjamin Kramer 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) 285040e1266SRichard Smith Mod->markUnavailable(); 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 39092669ee4SDaniel Jasper ModuleMap::HeadersMap::iterator 39192669ee4SDaniel Jasper ModuleMap::findKnownHeader(const FileEntry *File) { 392040e1266SRichard Smith resolveHeaderDirectives(File); 39359527666SDouglas Gregor HeadersMap::iterator Known = Headers.find(File); 39447972afdSRichard Smith if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && 39547972afdSRichard Smith Known == Headers.end() && File->getDir() == BuiltinIncludeDir && 396ba1b5c98SBruno Cardoso Lopes ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()))) { 3974eaf0a6cSDaniel Jasper HeaderInfo.loadTopLevelSystemModules(); 39892669ee4SDaniel Jasper return Headers.find(File); 3994eaf0a6cSDaniel Jasper } 40092669ee4SDaniel Jasper return Known; 40192669ee4SDaniel Jasper } 40292669ee4SDaniel Jasper 4034469138eSBen Langmuir ModuleMap::KnownHeader 4044469138eSBen Langmuir ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File, 4054469138eSBen Langmuir SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) { 40647972afdSRichard Smith if (UmbrellaDirs.empty()) 407afd1b1c9SEugene Zelenko return {}; 40847972afdSRichard Smith 4094469138eSBen Langmuir const DirectoryEntry *Dir = File->getDir(); 4104469138eSBen Langmuir assert(Dir && "file in no directory"); 4114469138eSBen Langmuir 4124469138eSBen Langmuir // Note: as an egregious but useful hack we use the real path here, because 4134469138eSBen Langmuir // frameworks moving from top-level frameworks to embedded frameworks tend 4144469138eSBen Langmuir // to be symlinked from the top-level location to the embedded location, 4154469138eSBen Langmuir // and we need to resolve lookups as if we had found the embedded location. 4164469138eSBen Langmuir StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir); 4174469138eSBen Langmuir 4184469138eSBen Langmuir // Keep walking up the directory hierarchy, looking for a directory with 4194469138eSBen Langmuir // an umbrella header. 4204469138eSBen Langmuir do { 4214469138eSBen Langmuir auto KnownDir = UmbrellaDirs.find(Dir); 4224469138eSBen Langmuir if (KnownDir != UmbrellaDirs.end()) 4234469138eSBen Langmuir return KnownHeader(KnownDir->second, NormalHeader); 4244469138eSBen Langmuir 4254469138eSBen Langmuir IntermediateDirs.push_back(Dir); 4264469138eSBen Langmuir 4274469138eSBen Langmuir // Retrieve our parent path. 4284469138eSBen Langmuir DirName = llvm::sys::path::parent_path(DirName); 4294469138eSBen Langmuir if (DirName.empty()) 4304469138eSBen Langmuir break; 4314469138eSBen Langmuir 4324469138eSBen Langmuir // Resolve the parent path to a directory entry. 4338d323d15SHarlan Haskins if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName)) 4348d323d15SHarlan Haskins Dir = *DirEntry; 4358d323d15SHarlan Haskins else 4368d323d15SHarlan Haskins Dir = nullptr; 4374469138eSBen Langmuir } while (Dir); 438afd1b1c9SEugene Zelenko return {}; 4394469138eSBen Langmuir } 4404469138eSBen Langmuir 44192669ee4SDaniel Jasper static bool violatesPrivateInclude(Module *RequestingModule, 44292669ee4SDaniel Jasper const FileEntry *IncFileEnt, 4434eb8393cSRichard Smith ModuleMap::KnownHeader Header) { 44492669ee4SDaniel Jasper #ifndef NDEBUG 4454eb8393cSRichard Smith if (Header.getRole() & ModuleMap::PrivateHeader) { 44692669ee4SDaniel Jasper // Check for consistency between the module header role 44792669ee4SDaniel Jasper // as obtained from the lookup and as obtained from the module. 44892669ee4SDaniel Jasper // This check is not cheap, so enable it only for debugging. 4492708e520SRichard Smith bool IsPrivate = false; 4502708e520SRichard Smith SmallVectorImpl<Module::Header> *HeaderList[] = { 4514eb8393cSRichard Smith &Header.getModule()->Headers[Module::HK_Private], 4524eb8393cSRichard Smith &Header.getModule()->Headers[Module::HK_PrivateTextual]}; 4532708e520SRichard Smith for (auto *Hs : HeaderList) 4542708e520SRichard Smith IsPrivate |= 4552708e520SRichard Smith std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) { 4563c1a41adSRichard Smith return H.Entry == IncFileEnt; 4572708e520SRichard Smith }) != Hs->end(); 4584eb8393cSRichard Smith assert(IsPrivate && "inconsistent headers and roles"); 45900bc95ecSRichard Smith } 46092669ee4SDaniel Jasper #endif 4614eb8393cSRichard Smith return !Header.isAccessibleFrom(RequestingModule); 46292669ee4SDaniel Jasper } 46392669ee4SDaniel Jasper 46471e1a64fSBen Langmuir static Module *getTopLevelOrNull(Module *M) { 46571e1a64fSBen Langmuir return M ? M->getTopLevelModule() : nullptr; 46671e1a64fSBen Langmuir } 46771e1a64fSBen Langmuir 46892669ee4SDaniel Jasper void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, 4698d4e90b3SRichard Smith bool RequestingModuleIsModuleInterface, 47092669ee4SDaniel Jasper SourceLocation FilenameLoc, 47192669ee4SDaniel Jasper StringRef Filename, 47292669ee4SDaniel Jasper const FileEntry *File) { 47392669ee4SDaniel Jasper // No errors for indirect modules. This may be a bit of a problem for modules 47492669ee4SDaniel Jasper // with no source files. 47571e1a64fSBen Langmuir if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule)) 47692669ee4SDaniel Jasper return; 47792669ee4SDaniel Jasper 478040e1266SRichard Smith if (RequestingModule) { 47992669ee4SDaniel Jasper resolveUses(RequestingModule, /*Complain=*/false); 480040e1266SRichard Smith resolveHeaderDirectives(RequestingModule); 481040e1266SRichard Smith } 48292669ee4SDaniel Jasper 48371e1a64fSBen Langmuir bool Excluded = false; 484d2d442caSCraig Topper Module *Private = nullptr; 485d2d442caSCraig Topper Module *NotUsed = nullptr; 48671e1a64fSBen Langmuir 48771e1a64fSBen Langmuir HeadersMap::iterator Known = findKnownHeader(File); 48871e1a64fSBen Langmuir if (Known != Headers.end()) { 48971e1a64fSBen Langmuir for (const KnownHeader &Header : Known->second) { 49092669ee4SDaniel Jasper // Remember private headers for later printing of a diagnostic. 4914eb8393cSRichard Smith if (violatesPrivateInclude(RequestingModule, File, Header)) { 49271e1a64fSBen Langmuir Private = Header.getModule(); 49392669ee4SDaniel Jasper continue; 49492669ee4SDaniel Jasper } 49592669ee4SDaniel Jasper 49692669ee4SDaniel Jasper // If uses need to be specified explicitly, we are only allowed to return 49792669ee4SDaniel Jasper // modules that are explicitly used by the requesting module. 49892669ee4SDaniel Jasper if (RequestingModule && LangOpts.ModulesDeclUse && 4998f4d3ff1SRichard Smith !RequestingModule->directlyUses(Header.getModule())) { 50071e1a64fSBen Langmuir NotUsed = Header.getModule(); 50192669ee4SDaniel Jasper continue; 50292669ee4SDaniel Jasper } 50392669ee4SDaniel Jasper 50492669ee4SDaniel Jasper // We have found a module that we can happily use. 50592669ee4SDaniel Jasper return; 50692669ee4SDaniel Jasper } 507feb54b6dSRichard Smith 508feb54b6dSRichard Smith Excluded = true; 50971e1a64fSBen Langmuir } 51092669ee4SDaniel Jasper 51192669ee4SDaniel Jasper // We have found a header, but it is private. 512d2d442caSCraig Topper if (Private) { 51311152dd5SRichard Smith Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module) 51492669ee4SDaniel Jasper << Filename; 51592669ee4SDaniel Jasper return; 51692669ee4SDaniel Jasper } 51792669ee4SDaniel Jasper 51892669ee4SDaniel Jasper // We have found a module, but we don't use it. 519d2d442caSCraig Topper if (NotUsed) { 52011152dd5SRichard Smith Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) 5214ea330c8SDaniel Jasper << RequestingModule->getTopLevelModule()->Name << Filename; 52292669ee4SDaniel Jasper return; 52392669ee4SDaniel Jasper } 52492669ee4SDaniel Jasper 52571e1a64fSBen Langmuir if (Excluded || isHeaderInUmbrellaDirs(File)) 52671e1a64fSBen Langmuir return; 52771e1a64fSBen Langmuir 52871e1a64fSBen Langmuir // At this point, only non-modular includes remain. 52971e1a64fSBen Langmuir 5305904c41eSBenjamin Kramer if (RequestingModule && LangOpts.ModulesStrictDeclUse) { 53111152dd5SRichard Smith Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) 5324ea330c8SDaniel Jasper << RequestingModule->getTopLevelModule()->Name << Filename; 533a67e4d32SManman Ren } else if (RequestingModule && RequestingModuleIsModuleInterface && 534a67e4d32SManman Ren LangOpts.isCompilingModule()) { 535a67e4d32SManman Ren // Do not diagnose when we are not compiling a module. 53671e1a64fSBen Langmuir diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ? 53771e1a64fSBen Langmuir diag::warn_non_modular_include_in_framework_module : 53871e1a64fSBen Langmuir diag::warn_non_modular_include_in_module; 53970a7738fSManman Ren Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName() 54070a7738fSManman Ren << File->getName(); 54171e1a64fSBen Langmuir } 54292669ee4SDaniel Jasper } 54392669ee4SDaniel Jasper 544ec87a50aSRichard Smith static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New, 545ec87a50aSRichard Smith const ModuleMap::KnownHeader &Old) { 5468b7c0398SSean Silva // Prefer available modules. 5478b7c0398SSean Silva if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable()) 5488b7c0398SSean Silva return true; 5498b7c0398SSean Silva 550ec87a50aSRichard Smith // Prefer a public header over a private header. 551ec87a50aSRichard Smith if ((New.getRole() & ModuleMap::PrivateHeader) != 552ec87a50aSRichard Smith (Old.getRole() & ModuleMap::PrivateHeader)) 553ec87a50aSRichard Smith return !(New.getRole() & ModuleMap::PrivateHeader); 554ec87a50aSRichard Smith 555ec87a50aSRichard Smith // Prefer a non-textual header over a textual header. 556ec87a50aSRichard Smith if ((New.getRole() & ModuleMap::TextualHeader) != 557ec87a50aSRichard Smith (Old.getRole() & ModuleMap::TextualHeader)) 558ec87a50aSRichard Smith return !(New.getRole() & ModuleMap::TextualHeader); 559ec87a50aSRichard Smith 560ec87a50aSRichard Smith // Don't have a reason to choose between these. Just keep the first one. 561ec87a50aSRichard Smith return false; 562ec87a50aSRichard Smith } 563ec87a50aSRichard Smith 564ed84df00SBruno Cardoso Lopes ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File, 565ed84df00SBruno Cardoso Lopes bool AllowTextual) { 566306d8920SRichard Smith auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader { 567ed84df00SBruno Cardoso Lopes if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader) 568afd1b1c9SEugene Zelenko return {}; 569306d8920SRichard Smith return R; 570306d8920SRichard Smith }; 571306d8920SRichard Smith 5724881e8b2SSean Silva HeadersMap::iterator Known = findKnownHeader(File); 5731fb5c3a6SDouglas Gregor if (Known != Headers.end()) { 574202210b3SRichard Smith ModuleMap::KnownHeader Result; 57597da9178SDaniel Jasper // Iterate over all modules that 'File' is part of to find the best fit. 5764881e8b2SSean Silva for (KnownHeader &H : Known->second) { 5777e82e019SRichard Smith // Prefer a header from the source module over all others. 5787e82e019SRichard Smith if (H.getModule()->getTopLevelModule() == SourceModule) 5792f633e7cSRichard Smith return MakeResult(H); 5804881e8b2SSean Silva if (!Result || isBetterKnownHeader(H, Result)) 5814881e8b2SSean Silva Result = H; 58297da9178SDaniel Jasper } 583306d8920SRichard Smith return MakeResult(Result); 5841fb5c3a6SDouglas Gregor } 585ab0c8a84SDouglas Gregor 586386bb073SRichard Smith return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File)); 587386bb073SRichard Smith } 588386bb073SRichard Smith 589386bb073SRichard Smith ModuleMap::KnownHeader 590386bb073SRichard Smith ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) { 591386bb073SRichard Smith assert(!Headers.count(File) && "already have a module for this header"); 592386bb073SRichard Smith 593f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs; 5944469138eSBen Langmuir KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs); 5954469138eSBen Langmuir if (H) { 5964469138eSBen Langmuir Module *Result = H.getModule(); 597930a85ccSDouglas Gregor 598930a85ccSDouglas Gregor // Search up the module stack until we find a module with an umbrella 59973141fa9SDouglas Gregor // directory. 600930a85ccSDouglas Gregor Module *UmbrellaModule = Result; 60173141fa9SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 602930a85ccSDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 603930a85ccSDouglas Gregor 604930a85ccSDouglas Gregor if (UmbrellaModule->InferSubmodules) { 6059d6448b1SBen Langmuir const FileEntry *UmbrellaModuleMap = 6069d6448b1SBen Langmuir getModuleMapFileForUniquing(UmbrellaModule); 6079d6448b1SBen Langmuir 608a89c5ac4SDouglas Gregor // Infer submodules for each of the directories we found between 609a89c5ac4SDouglas Gregor // the directory of the umbrella header and the directory where 610a89c5ac4SDouglas Gregor // the actual header is located. 6119458f82dSDouglas Gregor bool Explicit = UmbrellaModule->InferExplicitSubmodules; 6129458f82dSDouglas Gregor 6137033127bSDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 614a89c5ac4SDouglas Gregor // Find or create the module that corresponds to this directory name. 615056396aeSDouglas Gregor SmallString<32> NameBuf; 616056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 6174469138eSBen Langmuir llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf); 6189d6448b1SBen Langmuir Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 6199d6448b1SBen Langmuir Explicit).first; 6209d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = UmbrellaModuleMap; 621ffbafa2aSBen Langmuir Result->IsInferred = true; 622a89c5ac4SDouglas Gregor 623a89c5ac4SDouglas Gregor // Associate the module and the directory. 624a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I-1]] = Result; 625a89c5ac4SDouglas Gregor 626a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 627a89c5ac4SDouglas Gregor // wildcard to the set of exports. 628930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 629d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 630a89c5ac4SDouglas Gregor } 631a89c5ac4SDouglas Gregor 632a89c5ac4SDouglas Gregor // Infer a submodule with the same name as this header file. 633056396aeSDouglas Gregor SmallString<32> NameBuf; 634056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 635056396aeSDouglas Gregor llvm::sys::path::stem(File->getName()), NameBuf); 6369d6448b1SBen Langmuir Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 6379d6448b1SBen Langmuir Explicit).first; 6389d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = UmbrellaModuleMap; 639ffbafa2aSBen Langmuir Result->IsInferred = true; 6403c5305c1SArgyrios Kyrtzidis Result->addTopHeader(File); 641a89c5ac4SDouglas Gregor 642a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 643a89c5ac4SDouglas Gregor // wildcard to the set of exports. 644930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 645d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 646a89c5ac4SDouglas Gregor } else { 647a89c5ac4SDouglas Gregor // Record each of the directories we stepped through as being part of 648a89c5ac4SDouglas Gregor // the module we found, since the umbrella header covers them all. 649a89c5ac4SDouglas Gregor for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I) 650a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I]] = Result; 651a89c5ac4SDouglas Gregor } 652a89c5ac4SDouglas Gregor 653386bb073SRichard Smith KnownHeader Header(Result, NormalHeader); 654386bb073SRichard Smith Headers[File].push_back(Header); 655386bb073SRichard Smith return Header; 656a89c5ac4SDouglas Gregor } 657a89c5ac4SDouglas Gregor 658afd1b1c9SEugene Zelenko return {}; 659ab0c8a84SDouglas Gregor } 660ab0c8a84SDouglas Gregor 661386bb073SRichard Smith ArrayRef<ModuleMap::KnownHeader> 662386bb073SRichard Smith ModuleMap::findAllModulesForHeader(const FileEntry *File) const { 663040e1266SRichard Smith resolveHeaderDirectives(File); 664386bb073SRichard Smith auto It = Headers.find(File); 665386bb073SRichard Smith if (It == Headers.end()) 666386bb073SRichard Smith return None; 667386bb073SRichard Smith return It->second; 668386bb073SRichard Smith } 669386bb073SRichard Smith 670e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const { 671d2d442caSCraig Topper return isHeaderUnavailableInModule(Header, nullptr); 67250996ce1SRichard Smith } 67350996ce1SRichard Smith 67462bcd925SDmitri Gribenko bool 67562bcd925SDmitri Gribenko ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, 67662bcd925SDmitri Gribenko const Module *RequestingModule) const { 677040e1266SRichard Smith resolveHeaderDirectives(Header); 678e4412640SArgyrios Kyrtzidis HeadersMap::const_iterator Known = Headers.find(Header); 67997da9178SDaniel Jasper if (Known != Headers.end()) { 68097da9178SDaniel Jasper for (SmallVectorImpl<KnownHeader>::const_iterator 68197da9178SDaniel Jasper I = Known->second.begin(), 68297da9178SDaniel Jasper E = Known->second.end(); 68397da9178SDaniel Jasper I != E; ++I) { 684052d95a6SBruno Cardoso Lopes 685052d95a6SBruno Cardoso Lopes if (I->isAvailable() && 686052d95a6SBruno Cardoso Lopes (!RequestingModule || 687052d95a6SBruno Cardoso Lopes I->getModule()->isSubModuleOf(RequestingModule))) { 688052d95a6SBruno Cardoso Lopes // When no requesting module is available, the caller is looking if a 689052d95a6SBruno Cardoso Lopes // header is part a module by only looking into the module map. This is 690052d95a6SBruno Cardoso Lopes // done by warn_uncovered_module_header checks; don't consider textual 691052d95a6SBruno Cardoso Lopes // headers part of it in this mode, otherwise we get misleading warnings 692052d95a6SBruno Cardoso Lopes // that a umbrella header is not including a textual header. 693052d95a6SBruno Cardoso Lopes if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader) 694052d95a6SBruno Cardoso Lopes continue; 69597da9178SDaniel Jasper return false; 69697da9178SDaniel Jasper } 697052d95a6SBruno Cardoso Lopes } 69897da9178SDaniel Jasper return true; 69997da9178SDaniel Jasper } 7001fb5c3a6SDouglas Gregor 7011fb5c3a6SDouglas Gregor const DirectoryEntry *Dir = Header->getDir(); 702f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs; 7031fb5c3a6SDouglas Gregor StringRef DirName = Dir->getName(); 7041fb5c3a6SDouglas Gregor 70550996ce1SRichard Smith auto IsUnavailable = [&](const Module *M) { 70650996ce1SRichard Smith return !M->isAvailable() && (!RequestingModule || 70750996ce1SRichard Smith M->isSubModuleOf(RequestingModule)); 70850996ce1SRichard Smith }; 70950996ce1SRichard Smith 7101fb5c3a6SDouglas Gregor // Keep walking up the directory hierarchy, looking for a directory with 7111fb5c3a6SDouglas Gregor // an umbrella header. 7121fb5c3a6SDouglas Gregor do { 713e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir 7141fb5c3a6SDouglas Gregor = UmbrellaDirs.find(Dir); 7151fb5c3a6SDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 7161fb5c3a6SDouglas Gregor Module *Found = KnownDir->second; 71750996ce1SRichard Smith if (IsUnavailable(Found)) 7181fb5c3a6SDouglas Gregor return true; 7191fb5c3a6SDouglas Gregor 7201fb5c3a6SDouglas Gregor // Search up the module stack until we find a module with an umbrella 7211fb5c3a6SDouglas Gregor // directory. 7221fb5c3a6SDouglas Gregor Module *UmbrellaModule = Found; 7231fb5c3a6SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 7241fb5c3a6SDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 7251fb5c3a6SDouglas Gregor 7261fb5c3a6SDouglas Gregor if (UmbrellaModule->InferSubmodules) { 7271fb5c3a6SDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 7281fb5c3a6SDouglas Gregor // Find or create the module that corresponds to this directory name. 729056396aeSDouglas Gregor SmallString<32> NameBuf; 730056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 731056396aeSDouglas Gregor llvm::sys::path::stem(SkippedDirs[I-1]->getName()), 732056396aeSDouglas Gregor NameBuf); 7331fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 7341fb5c3a6SDouglas Gregor if (!Found) 7351fb5c3a6SDouglas Gregor return false; 73650996ce1SRichard Smith if (IsUnavailable(Found)) 7371fb5c3a6SDouglas Gregor return true; 7381fb5c3a6SDouglas Gregor } 7391fb5c3a6SDouglas Gregor 7401fb5c3a6SDouglas Gregor // Infer a submodule with the same name as this header file. 741056396aeSDouglas Gregor SmallString<32> NameBuf; 742056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 743056396aeSDouglas Gregor llvm::sys::path::stem(Header->getName()), 744056396aeSDouglas Gregor NameBuf); 7451fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 7461fb5c3a6SDouglas Gregor if (!Found) 7471fb5c3a6SDouglas Gregor return false; 7481fb5c3a6SDouglas Gregor } 7491fb5c3a6SDouglas Gregor 75050996ce1SRichard Smith return IsUnavailable(Found); 7511fb5c3a6SDouglas Gregor } 7521fb5c3a6SDouglas Gregor 7531fb5c3a6SDouglas Gregor SkippedDirs.push_back(Dir); 7541fb5c3a6SDouglas Gregor 7551fb5c3a6SDouglas Gregor // Retrieve our parent path. 7561fb5c3a6SDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 7571fb5c3a6SDouglas Gregor if (DirName.empty()) 7581fb5c3a6SDouglas Gregor break; 7591fb5c3a6SDouglas Gregor 7601fb5c3a6SDouglas Gregor // Resolve the parent path to a directory entry. 7618d323d15SHarlan Haskins if (auto DirEntry = SourceMgr.getFileManager().getDirectory(DirName)) 7628d323d15SHarlan Haskins Dir = *DirEntry; 7638d323d15SHarlan Haskins else 7648d323d15SHarlan Haskins Dir = nullptr; 7651fb5c3a6SDouglas Gregor } while (Dir); 7661fb5c3a6SDouglas Gregor 7671fb5c3a6SDouglas Gregor return false; 7681fb5c3a6SDouglas Gregor } 7691fb5c3a6SDouglas Gregor 770e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const { 771e4412640SArgyrios Kyrtzidis llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name); 77288bdfb0eSDouglas Gregor if (Known != Modules.end()) 77388bdfb0eSDouglas Gregor return Known->getValue(); 77488bdfb0eSDouglas Gregor 775d2d442caSCraig Topper return nullptr; 77688bdfb0eSDouglas Gregor } 77788bdfb0eSDouglas Gregor 778e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name, 779e4412640SArgyrios Kyrtzidis Module *Context) const { 7802b82c2a5SDouglas Gregor for(; Context; Context = Context->Parent) { 7812b82c2a5SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Context)) 7822b82c2a5SDouglas Gregor return Sub; 7832b82c2a5SDouglas Gregor } 7842b82c2a5SDouglas Gregor 7852b82c2a5SDouglas Gregor return findModule(Name); 7862b82c2a5SDouglas Gregor } 7872b82c2a5SDouglas Gregor 788e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{ 7892b82c2a5SDouglas Gregor if (!Context) 7902b82c2a5SDouglas Gregor return findModule(Name); 7912b82c2a5SDouglas Gregor 792eb90e830SDouglas Gregor return Context->findSubmodule(Name); 7932b82c2a5SDouglas Gregor } 7942b82c2a5SDouglas Gregor 795c192d194SBruno Cardoso Lopes std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name, 796c192d194SBruno Cardoso Lopes Module *Parent, 797c192d194SBruno Cardoso Lopes bool IsFramework, 798c192d194SBruno Cardoso Lopes bool IsExplicit) { 79969021974SDouglas Gregor // Try to find an existing module with this name. 800eb90e830SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Parent)) 801eb90e830SDouglas Gregor return std::make_pair(Sub, false); 80269021974SDouglas Gregor 80369021974SDouglas Gregor // Create a new module with this name. 8049ffe5a35SDavid Blaikie Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, 8059ffe5a35SDavid Blaikie IsExplicit, NumCreatedModules++); 8066f722b4eSArgyrios Kyrtzidis if (!Parent) { 8077e82e019SRichard Smith if (LangOpts.CurrentModule == Name) 8087e82e019SRichard Smith SourceModule = Result; 80969021974SDouglas Gregor Modules[Name] = Result; 810c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID; 8116f722b4eSArgyrios Kyrtzidis } 81269021974SDouglas Gregor return std::make_pair(Result, true); 81369021974SDouglas Gregor } 81469021974SDouglas Gregor 815a5bbbfefSRichard Smith Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc) { 816d6509cf2SRichard Smith PendingSubmodules.emplace_back( 817056bf77fSRichard Smith new Module("<global>", Loc, nullptr, /*IsFramework*/ false, 818056bf77fSRichard Smith /*IsExplicit*/ true, NumCreatedModules++)); 819d6509cf2SRichard Smith PendingSubmodules.back()->Kind = Module::GlobalModuleFragment; 820d6509cf2SRichard Smith return PendingSubmodules.back().get(); 821dd8b5337SRichard Smith } 822dd8b5337SRichard Smith 823a5bbbfefSRichard Smith Module * 824a5bbbfefSRichard Smith ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent, 825a5bbbfefSRichard Smith SourceLocation Loc) { 826a5bbbfefSRichard Smith auto *Result = 827a5bbbfefSRichard Smith new Module("<private>", Loc, Parent, /*IsFramework*/ false, 828a5bbbfefSRichard Smith /*IsExplicit*/ true, NumCreatedModules++); 829a5bbbfefSRichard Smith Result->Kind = Module::PrivateModuleFragment; 830a5bbbfefSRichard Smith return Result; 831a5bbbfefSRichard Smith } 832a5bbbfefSRichard Smith 833bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc, 834dd8b5337SRichard Smith StringRef Name, 835dd8b5337SRichard Smith Module *GlobalModule) { 836bbcc9f04SRichard Smith assert(LangOpts.CurrentModule == Name && "module name mismatch"); 837bbcc9f04SRichard Smith assert(!Modules[Name] && "redefining existing module"); 838bbcc9f04SRichard Smith 839bbcc9f04SRichard Smith auto *Result = 840bbcc9f04SRichard Smith new Module(Name, Loc, nullptr, /*IsFramework*/ false, 841bbcc9f04SRichard Smith /*IsExplicit*/ false, NumCreatedModules++); 842145e15a3SRichard Smith Result->Kind = Module::ModuleInterfaceUnit; 843bbcc9f04SRichard Smith Modules[Name] = SourceModule = Result; 844bbcc9f04SRichard Smith 845dd8b5337SRichard Smith // Reparent the current global module fragment as a submodule of this module. 846d6509cf2SRichard Smith for (auto &Submodule : PendingSubmodules) { 847d6509cf2SRichard Smith Submodule->setParent(Result); 848d6509cf2SRichard Smith Submodule.release(); // now owned by parent 849d6509cf2SRichard Smith } 850d6509cf2SRichard Smith PendingSubmodules.clear(); 851dd8b5337SRichard Smith 852bbcc9f04SRichard Smith // Mark the main source file as being within the newly-created module so that 853bbcc9f04SRichard Smith // declarations and macros are properly visibility-restricted to it. 854bbcc9f04SRichard Smith auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()); 855bbcc9f04SRichard Smith assert(MainFile && "no input file for module interface"); 856bbcc9f04SRichard Smith Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader)); 857bbcc9f04SRichard Smith 858bbcc9f04SRichard Smith return Result; 859bbcc9f04SRichard Smith } 860bbcc9f04SRichard Smith 861d6509cf2SRichard Smith Module *ModuleMap::createHeaderModule(StringRef Name, 862d6509cf2SRichard Smith ArrayRef<Module::Header> Headers) { 863d6509cf2SRichard Smith assert(LangOpts.CurrentModule == Name && "module name mismatch"); 864d6509cf2SRichard Smith assert(!Modules[Name] && "redefining existing module"); 865d6509cf2SRichard Smith 866d6509cf2SRichard Smith auto *Result = 867d6509cf2SRichard Smith new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false, 868d6509cf2SRichard Smith /*IsExplicit*/ false, NumCreatedModules++); 869d6509cf2SRichard Smith Result->Kind = Module::ModuleInterfaceUnit; 870d6509cf2SRichard Smith Modules[Name] = SourceModule = Result; 871d6509cf2SRichard Smith 872d6509cf2SRichard Smith for (const Module::Header &H : Headers) { 873d6509cf2SRichard Smith auto *M = new Module(H.NameAsWritten, SourceLocation(), Result, 874d6509cf2SRichard Smith /*IsFramework*/ false, 875d6509cf2SRichard Smith /*IsExplicit*/ true, NumCreatedModules++); 876d6509cf2SRichard Smith // Header modules are implicitly 'export *'. 877d6509cf2SRichard Smith M->Exports.push_back(Module::ExportDecl(nullptr, true)); 878d6509cf2SRichard Smith addHeader(M, H, NormalHeader); 879d6509cf2SRichard Smith } 880d6509cf2SRichard Smith 881d6509cf2SRichard Smith return Result; 882d6509cf2SRichard Smith } 883d6509cf2SRichard Smith 8849fc8faf9SAdrian Prantl /// For a framework module, infer the framework against which we 88511dfe6feSDouglas Gregor /// should link. 88611dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir, 88711dfe6feSDouglas Gregor FileManager &FileMgr) { 88811dfe6feSDouglas Gregor assert(Mod->IsFramework && "Can only infer linking for framework modules"); 88911dfe6feSDouglas Gregor assert(!Mod->isSubFramework() && 89011dfe6feSDouglas Gregor "Can only infer linking for top-level frameworks"); 89111dfe6feSDouglas Gregor 89211dfe6feSDouglas Gregor SmallString<128> LibName; 89311dfe6feSDouglas Gregor LibName += FrameworkDir->getName(); 89411dfe6feSDouglas Gregor llvm::sys::path::append(LibName, Mod->Name); 8958aaae5a9SJuergen Ributzka 8968aaae5a9SJuergen Ributzka // The library name of a framework has more than one possible extension since 8978aaae5a9SJuergen Ributzka // the introduction of the text-based dynamic library format. We need to check 8988aaae5a9SJuergen Ributzka // for both before we give up. 8998013e81dSBenjamin Kramer for (const char *extension : {"", ".tbd"}) { 9008aaae5a9SJuergen Ributzka llvm::sys::path::replace_extension(LibName, extension); 90111dfe6feSDouglas Gregor if (FileMgr.getFile(LibName)) { 90211dfe6feSDouglas Gregor Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name, 90311dfe6feSDouglas Gregor /*IsFramework=*/true)); 9048aaae5a9SJuergen Ributzka return; 9058aaae5a9SJuergen Ributzka } 90611dfe6feSDouglas Gregor } 90711dfe6feSDouglas Gregor } 90811dfe6feSDouglas Gregor 909a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 910a525400dSBen Langmuir bool IsSystem, Module *Parent) { 911c1d88ea5SBen Langmuir Attributes Attrs; 912c1d88ea5SBen Langmuir Attrs.IsSystem = IsSystem; 913a525400dSBen Langmuir return inferFrameworkModule(FrameworkDir, Attrs, Parent); 914c1d88ea5SBen Langmuir } 915c1d88ea5SBen Langmuir 916a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 917c1d88ea5SBen Langmuir Attributes Attrs, Module *Parent) { 918a525400dSBen Langmuir // Note: as an egregious but useful hack we use the real path here, because 919a525400dSBen Langmuir // we might be looking at an embedded framework that symlinks out to a 920a525400dSBen Langmuir // top-level framework, and we need to infer as if we were naming the 921a525400dSBen Langmuir // top-level framework. 922a525400dSBen Langmuir StringRef FrameworkDirName = 923a525400dSBen Langmuir SourceMgr.getFileManager().getCanonicalName(FrameworkDir); 924a525400dSBen Langmuir 925a525400dSBen Langmuir // In case this is a case-insensitive filesystem, use the canonical 926a525400dSBen Langmuir // directory name as the ModuleName, since modules are case-sensitive. 927a525400dSBen Langmuir // FIXME: we should be able to give a fix-it hint for the correct spelling. 928a525400dSBen Langmuir SmallString<32> ModuleNameStorage; 929a525400dSBen Langmuir StringRef ModuleName = sanitizeFilenameAsIdentifier( 930a525400dSBen Langmuir llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage); 931c1d88ea5SBen Langmuir 93256c64013SDouglas Gregor // Check whether we've already found this module. 933e89dbc1dSDouglas Gregor if (Module *Mod = lookupModuleQualified(ModuleName, Parent)) 934e89dbc1dSDouglas Gregor return Mod; 935e89dbc1dSDouglas Gregor 9361f76c4e8SManuel Klimek FileManager &FileMgr = SourceMgr.getFileManager(); 93756c64013SDouglas Gregor 9389194a91dSDouglas Gregor // If the framework has a parent path from which we're allowed to infer 9399194a91dSDouglas Gregor // a framework module, do so. 940beee15e7SBen Langmuir const FileEntry *ModuleMapFile = nullptr; 9419194a91dSDouglas Gregor if (!Parent) { 9424ddf2221SDouglas Gregor // Determine whether we're allowed to infer a module map. 9439194a91dSDouglas Gregor bool canInfer = false; 9444ddf2221SDouglas Gregor if (llvm::sys::path::has_parent_path(FrameworkDirName)) { 9459194a91dSDouglas Gregor // Figure out the parent path. 9464ddf2221SDouglas Gregor StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName); 9478d323d15SHarlan Haskins if (auto ParentDir = FileMgr.getDirectory(Parent)) { 9489194a91dSDouglas Gregor // Check whether we have already looked into the parent directory 9499194a91dSDouglas Gregor // for a module map. 950e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator 9518d323d15SHarlan Haskins inferred = InferredDirectories.find(*ParentDir); 9529194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) { 9539194a91dSDouglas Gregor // We haven't looked here before. Load a module map, if there is 9549194a91dSDouglas Gregor // one. 955984e1df7SBen Langmuir bool IsFrameworkDir = Parent.endswith(".framework"); 956984e1df7SBen Langmuir if (const FileEntry *ModMapFile = 9578d323d15SHarlan Haskins HeaderInfo.lookupModuleMapFile(*ParentDir, IsFrameworkDir)) { 9588d323d15SHarlan Haskins parseModuleMapFile(ModMapFile, Attrs.IsSystem, *ParentDir); 9598d323d15SHarlan Haskins inferred = InferredDirectories.find(*ParentDir); 9609194a91dSDouglas Gregor } 9619194a91dSDouglas Gregor 9629194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) 9639194a91dSDouglas Gregor inferred = InferredDirectories.insert( 9648d323d15SHarlan Haskins std::make_pair(*ParentDir, InferredDirectory())).first; 9659194a91dSDouglas Gregor } 9669194a91dSDouglas Gregor 9679194a91dSDouglas Gregor if (inferred->second.InferModules) { 9689194a91dSDouglas Gregor // We're allowed to infer for this directory, but make sure it's okay 9699194a91dSDouglas Gregor // to infer this particular module. 9704ddf2221SDouglas Gregor StringRef Name = llvm::sys::path::stem(FrameworkDirName); 9719194a91dSDouglas Gregor canInfer = std::find(inferred->second.ExcludedModules.begin(), 9729194a91dSDouglas Gregor inferred->second.ExcludedModules.end(), 9739194a91dSDouglas Gregor Name) == inferred->second.ExcludedModules.end(); 9749194a91dSDouglas Gregor 975c1d88ea5SBen Langmuir Attrs.IsSystem |= inferred->second.Attrs.IsSystem; 976c1d88ea5SBen Langmuir Attrs.IsExternC |= inferred->second.Attrs.IsExternC; 977c1d88ea5SBen Langmuir Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive; 978ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes |= 979ed84df00SBruno Cardoso Lopes inferred->second.Attrs.NoUndeclaredIncludes; 980beee15e7SBen Langmuir ModuleMapFile = inferred->second.ModuleMapFile; 9819194a91dSDouglas Gregor } 9829194a91dSDouglas Gregor } 9839194a91dSDouglas Gregor } 9849194a91dSDouglas Gregor 9859194a91dSDouglas Gregor // If we're not allowed to infer a framework module, don't. 9869194a91dSDouglas Gregor if (!canInfer) 987d2d442caSCraig Topper return nullptr; 988beee15e7SBen Langmuir } else 9899d6448b1SBen Langmuir ModuleMapFile = getModuleMapFileForUniquing(Parent); 9909194a91dSDouglas Gregor 9919194a91dSDouglas Gregor 99256c64013SDouglas Gregor // Look for an umbrella header. 9932c1dd271SDylan Noblesmith SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 99417381a06SBenjamin Kramer llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h"); 9958d323d15SHarlan Haskins auto UmbrellaHeader = FileMgr.getFile(UmbrellaName); 99656c64013SDouglas Gregor 99756c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the 99856c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good 99956c64013SDouglas Gregor // idea. 100056c64013SDouglas Gregor if (!UmbrellaHeader) 1001d2d442caSCraig Topper return nullptr; 100256c64013SDouglas Gregor 10039d6448b1SBen Langmuir Module *Result = new Module(ModuleName, SourceLocation(), Parent, 1004a7e2cc68SRichard Smith /*IsFramework=*/true, /*IsExplicit=*/false, 1005a7e2cc68SRichard Smith NumCreatedModules++); 10069d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = ModuleMapFile; 10079d6448b1SBen Langmuir Result->IsInferred = true; 10087e82e019SRichard Smith if (!Parent) { 10097e82e019SRichard Smith if (LangOpts.CurrentModule == ModuleName) 1010ba7f2f71SDaniel Jasper SourceModule = Result; 10117e82e019SRichard Smith Modules[ModuleName] = Result; 1012c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID; 1013ba7f2f71SDaniel Jasper } 1014c1d88ea5SBen Langmuir 1015c1d88ea5SBen Langmuir Result->IsSystem |= Attrs.IsSystem; 1016c1d88ea5SBen Langmuir Result->IsExternC |= Attrs.IsExternC; 1017c1d88ea5SBen Langmuir Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive; 1018ed84df00SBruno Cardoso Lopes Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes; 10192b63d15fSRichard Smith Result->Directory = FrameworkDir; 1020a686e1b0SDouglas Gregor 1021322f633cSDouglas Gregor // umbrella header "umbrella-header-name" 10222b63d15fSRichard Smith // 10232b63d15fSRichard Smith // The "Headers/" component of the name is implied because this is 10242b63d15fSRichard Smith // a framework module. 10258d323d15SHarlan Haskins setUmbrellaHeader(Result, *UmbrellaHeader, ModuleName + ".h"); 1026d8bd7537SDouglas Gregor 1027d8bd7537SDouglas Gregor // export * 1028d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 1029d8bd7537SDouglas Gregor 1030a89c5ac4SDouglas Gregor // module * { export * } 1031a89c5ac4SDouglas Gregor Result->InferSubmodules = true; 1032a89c5ac4SDouglas Gregor Result->InferExportWildcard = true; 1033a89c5ac4SDouglas Gregor 1034e89dbc1dSDouglas Gregor // Look for subframeworks. 1035c080917eSRafael Espindola std::error_code EC; 10362c1dd271SDylan Noblesmith SmallString<128> SubframeworksDirName 1037ddaa69cbSDouglas Gregor = StringRef(FrameworkDir->getName()); 1038e89dbc1dSDouglas Gregor llvm::sys::path::append(SubframeworksDirName, "Frameworks"); 10392d4d8cb3SBenjamin Kramer llvm::sys::path::native(SubframeworksDirName); 1040db8a7422SDuncan P. N. Exon Smith llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); 1041fc51490bSJonas Devlieghere for (llvm::vfs::directory_iterator 1042fc51490bSJonas Devlieghere Dir = FS.dir_begin(SubframeworksDirName, EC), 1043b171a59bSBruno Cardoso Lopes DirEnd; 1044e89dbc1dSDouglas Gregor Dir != DirEnd && !EC; Dir.increment(EC)) { 10450ae00567SSam McCall if (!StringRef(Dir->path()).endswith(".framework")) 1046e89dbc1dSDouglas Gregor continue; 1047f2161a70SDouglas Gregor 10488d323d15SHarlan Haskins if (auto SubframeworkDir = 10490ae00567SSam McCall FileMgr.getDirectory(Dir->path())) { 105007c22b78SDouglas Gregor // Note: as an egregious but useful hack, we use the real path here and 105107c22b78SDouglas Gregor // check whether it is actually a subdirectory of the parent directory. 105207c22b78SDouglas Gregor // This will not be the case if the 'subframework' is actually a symlink 105307c22b78SDouglas Gregor // out to a top-level framework. 10548d323d15SHarlan Haskins StringRef SubframeworkDirName = 10558d323d15SHarlan Haskins FileMgr.getCanonicalName(*SubframeworkDir); 105607c22b78SDouglas Gregor bool FoundParent = false; 105707c22b78SDouglas Gregor do { 105807c22b78SDouglas Gregor // Get the parent directory name. 105907c22b78SDouglas Gregor SubframeworkDirName 106007c22b78SDouglas Gregor = llvm::sys::path::parent_path(SubframeworkDirName); 106107c22b78SDouglas Gregor if (SubframeworkDirName.empty()) 106207c22b78SDouglas Gregor break; 106307c22b78SDouglas Gregor 10648d323d15SHarlan Haskins if (auto SubDir = FileMgr.getDirectory(SubframeworkDirName)) { 10658d323d15SHarlan Haskins if (*SubDir == FrameworkDir) { 106607c22b78SDouglas Gregor FoundParent = true; 106707c22b78SDouglas Gregor break; 106807c22b78SDouglas Gregor } 10698d323d15SHarlan Haskins } 107007c22b78SDouglas Gregor } while (true); 107107c22b78SDouglas Gregor 107207c22b78SDouglas Gregor if (!FoundParent) 107307c22b78SDouglas Gregor continue; 107407c22b78SDouglas Gregor 1075e89dbc1dSDouglas Gregor // FIXME: Do we want to warn about subframeworks without umbrella headers? 10768d323d15SHarlan Haskins inferFrameworkModule(*SubframeworkDir, Attrs, Result); 1077e89dbc1dSDouglas Gregor } 1078e89dbc1dSDouglas Gregor } 1079e89dbc1dSDouglas Gregor 108011dfe6feSDouglas Gregor // If the module is a top-level framework, automatically link against the 108111dfe6feSDouglas Gregor // framework. 108211dfe6feSDouglas Gregor if (!Result->isSubFramework()) { 108311dfe6feSDouglas Gregor inferFrameworkLink(Result, FrameworkDir, FileMgr); 108411dfe6feSDouglas Gregor } 108511dfe6feSDouglas Gregor 108656c64013SDouglas Gregor return Result; 108756c64013SDouglas Gregor } 108856c64013SDouglas Gregor 10898587dfd9SBruno Cardoso Lopes Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework, 10908587dfd9SBruno Cardoso Lopes Module *ShadowingModule) { 10918587dfd9SBruno Cardoso Lopes 10928587dfd9SBruno Cardoso Lopes // Create a new module with this name. 10938587dfd9SBruno Cardoso Lopes Module *Result = 10948587dfd9SBruno Cardoso Lopes new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework, 10958587dfd9SBruno Cardoso Lopes /*IsExplicit=*/false, NumCreatedModules++); 10968587dfd9SBruno Cardoso Lopes Result->ShadowingModule = ShadowingModule; 10978587dfd9SBruno Cardoso Lopes Result->IsAvailable = false; 1098c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID; 10998587dfd9SBruno Cardoso Lopes ShadowModules.push_back(Result); 11008587dfd9SBruno Cardoso Lopes 11018587dfd9SBruno Cardoso Lopes return Result; 11028587dfd9SBruno Cardoso Lopes } 11038587dfd9SBruno Cardoso Lopes 11042b63d15fSRichard Smith void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader, 11052b63d15fSRichard Smith Twine NameAsWritten) { 110697da9178SDaniel Jasper Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader)); 110773141fa9SDouglas Gregor Mod->Umbrella = UmbrellaHeader; 1108*bc883665SReid Kleckner Mod->HasUmbrellaDir = false; 11092b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 11107033127bSDouglas Gregor UmbrellaDirs[UmbrellaHeader->getDir()] = Mod; 1111b3a0fa48SBruno Cardoso Lopes 1112b3a0fa48SBruno Cardoso Lopes // Notify callbacks that we just added a new header. 1113b3a0fa48SBruno Cardoso Lopes for (const auto &Cb : Callbacks) 1114b3a0fa48SBruno Cardoso Lopes Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader); 1115a89c5ac4SDouglas Gregor } 1116a89c5ac4SDouglas Gregor 11172b63d15fSRichard Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, 11182b63d15fSRichard Smith Twine NameAsWritten) { 1119524e33e1SDouglas Gregor Mod->Umbrella = UmbrellaDir; 1120*bc883665SReid Kleckner Mod->HasUmbrellaDir = true; 11212b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 1122524e33e1SDouglas Gregor UmbrellaDirs[UmbrellaDir] = Mod; 1123524e33e1SDouglas Gregor } 1124524e33e1SDouglas Gregor 1125040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod, 11269f6020bcSBruno Cardoso Lopes Module::UnresolvedHeaderDirective Header, 11279f6020bcSBruno Cardoso Lopes bool &NeedsFramework) { 1128040e1266SRichard Smith // If there is a builtin counterpart to this file, add it now so it can 1129040e1266SRichard Smith // wrap the system header. 1130040e1266SRichard Smith if (resolveAsBuiltinHeader(Mod, Header)) { 1131040e1266SRichard Smith // If we have both a builtin and system version of the file, the 1132040e1266SRichard Smith // builtin version may want to inject macros into the system header, so 1133040e1266SRichard Smith // force the system header to be treated as a textual header in this 1134040e1266SRichard Smith // case. 1135040e1266SRichard Smith Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole( 1136040e1266SRichard Smith headerKindToRole(Header.Kind) | ModuleMap::TextualHeader)); 1137040e1266SRichard Smith Header.HasBuiltinHeader = true; 11383c1a41adSRichard Smith } 1139040e1266SRichard Smith 1140040e1266SRichard Smith // If possible, don't stat the header until we need to. This requires the 1141040e1266SRichard Smith // user to have provided us with some stat information about the file. 1142040e1266SRichard Smith // FIXME: Add support for lazily stat'ing umbrella headers and excluded 1143040e1266SRichard Smith // headers. 1144040e1266SRichard Smith if ((Header.Size || Header.ModTime) && !Header.IsUmbrella && 1145040e1266SRichard Smith Header.Kind != Module::HK_Excluded) { 1146040e1266SRichard Smith // We expect more variation in mtime than size, so if we're given both, 1147040e1266SRichard Smith // use the mtime as the key. 1148040e1266SRichard Smith if (Header.ModTime) 1149040e1266SRichard Smith LazyHeadersByModTime[*Header.ModTime].push_back(Mod); 1150040e1266SRichard Smith else 1151040e1266SRichard Smith LazyHeadersBySize[*Header.Size].push_back(Mod); 1152040e1266SRichard Smith Mod->UnresolvedHeaders.push_back(Header); 1153040e1266SRichard Smith return; 1154040e1266SRichard Smith } 1155040e1266SRichard Smith 1156040e1266SRichard Smith // We don't have stat information or can't defer looking this file up. 1157040e1266SRichard Smith // Perform the lookup now. 11589f6020bcSBruno Cardoso Lopes resolveHeader(Mod, Header, NeedsFramework); 1159040e1266SRichard Smith } 1160040e1266SRichard Smith 1161040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const { 1162040e1266SRichard Smith auto BySize = LazyHeadersBySize.find(File->getSize()); 1163040e1266SRichard Smith if (BySize != LazyHeadersBySize.end()) { 1164040e1266SRichard Smith for (auto *M : BySize->second) 1165040e1266SRichard Smith resolveHeaderDirectives(M); 1166040e1266SRichard Smith LazyHeadersBySize.erase(BySize); 1167040e1266SRichard Smith } 1168040e1266SRichard Smith 1169040e1266SRichard Smith auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime()); 1170040e1266SRichard Smith if (ByModTime != LazyHeadersByModTime.end()) { 1171040e1266SRichard Smith for (auto *M : ByModTime->second) 1172040e1266SRichard Smith resolveHeaderDirectives(M); 1173040e1266SRichard Smith LazyHeadersByModTime.erase(ByModTime); 1174040e1266SRichard Smith } 1175040e1266SRichard Smith } 1176040e1266SRichard Smith 1177040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(Module *Mod) const { 11789f6020bcSBruno Cardoso Lopes bool NeedsFramework = false; 1179040e1266SRichard Smith for (auto &Header : Mod->UnresolvedHeaders) 1180040e1266SRichard Smith // This operation is logically const; we're just changing how we represent 1181040e1266SRichard Smith // the header information for this file. 11829f6020bcSBruno Cardoso Lopes const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework); 1183040e1266SRichard Smith Mod->UnresolvedHeaders.clear(); 11840e98d938SNAKAMURA Takumi } 1185202210b3SRichard Smith 11863c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header, 1187d8879c85SRichard Smith ModuleHeaderRole Role, bool Imported) { 1188386bb073SRichard Smith KnownHeader KH(Mod, Role); 11893c1a41adSRichard Smith 1190386bb073SRichard Smith // Only add each header to the headers list once. 1191386bb073SRichard Smith // FIXME: Should we diagnose if a header is listed twice in the 1192386bb073SRichard Smith // same module definition? 1193386bb073SRichard Smith auto &HeaderList = Headers[Header.Entry]; 1194386bb073SRichard Smith for (auto H : HeaderList) 1195386bb073SRichard Smith if (H == KH) 1196386bb073SRichard Smith return; 1197386bb073SRichard Smith 1198386bb073SRichard Smith HeaderList.push_back(KH); 11991ec383c7SPiotr Padlewski Mod->Headers[headerRoleToKind(Role)].push_back(Header); 1200386bb073SRichard Smith 12017e82e019SRichard Smith bool isCompilingModuleHeader = 1202bbcc9f04SRichard Smith LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule; 1203d8879c85SRichard Smith if (!Imported || isCompilingModuleHeader) { 1204d8879c85SRichard Smith // When we import HeaderFileInfo, the external source is expected to 1205d8879c85SRichard Smith // set the isModuleHeader flag itself. 1206d8879c85SRichard Smith HeaderInfo.MarkFileModuleHeader(Header.Entry, Role, 1207d8879c85SRichard Smith isCompilingModuleHeader); 1208d8879c85SRichard Smith } 1209e62cfd7cSBruno Cardoso Lopes 1210e62cfd7cSBruno Cardoso Lopes // Notify callbacks that we just added a new header. 1211e62cfd7cSBruno Cardoso Lopes for (const auto &Cb : Callbacks) 1212f0841790SBruno Cardoso Lopes Cb->moduleMapAddHeader(Header.Entry->getName()); 1213a89c5ac4SDouglas Gregor } 1214a89c5ac4SDouglas Gregor 12153c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) { 1216feb54b6dSRichard Smith // Add this as a known header so we won't implicitly add it to any 1217feb54b6dSRichard Smith // umbrella directory module. 1218feb54b6dSRichard Smith // FIXME: Should we only exclude it from umbrella modules within the 1219feb54b6dSRichard Smith // specified module? 12203c1a41adSRichard Smith (void) Headers[Header.Entry]; 12213c1a41adSRichard Smith 12223c1a41adSRichard Smith Mod->Headers[Module::HK_Excluded].push_back(std::move(Header)); 1223feb54b6dSRichard Smith } 1224feb54b6dSRichard Smith 1225514b636aSDouglas Gregor const FileEntry * 12264b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const { 12271f76c4e8SManuel Klimek if (Module->DefinitionLoc.isInvalid()) 1228d2d442caSCraig Topper return nullptr; 1229514b636aSDouglas Gregor 12301f76c4e8SManuel Klimek return SourceMgr.getFileEntryForID( 12311f76c4e8SManuel Klimek SourceMgr.getFileID(Module->DefinitionLoc)); 1232514b636aSDouglas Gregor } 1233514b636aSDouglas Gregor 12344b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const { 12359d6448b1SBen Langmuir if (M->IsInferred) { 12369d6448b1SBen Langmuir assert(InferredModuleAllowedBy.count(M) && "missing inferred module map"); 12379d6448b1SBen Langmuir return InferredModuleAllowedBy.find(M)->second; 12389d6448b1SBen Langmuir } 12399d6448b1SBen Langmuir return getContainingModuleMapFile(M); 12409d6448b1SBen Langmuir } 12419d6448b1SBen Langmuir 12429d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) { 12439d6448b1SBen Langmuir assert(M->IsInferred && "module not inferred"); 12449d6448b1SBen Langmuir InferredModuleAllowedBy[M] = ModMap; 12459d6448b1SBen Langmuir } 12469d6448b1SBen Langmuir 1247cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() { 1248718292f2SDouglas Gregor llvm::errs() << "Modules:"; 1249718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 1250718292f2SDouglas Gregor MEnd = Modules.end(); 1251718292f2SDouglas Gregor M != MEnd; ++M) 1252d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 1253718292f2SDouglas Gregor 1254718292f2SDouglas Gregor llvm::errs() << "Headers:"; 125559527666SDouglas Gregor for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end(); 1256718292f2SDouglas Gregor H != HEnd; ++H) { 125797da9178SDaniel Jasper llvm::errs() << " \"" << H->first->getName() << "\" -> "; 125897da9178SDaniel Jasper for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(), 125997da9178SDaniel Jasper E = H->second.end(); 126097da9178SDaniel Jasper I != E; ++I) { 126197da9178SDaniel Jasper if (I != H->second.begin()) 126297da9178SDaniel Jasper llvm::errs() << ","; 126397da9178SDaniel Jasper llvm::errs() << I->getModule()->getFullModuleName(); 126497da9178SDaniel Jasper } 126597da9178SDaniel Jasper llvm::errs() << "\n"; 1266718292f2SDouglas Gregor } 1267718292f2SDouglas Gregor } 1268718292f2SDouglas Gregor 12692b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) { 127042413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedExports); 127142413141SRichard Smith Mod->UnresolvedExports.clear(); 127242413141SRichard Smith for (auto &UE : Unresolved) { 127342413141SRichard Smith Module::ExportDecl Export = resolveExport(Mod, UE, Complain); 1274f5eedd05SDouglas Gregor if (Export.getPointer() || Export.getInt()) 12752b82c2a5SDouglas Gregor Mod->Exports.push_back(Export); 12762b82c2a5SDouglas Gregor else 127742413141SRichard Smith Mod->UnresolvedExports.push_back(UE); 12782b82c2a5SDouglas Gregor } 127942413141SRichard Smith return !Mod->UnresolvedExports.empty(); 12802b82c2a5SDouglas Gregor } 12812b82c2a5SDouglas Gregor 1282ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) { 128342413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedDirectUses); 128442413141SRichard Smith Mod->UnresolvedDirectUses.clear(); 128542413141SRichard Smith for (auto &UDU : Unresolved) { 128642413141SRichard Smith Module *DirectUse = resolveModuleId(UDU, Mod, Complain); 1287ba7f2f71SDaniel Jasper if (DirectUse) 1288ba7f2f71SDaniel Jasper Mod->DirectUses.push_back(DirectUse); 1289ba7f2f71SDaniel Jasper else 129042413141SRichard Smith Mod->UnresolvedDirectUses.push_back(UDU); 1291ba7f2f71SDaniel Jasper } 129242413141SRichard Smith return !Mod->UnresolvedDirectUses.empty(); 1293ba7f2f71SDaniel Jasper } 1294ba7f2f71SDaniel Jasper 1295fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) { 129642413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedConflicts); 129742413141SRichard Smith Mod->UnresolvedConflicts.clear(); 129842413141SRichard Smith for (auto &UC : Unresolved) { 129942413141SRichard Smith if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) { 1300fb912657SDouglas Gregor Module::Conflict Conflict; 1301fb912657SDouglas Gregor Conflict.Other = OtherMod; 130242413141SRichard Smith Conflict.Message = UC.Message; 1303fb912657SDouglas Gregor Mod->Conflicts.push_back(Conflict); 130442413141SRichard Smith } else 130542413141SRichard Smith Mod->UnresolvedConflicts.push_back(UC); 1306fb912657SDouglas Gregor } 130742413141SRichard Smith return !Mod->UnresolvedConflicts.empty(); 1308fb912657SDouglas Gregor } 1309fb912657SDouglas Gregor 1310718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1311718292f2SDouglas Gregor // Module map file parser 1312718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1313718292f2SDouglas Gregor 1314718292f2SDouglas Gregor namespace clang { 1315afd1b1c9SEugene Zelenko 13169fc8faf9SAdrian Prantl /// A token in a module map file. 1317718292f2SDouglas Gregor struct MMToken { 1318718292f2SDouglas Gregor enum TokenKind { 13191fb5c3a6SDouglas Gregor Comma, 132035b13eceSDouglas Gregor ConfigMacros, 1321fb912657SDouglas Gregor Conflict, 1322718292f2SDouglas Gregor EndOfFile, 1323718292f2SDouglas Gregor HeaderKeyword, 1324718292f2SDouglas Gregor Identifier, 1325a3feee2aSRichard Smith Exclaim, 132659527666SDouglas Gregor ExcludeKeyword, 1327718292f2SDouglas Gregor ExplicitKeyword, 13282b82c2a5SDouglas Gregor ExportKeyword, 1329f0b11de2SDouglas Gregor ExportAsKeyword, 133097292843SDaniel Jasper ExternKeyword, 1331755b2055SDouglas Gregor FrameworkKeyword, 13326ddfca91SDouglas Gregor LinkKeyword, 1333718292f2SDouglas Gregor ModuleKeyword, 13342b82c2a5SDouglas Gregor Period, 1335b53e5483SLawrence Crowl PrivateKeyword, 1336718292f2SDouglas Gregor UmbrellaKeyword, 1337ba7f2f71SDaniel Jasper UseKeyword, 13381fb5c3a6SDouglas Gregor RequiresKeyword, 13392b82c2a5SDouglas Gregor Star, 1340718292f2SDouglas Gregor StringLiteral, 1341040e1266SRichard Smith IntegerLiteral, 1342306d8920SRichard Smith TextualKeyword, 1343718292f2SDouglas Gregor LBrace, 1344a686e1b0SDouglas Gregor RBrace, 1345a686e1b0SDouglas Gregor LSquare, 1346a686e1b0SDouglas Gregor RSquare 1347718292f2SDouglas Gregor } Kind; 1348718292f2SDouglas Gregor 1349718292f2SDouglas Gregor unsigned Location; 1350718292f2SDouglas Gregor unsigned StringLength; 1351040e1266SRichard Smith union { 1352040e1266SRichard Smith // If Kind != IntegerLiteral. 1353718292f2SDouglas Gregor const char *StringData; 1354afd1b1c9SEugene Zelenko 1355040e1266SRichard Smith // If Kind == IntegerLiteral. 1356040e1266SRichard Smith uint64_t IntegerValue; 1357040e1266SRichard Smith }; 1358718292f2SDouglas Gregor 1359718292f2SDouglas Gregor void clear() { 1360718292f2SDouglas Gregor Kind = EndOfFile; 1361718292f2SDouglas Gregor Location = 0; 1362718292f2SDouglas Gregor StringLength = 0; 1363d2d442caSCraig Topper StringData = nullptr; 1364718292f2SDouglas Gregor } 1365718292f2SDouglas Gregor 1366718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 1367718292f2SDouglas Gregor 1368718292f2SDouglas Gregor SourceLocation getLocation() const { 1369718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 1370718292f2SDouglas Gregor } 1371718292f2SDouglas Gregor 1372040e1266SRichard Smith uint64_t getInteger() const { 1373040e1266SRichard Smith return Kind == IntegerLiteral ? IntegerValue : 0; 1374040e1266SRichard Smith } 1375040e1266SRichard Smith 1376718292f2SDouglas Gregor StringRef getString() const { 1377040e1266SRichard Smith return Kind == IntegerLiteral ? StringRef() 1378040e1266SRichard Smith : StringRef(StringData, StringLength); 1379718292f2SDouglas Gregor } 1380718292f2SDouglas Gregor }; 1381718292f2SDouglas Gregor 1382718292f2SDouglas Gregor class ModuleMapParser { 1383718292f2SDouglas Gregor Lexer &L; 1384718292f2SDouglas Gregor SourceManager &SourceMgr; 1385bc10b9fbSDouglas Gregor 13869fc8faf9SAdrian Prantl /// Default target information, used only for string literal 1387bc10b9fbSDouglas Gregor /// parsing. 1388bc10b9fbSDouglas Gregor const TargetInfo *Target; 1389bc10b9fbSDouglas Gregor 1390718292f2SDouglas Gregor DiagnosticsEngine &Diags; 1391718292f2SDouglas Gregor ModuleMap ⤅ 1392718292f2SDouglas Gregor 13939fc8faf9SAdrian Prantl /// The current module map file. 1394beee15e7SBen Langmuir const FileEntry *ModuleMapFile; 1395beee15e7SBen Langmuir 13969f6020bcSBruno Cardoso Lopes /// Source location of most recent parsed module declaration 13979f6020bcSBruno Cardoso Lopes SourceLocation CurrModuleDeclLoc; 13989f6020bcSBruno Cardoso Lopes 13999fc8faf9SAdrian Prantl /// The directory that file names in this module map file should 14009acb99e3SRichard Smith /// be resolved relative to. 14015257fc63SDouglas Gregor const DirectoryEntry *Directory; 14025257fc63SDouglas Gregor 14039fc8faf9SAdrian Prantl /// Whether this module map is in a system header directory. 1404963c5535SDouglas Gregor bool IsSystem; 1405963c5535SDouglas Gregor 14069fc8faf9SAdrian Prantl /// Whether an error occurred. 1407afd1b1c9SEugene Zelenko bool HadError = false; 1408718292f2SDouglas Gregor 14099fc8faf9SAdrian Prantl /// Stores string data for the various string literals referenced 1410718292f2SDouglas Gregor /// during parsing. 1411718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 1412718292f2SDouglas Gregor 14139fc8faf9SAdrian Prantl /// The current token. 1414718292f2SDouglas Gregor MMToken Tok; 1415718292f2SDouglas Gregor 14169fc8faf9SAdrian Prantl /// The active module. 1417afd1b1c9SEugene Zelenko Module *ActiveModule = nullptr; 1418718292f2SDouglas Gregor 14199fc8faf9SAdrian Prantl /// Whether a module uses the 'requires excluded' hack to mark its 14207ff29148SBen Langmuir /// contents as 'textual'. 14217ff29148SBen Langmuir /// 14227ff29148SBen Langmuir /// On older Darwin SDK versions, 'requires excluded' is used to mark the 14237ff29148SBen Langmuir /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as 14247ff29148SBen Langmuir /// non-modular headers. For backwards compatibility, we continue to 14257ff29148SBen Langmuir /// support this idiom for just these modules, and map the headers to 14267ff29148SBen Langmuir /// 'textual' to match the original intent. 14277ff29148SBen Langmuir llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack; 14287ff29148SBen Langmuir 14299fc8faf9SAdrian Prantl /// Consume the current token and return its location. 1430718292f2SDouglas Gregor SourceLocation consumeToken(); 1431718292f2SDouglas Gregor 14329fc8faf9SAdrian Prantl /// Skip tokens until we reach the a token with the given kind 1433718292f2SDouglas Gregor /// (or the end of the file). 1434718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 1435718292f2SDouglas Gregor 1436afd1b1c9SEugene Zelenko using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>; 1437afd1b1c9SEugene Zelenko 1438e7ab3669SDouglas Gregor bool parseModuleId(ModuleId &Id); 1439718292f2SDouglas Gregor void parseModuleDecl(); 144097292843SDaniel Jasper void parseExternModuleDecl(); 14411fb5c3a6SDouglas Gregor void parseRequiresDecl(); 1442afd1b1c9SEugene Zelenko void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc); 1443524e33e1SDouglas Gregor void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc); 14442b82c2a5SDouglas Gregor void parseExportDecl(); 1445f0b11de2SDouglas Gregor void parseExportAsDecl(); 1446ba7f2f71SDaniel Jasper void parseUseDecl(); 14476ddfca91SDouglas Gregor void parseLinkDecl(); 144835b13eceSDouglas Gregor void parseConfigMacros(); 1449fb912657SDouglas Gregor void parseConflict(); 14509194a91dSDouglas Gregor void parseInferredModuleDecl(bool Framework, bool Explicit); 1451c1d88ea5SBen Langmuir 14525f11e128SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra 14535f11e128SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH 14545f11e128SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written 14555f11e128SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits. 14565f11e128SBruno Cardoso Lopes void diagnosePrivateModules(SourceLocation ExplicitLoc, 14575f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc); 14585f11e128SBruno Cardoso Lopes 1459afd1b1c9SEugene Zelenko using Attributes = ModuleMap::Attributes; 1460afd1b1c9SEugene Zelenko 14614442605fSBill Wendling bool parseOptionalAttributes(Attributes &Attrs); 1462718292f2SDouglas Gregor 1463718292f2SDouglas Gregor public: 1464718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 14658587dfd9SBruno Cardoso Lopes const TargetInfo *Target, DiagnosticsEngine &Diags, 14668587dfd9SBruno Cardoso Lopes ModuleMap &Map, const FileEntry *ModuleMapFile, 1467c192d194SBruno Cardoso Lopes const DirectoryEntry *Directory, bool IsSystem) 1468bc10b9fbSDouglas Gregor : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map), 1469beee15e7SBen Langmuir ModuleMapFile(ModuleMapFile), Directory(Directory), 1470c192d194SBruno Cardoso Lopes IsSystem(IsSystem) { 1471718292f2SDouglas Gregor Tok.clear(); 1472718292f2SDouglas Gregor consumeToken(); 1473718292f2SDouglas Gregor } 1474718292f2SDouglas Gregor 1475718292f2SDouglas Gregor bool parseModuleMapFile(); 14768128f332SRichard Smith 14778128f332SRichard Smith bool terminatedByDirective() { return false; } 14788128f332SRichard Smith SourceLocation getLocation() { return Tok.getLocation(); } 1479718292f2SDouglas Gregor }; 1480afd1b1c9SEugene Zelenko 1481afd1b1c9SEugene Zelenko } // namespace clang 1482718292f2SDouglas Gregor 1483718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 1484718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 1485718292f2SDouglas Gregor 14868128f332SRichard Smith retry: 14878128f332SRichard Smith Tok.clear(); 1488718292f2SDouglas Gregor Token LToken; 1489718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 1490718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 1491718292f2SDouglas Gregor switch (LToken.getKind()) { 14922d57cea2SAlp Toker case tok::raw_identifier: { 14932d57cea2SAlp Toker StringRef RI = LToken.getRawIdentifier(); 14942d57cea2SAlp Toker Tok.StringData = RI.data(); 14952d57cea2SAlp Toker Tok.StringLength = RI.size(); 14962d57cea2SAlp Toker Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI) 149735b13eceSDouglas Gregor .Case("config_macros", MMToken::ConfigMacros) 1498fb912657SDouglas Gregor .Case("conflict", MMToken::Conflict) 149959527666SDouglas Gregor .Case("exclude", MMToken::ExcludeKeyword) 1500718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 15012b82c2a5SDouglas Gregor .Case("export", MMToken::ExportKeyword) 1502f0b11de2SDouglas Gregor .Case("export_as", MMToken::ExportAsKeyword) 150397292843SDaniel Jasper .Case("extern", MMToken::ExternKeyword) 1504755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 150535b13eceSDouglas Gregor .Case("header", MMToken::HeaderKeyword) 15066ddfca91SDouglas Gregor .Case("link", MMToken::LinkKeyword) 1507718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 1508b53e5483SLawrence Crowl .Case("private", MMToken::PrivateKeyword) 15091fb5c3a6SDouglas Gregor .Case("requires", MMToken::RequiresKeyword) 1510306d8920SRichard Smith .Case("textual", MMToken::TextualKeyword) 1511718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 1512ba7f2f71SDaniel Jasper .Case("use", MMToken::UseKeyword) 1513718292f2SDouglas Gregor .Default(MMToken::Identifier); 1514718292f2SDouglas Gregor break; 15152d57cea2SAlp Toker } 1516718292f2SDouglas Gregor 15171fb5c3a6SDouglas Gregor case tok::comma: 15181fb5c3a6SDouglas Gregor Tok.Kind = MMToken::Comma; 15191fb5c3a6SDouglas Gregor break; 15201fb5c3a6SDouglas Gregor 1521718292f2SDouglas Gregor case tok::eof: 1522718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 1523718292f2SDouglas Gregor break; 1524718292f2SDouglas Gregor 1525718292f2SDouglas Gregor case tok::l_brace: 1526718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 1527718292f2SDouglas Gregor break; 1528718292f2SDouglas Gregor 1529a686e1b0SDouglas Gregor case tok::l_square: 1530a686e1b0SDouglas Gregor Tok.Kind = MMToken::LSquare; 1531a686e1b0SDouglas Gregor break; 1532a686e1b0SDouglas Gregor 15332b82c2a5SDouglas Gregor case tok::period: 15342b82c2a5SDouglas Gregor Tok.Kind = MMToken::Period; 15352b82c2a5SDouglas Gregor break; 15362b82c2a5SDouglas Gregor 1537718292f2SDouglas Gregor case tok::r_brace: 1538718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 1539718292f2SDouglas Gregor break; 1540718292f2SDouglas Gregor 1541a686e1b0SDouglas Gregor case tok::r_square: 1542a686e1b0SDouglas Gregor Tok.Kind = MMToken::RSquare; 1543a686e1b0SDouglas Gregor break; 1544a686e1b0SDouglas Gregor 15452b82c2a5SDouglas Gregor case tok::star: 15462b82c2a5SDouglas Gregor Tok.Kind = MMToken::Star; 15472b82c2a5SDouglas Gregor break; 15482b82c2a5SDouglas Gregor 1549a3feee2aSRichard Smith case tok::exclaim: 1550a3feee2aSRichard Smith Tok.Kind = MMToken::Exclaim; 1551a3feee2aSRichard Smith break; 1552a3feee2aSRichard Smith 1553718292f2SDouglas Gregor case tok::string_literal: { 1554d67aea28SRichard Smith if (LToken.hasUDSuffix()) { 1555d67aea28SRichard Smith Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl); 1556d67aea28SRichard Smith HadError = true; 1557d67aea28SRichard Smith goto retry; 1558d67aea28SRichard Smith } 1559d67aea28SRichard Smith 1560718292f2SDouglas Gregor // Parse the string literal. 1561718292f2SDouglas Gregor LangOptions LangOpts; 15629d5583efSCraig Topper StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target); 1563718292f2SDouglas Gregor if (StringLiteral.hadError) 1564718292f2SDouglas Gregor goto retry; 1565718292f2SDouglas Gregor 1566718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 1567718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 1568718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 1569718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 1570718292f2SDouglas Gregor Saved[Length] = 0; 1571718292f2SDouglas Gregor 1572718292f2SDouglas Gregor // Form the token. 1573718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 1574718292f2SDouglas Gregor Tok.StringData = Saved; 1575718292f2SDouglas Gregor Tok.StringLength = Length; 1576718292f2SDouglas Gregor break; 1577718292f2SDouglas Gregor } 1578718292f2SDouglas Gregor 1579040e1266SRichard Smith case tok::numeric_constant: { 1580040e1266SRichard Smith // We don't support any suffixes or other complications. 1581040e1266SRichard Smith SmallString<32> SpellingBuffer; 1582040e1266SRichard Smith SpellingBuffer.resize(LToken.getLength() + 1); 1583040e1266SRichard Smith const char *Start = SpellingBuffer.data(); 1584040e1266SRichard Smith unsigned Length = 1585040e1266SRichard Smith Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts()); 1586040e1266SRichard Smith uint64_t Value; 1587040e1266SRichard Smith if (StringRef(Start, Length).getAsInteger(0, Value)) { 1588040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1589040e1266SRichard Smith HadError = true; 1590040e1266SRichard Smith goto retry; 1591040e1266SRichard Smith } 1592040e1266SRichard Smith 1593040e1266SRichard Smith Tok.Kind = MMToken::IntegerLiteral; 1594040e1266SRichard Smith Tok.IntegerValue = Value; 1595040e1266SRichard Smith break; 1596040e1266SRichard Smith } 1597040e1266SRichard Smith 1598718292f2SDouglas Gregor case tok::comment: 1599718292f2SDouglas Gregor goto retry; 1600718292f2SDouglas Gregor 16018128f332SRichard Smith case tok::hash: 16028128f332SRichard Smith // A module map can be terminated prematurely by 16038128f332SRichard Smith // #pragma clang module contents 16048128f332SRichard Smith // When building the module, we'll treat the rest of the file as the 16058128f332SRichard Smith // contents of the module. 16068128f332SRichard Smith { 16078128f332SRichard Smith auto NextIsIdent = [&](StringRef Str) -> bool { 16088128f332SRichard Smith L.LexFromRawLexer(LToken); 16098128f332SRichard Smith return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) && 16108128f332SRichard Smith LToken.getRawIdentifier() == Str; 16118128f332SRichard Smith }; 16128128f332SRichard Smith if (NextIsIdent("pragma") && NextIsIdent("clang") && 16138128f332SRichard Smith NextIsIdent("module") && NextIsIdent("contents")) { 16148128f332SRichard Smith Tok.Kind = MMToken::EndOfFile; 16158128f332SRichard Smith break; 16168128f332SRichard Smith } 16178128f332SRichard Smith } 16188128f332SRichard Smith LLVM_FALLTHROUGH; 16198128f332SRichard Smith 1620718292f2SDouglas Gregor default: 16218128f332SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1622718292f2SDouglas Gregor HadError = true; 1623718292f2SDouglas Gregor goto retry; 1624718292f2SDouglas Gregor } 1625718292f2SDouglas Gregor 1626718292f2SDouglas Gregor return Result; 1627718292f2SDouglas Gregor } 1628718292f2SDouglas Gregor 1629718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 1630718292f2SDouglas Gregor unsigned braceDepth = 0; 1631a686e1b0SDouglas Gregor unsigned squareDepth = 0; 1632718292f2SDouglas Gregor do { 1633718292f2SDouglas Gregor switch (Tok.Kind) { 1634718292f2SDouglas Gregor case MMToken::EndOfFile: 1635718292f2SDouglas Gregor return; 1636718292f2SDouglas Gregor 1637718292f2SDouglas Gregor case MMToken::LBrace: 1638a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1639718292f2SDouglas Gregor return; 1640718292f2SDouglas Gregor 1641718292f2SDouglas Gregor ++braceDepth; 1642718292f2SDouglas Gregor break; 1643718292f2SDouglas Gregor 1644a686e1b0SDouglas Gregor case MMToken::LSquare: 1645a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1646a686e1b0SDouglas Gregor return; 1647a686e1b0SDouglas Gregor 1648a686e1b0SDouglas Gregor ++squareDepth; 1649a686e1b0SDouglas Gregor break; 1650a686e1b0SDouglas Gregor 1651718292f2SDouglas Gregor case MMToken::RBrace: 1652718292f2SDouglas Gregor if (braceDepth > 0) 1653718292f2SDouglas Gregor --braceDepth; 1654718292f2SDouglas Gregor else if (Tok.is(K)) 1655718292f2SDouglas Gregor return; 1656718292f2SDouglas Gregor break; 1657718292f2SDouglas Gregor 1658a686e1b0SDouglas Gregor case MMToken::RSquare: 1659a686e1b0SDouglas Gregor if (squareDepth > 0) 1660a686e1b0SDouglas Gregor --squareDepth; 1661a686e1b0SDouglas Gregor else if (Tok.is(K)) 1662a686e1b0SDouglas Gregor return; 1663a686e1b0SDouglas Gregor break; 1664a686e1b0SDouglas Gregor 1665718292f2SDouglas Gregor default: 1666a686e1b0SDouglas Gregor if (braceDepth == 0 && squareDepth == 0 && Tok.is(K)) 1667718292f2SDouglas Gregor return; 1668718292f2SDouglas Gregor break; 1669718292f2SDouglas Gregor } 1670718292f2SDouglas Gregor 1671718292f2SDouglas Gregor consumeToken(); 1672718292f2SDouglas Gregor } while (true); 1673718292f2SDouglas Gregor } 1674718292f2SDouglas Gregor 16759fc8faf9SAdrian Prantl /// Parse a module-id. 1676e7ab3669SDouglas Gregor /// 1677e7ab3669SDouglas Gregor /// module-id: 1678e7ab3669SDouglas Gregor /// identifier 1679e7ab3669SDouglas Gregor /// identifier '.' module-id 1680e7ab3669SDouglas Gregor /// 1681e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise. 1682e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) { 1683e7ab3669SDouglas Gregor Id.clear(); 1684e7ab3669SDouglas Gregor do { 16853cd34c76SDaniel Jasper if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) { 1686adcd0268SBenjamin Kramer Id.push_back( 1687adcd0268SBenjamin Kramer std::make_pair(std::string(Tok.getString()), Tok.getLocation())); 1688e7ab3669SDouglas Gregor consumeToken(); 1689e7ab3669SDouglas Gregor } else { 1690e7ab3669SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 1691e7ab3669SDouglas Gregor return true; 1692e7ab3669SDouglas Gregor } 1693e7ab3669SDouglas Gregor 1694e7ab3669SDouglas Gregor if (!Tok.is(MMToken::Period)) 1695e7ab3669SDouglas Gregor break; 1696e7ab3669SDouglas Gregor 1697e7ab3669SDouglas Gregor consumeToken(); 1698e7ab3669SDouglas Gregor } while (true); 1699e7ab3669SDouglas Gregor 1700e7ab3669SDouglas Gregor return false; 1701e7ab3669SDouglas Gregor } 1702e7ab3669SDouglas Gregor 1703a686e1b0SDouglas Gregor namespace { 1704afd1b1c9SEugene Zelenko 17059fc8faf9SAdrian Prantl /// Enumerates the known attributes. 1706a686e1b0SDouglas Gregor enum AttributeKind { 17079fc8faf9SAdrian Prantl /// An unknown attribute. 1708a686e1b0SDouglas Gregor AT_unknown, 1709afd1b1c9SEugene Zelenko 17109fc8faf9SAdrian Prantl /// The 'system' attribute. 171135b13eceSDouglas Gregor AT_system, 1712afd1b1c9SEugene Zelenko 17139fc8faf9SAdrian Prantl /// The 'extern_c' attribute. 171477944868SRichard Smith AT_extern_c, 1715afd1b1c9SEugene Zelenko 17169fc8faf9SAdrian Prantl /// The 'exhaustive' attribute. 1717ed84df00SBruno Cardoso Lopes AT_exhaustive, 1718afd1b1c9SEugene Zelenko 17199fc8faf9SAdrian Prantl /// The 'no_undeclared_includes' attribute. 1720ed84df00SBruno Cardoso Lopes AT_no_undeclared_includes 1721a686e1b0SDouglas Gregor }; 1722afd1b1c9SEugene Zelenko 1723afd1b1c9SEugene Zelenko } // namespace 1724a686e1b0SDouglas Gregor 172529729919SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra 172629729919SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH 172729729919SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written 172829729919SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits. 17295f11e128SBruno Cardoso Lopes void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc, 17305f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc) { 173129729919SBruno Cardoso Lopes auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical, 17327d29486dSBruno Cardoso Lopes const Module *M, SourceRange ReplLoc) { 173329729919SBruno Cardoso Lopes auto D = Diags.Report(ActiveModule->DefinitionLoc, 173429729919SBruno Cardoso Lopes diag::note_mmap_rename_top_level_private_module); 173529729919SBruno Cardoso Lopes D << BadName << M->Name; 17367d29486dSBruno Cardoso Lopes D << FixItHint::CreateReplacement(ReplLoc, Canonical); 173729729919SBruno Cardoso Lopes }; 173829729919SBruno Cardoso Lopes 173929729919SBruno Cardoso Lopes for (auto E = Map.module_begin(); E != Map.module_end(); ++E) { 174029729919SBruno Cardoso Lopes auto const *M = E->getValue(); 174129729919SBruno Cardoso Lopes if (M->Directory != ActiveModule->Directory) 174229729919SBruno Cardoso Lopes continue; 174329729919SBruno Cardoso Lopes 174429729919SBruno Cardoso Lopes SmallString<128> FullName(ActiveModule->getFullModuleName()); 174529729919SBruno Cardoso Lopes if (!FullName.startswith(M->Name) && !FullName.endswith("Private")) 174629729919SBruno Cardoso Lopes continue; 17475f11e128SBruno Cardoso Lopes SmallString<128> FixedPrivModDecl; 174829729919SBruno Cardoso Lopes SmallString<128> Canonical(M->Name); 174929729919SBruno Cardoso Lopes Canonical.append("_Private"); 175029729919SBruno Cardoso Lopes 175129729919SBruno Cardoso Lopes // Foo.Private -> Foo_Private 175229729919SBruno Cardoso Lopes if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent && 175329729919SBruno Cardoso Lopes M->Name == ActiveModule->Parent->Name) { 175429729919SBruno Cardoso Lopes Diags.Report(ActiveModule->DefinitionLoc, 175529729919SBruno Cardoso Lopes diag::warn_mmap_mismatched_private_submodule) 175629729919SBruno Cardoso Lopes << FullName; 17575f11e128SBruno Cardoso Lopes 17585f11e128SBruno Cardoso Lopes SourceLocation FixItInitBegin = CurrModuleDeclLoc; 17595f11e128SBruno Cardoso Lopes if (FrameworkLoc.isValid()) 17605f11e128SBruno Cardoso Lopes FixItInitBegin = FrameworkLoc; 17615f11e128SBruno Cardoso Lopes if (ExplicitLoc.isValid()) 17625f11e128SBruno Cardoso Lopes FixItInitBegin = ExplicitLoc; 17635f11e128SBruno Cardoso Lopes 17645f11e128SBruno Cardoso Lopes if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework) 17655f11e128SBruno Cardoso Lopes FixedPrivModDecl.append("framework "); 17665f11e128SBruno Cardoso Lopes FixedPrivModDecl.append("module "); 17675f11e128SBruno Cardoso Lopes FixedPrivModDecl.append(Canonical); 17685f11e128SBruno Cardoso Lopes 17695f11e128SBruno Cardoso Lopes GenNoteAndFixIt(FullName, FixedPrivModDecl, M, 17705f11e128SBruno Cardoso Lopes SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc)); 177129729919SBruno Cardoso Lopes continue; 177229729919SBruno Cardoso Lopes } 177329729919SBruno Cardoso Lopes 177429729919SBruno Cardoso Lopes // FooPrivate and whatnots -> Foo_Private 177529729919SBruno Cardoso Lopes if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name && 177629729919SBruno Cardoso Lopes ActiveModule->Name != Canonical) { 177729729919SBruno Cardoso Lopes Diags.Report(ActiveModule->DefinitionLoc, 177829729919SBruno Cardoso Lopes diag::warn_mmap_mismatched_private_module_name) 177929729919SBruno Cardoso Lopes << ActiveModule->Name; 17807d29486dSBruno Cardoso Lopes GenNoteAndFixIt(ActiveModule->Name, Canonical, M, 17817d29486dSBruno Cardoso Lopes SourceRange(ActiveModule->DefinitionLoc)); 178229729919SBruno Cardoso Lopes } 178329729919SBruno Cardoso Lopes } 178429729919SBruno Cardoso Lopes } 178529729919SBruno Cardoso Lopes 17869fc8faf9SAdrian Prantl /// Parse a module declaration. 1787718292f2SDouglas Gregor /// 1788718292f2SDouglas Gregor /// module-declaration: 178997292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 1790a686e1b0SDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt] 1791a686e1b0SDouglas Gregor /// { module-member* } 1792a686e1b0SDouglas Gregor /// 1793718292f2SDouglas Gregor /// module-member: 17941fb5c3a6SDouglas Gregor /// requires-declaration 1795718292f2SDouglas Gregor /// header-declaration 1796e7ab3669SDouglas Gregor /// submodule-declaration 17972b82c2a5SDouglas Gregor /// export-declaration 1798f0b11de2SDouglas Gregor /// export-as-declaration 17996ddfca91SDouglas Gregor /// link-declaration 180073441091SDouglas Gregor /// 180173441091SDouglas Gregor /// submodule-declaration: 180273441091SDouglas Gregor /// module-declaration 180373441091SDouglas Gregor /// inferred-submodule-declaration 1804718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 1805755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 180697292843SDaniel Jasper Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword)); 180797292843SDaniel Jasper if (Tok.is(MMToken::ExternKeyword)) { 180897292843SDaniel Jasper parseExternModuleDecl(); 180997292843SDaniel Jasper return; 181097292843SDaniel Jasper } 181197292843SDaniel Jasper 1812f2161a70SDouglas Gregor // Parse 'explicit' or 'framework' keyword, if present. 1813e7ab3669SDouglas Gregor SourceLocation ExplicitLoc; 18145f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc; 1815718292f2SDouglas Gregor bool Explicit = false; 1816f2161a70SDouglas Gregor bool Framework = false; 1817755b2055SDouglas Gregor 1818f2161a70SDouglas Gregor // Parse 'explicit' keyword, if present. 1819f2161a70SDouglas Gregor if (Tok.is(MMToken::ExplicitKeyword)) { 1820e7ab3669SDouglas Gregor ExplicitLoc = consumeToken(); 1821f2161a70SDouglas Gregor Explicit = true; 1822f2161a70SDouglas Gregor } 1823f2161a70SDouglas Gregor 1824f2161a70SDouglas Gregor // Parse 'framework' keyword, if present. 1825755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 18265f11e128SBruno Cardoso Lopes FrameworkLoc = consumeToken(); 1827755b2055SDouglas Gregor Framework = true; 1828755b2055SDouglas Gregor } 1829718292f2SDouglas Gregor 1830718292f2SDouglas Gregor // Parse 'module' keyword. 1831718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 1832d6343c99SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 1833718292f2SDouglas Gregor consumeToken(); 1834718292f2SDouglas Gregor HadError = true; 1835718292f2SDouglas Gregor return; 1836718292f2SDouglas Gregor } 18379f6020bcSBruno Cardoso Lopes CurrModuleDeclLoc = consumeToken(); // 'module' keyword 1838718292f2SDouglas Gregor 183973441091SDouglas Gregor // If we have a wildcard for the module name, this is an inferred submodule. 184073441091SDouglas Gregor // Parse it. 184173441091SDouglas Gregor if (Tok.is(MMToken::Star)) 18429194a91dSDouglas Gregor return parseInferredModuleDecl(Framework, Explicit); 184373441091SDouglas Gregor 1844718292f2SDouglas Gregor // Parse the module name. 1845e7ab3669SDouglas Gregor ModuleId Id; 1846e7ab3669SDouglas Gregor if (parseModuleId(Id)) { 1847718292f2SDouglas Gregor HadError = true; 1848718292f2SDouglas Gregor return; 1849718292f2SDouglas Gregor } 1850e7ab3669SDouglas Gregor 1851e7ab3669SDouglas Gregor if (ActiveModule) { 1852e7ab3669SDouglas Gregor if (Id.size() > 1) { 1853e7ab3669SDouglas Gregor Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id) 1854e7ab3669SDouglas Gregor << SourceRange(Id.front().second, Id.back().second); 1855e7ab3669SDouglas Gregor 1856e7ab3669SDouglas Gregor HadError = true; 1857e7ab3669SDouglas Gregor return; 1858e7ab3669SDouglas Gregor } 1859e7ab3669SDouglas Gregor } else if (Id.size() == 1 && Explicit) { 1860e7ab3669SDouglas Gregor // Top-level modules can't be explicit. 1861e7ab3669SDouglas Gregor Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level); 1862e7ab3669SDouglas Gregor Explicit = false; 1863e7ab3669SDouglas Gregor ExplicitLoc = SourceLocation(); 1864e7ab3669SDouglas Gregor HadError = true; 1865e7ab3669SDouglas Gregor } 1866e7ab3669SDouglas Gregor 1867e7ab3669SDouglas Gregor Module *PreviousActiveModule = ActiveModule; 1868e7ab3669SDouglas Gregor if (Id.size() > 1) { 1869e7ab3669SDouglas Gregor // This module map defines a submodule. Go find the module of which it 1870e7ab3669SDouglas Gregor // is a submodule. 1871d2d442caSCraig Topper ActiveModule = nullptr; 18724b8a9e95SBen Langmuir const Module *TopLevelModule = nullptr; 1873e7ab3669SDouglas Gregor for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) { 1874e7ab3669SDouglas Gregor if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) { 18754b8a9e95SBen Langmuir if (I == 0) 18764b8a9e95SBen Langmuir TopLevelModule = Next; 1877e7ab3669SDouglas Gregor ActiveModule = Next; 1878e7ab3669SDouglas Gregor continue; 1879e7ab3669SDouglas Gregor } 1880e7ab3669SDouglas Gregor 1881e7ab3669SDouglas Gregor if (ActiveModule) { 1882e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified) 18835b5d21eaSRichard Smith << Id[I].first 18845b5d21eaSRichard Smith << ActiveModule->getTopLevelModule()->getFullModuleName(); 1885e7ab3669SDouglas Gregor } else { 1886e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_expected_module_name); 1887e7ab3669SDouglas Gregor } 1888e7ab3669SDouglas Gregor HadError = true; 1889e7ab3669SDouglas Gregor return; 1890e7ab3669SDouglas Gregor } 18914b8a9e95SBen Langmuir 18924b8a9e95SBen Langmuir if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) { 18934b8a9e95SBen Langmuir assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) && 18944b8a9e95SBen Langmuir "submodule defined in same file as 'module *' that allowed its " 18954b8a9e95SBen Langmuir "top-level module"); 18964b8a9e95SBen Langmuir Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile); 18974b8a9e95SBen Langmuir } 1898e7ab3669SDouglas Gregor } 1899e7ab3669SDouglas Gregor 1900e7ab3669SDouglas Gregor StringRef ModuleName = Id.back().first; 1901e7ab3669SDouglas Gregor SourceLocation ModuleNameLoc = Id.back().second; 1902718292f2SDouglas Gregor 1903a686e1b0SDouglas Gregor // Parse the optional attribute list. 19044442605fSBill Wendling Attributes Attrs; 19055d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 19065d29dee0SDavide Italiano return; 19075d29dee0SDavide Italiano 1908718292f2SDouglas Gregor // Parse the opening brace. 1909718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 1910718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 1911718292f2SDouglas Gregor << ModuleName; 1912718292f2SDouglas Gregor HadError = true; 1913718292f2SDouglas Gregor return; 1914718292f2SDouglas Gregor } 1915718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 1916718292f2SDouglas Gregor 1917718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 19188587dfd9SBruno Cardoso Lopes Module *ShadowingModule = nullptr; 1919eb90e830SDouglas Gregor if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { 19204a3751ffSRichard Smith // We might see a (re)definition of a module that we already have a 19214a3751ffSRichard Smith // definition for in two cases: 19224a3751ffSRichard Smith // - If we loaded one definition from an AST file and we've just found a 19234a3751ffSRichard Smith // corresponding definition in a module map file, or 19244a3751ffSRichard Smith bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid(); 19254a3751ffSRichard Smith // - If we're building a (preprocessed) module and we've just loaded the 19264a3751ffSRichard Smith // module map file from which it was created. 19274a3751ffSRichard Smith bool ParsedAsMainInput = 19284a3751ffSRichard Smith Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap && 19294a3751ffSRichard Smith Map.LangOpts.CurrentModule == ModuleName && 19304a3751ffSRichard Smith SourceMgr.getDecomposedLoc(ModuleNameLoc).first != 19314a3751ffSRichard Smith SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first; 19324a3751ffSRichard Smith if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) { 1933fcc54a3bSDouglas Gregor // Skip the module definition. 1934fcc54a3bSDouglas Gregor skipUntil(MMToken::RBrace); 1935fcc54a3bSDouglas Gregor if (Tok.is(MMToken::RBrace)) 1936fcc54a3bSDouglas Gregor consumeToken(); 1937fcc54a3bSDouglas Gregor else { 1938fcc54a3bSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 1939fcc54a3bSDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 1940fcc54a3bSDouglas Gregor HadError = true; 1941fcc54a3bSDouglas Gregor } 1942fcc54a3bSDouglas Gregor return; 1943fcc54a3bSDouglas Gregor } 1944fcc54a3bSDouglas Gregor 1945c192d194SBruno Cardoso Lopes if (!Existing->Parent && Map.mayShadowNewModule(Existing)) { 19468587dfd9SBruno Cardoso Lopes ShadowingModule = Existing; 19478587dfd9SBruno Cardoso Lopes } else { 19488587dfd9SBruno Cardoso Lopes // This is not a shawdowed module decl, it is an illegal redefinition. 1949718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 1950718292f2SDouglas Gregor << ModuleName; 1951eb90e830SDouglas Gregor Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition); 1952718292f2SDouglas Gregor 1953718292f2SDouglas Gregor // Skip the module definition. 1954718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 1955718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 1956718292f2SDouglas Gregor consumeToken(); 1957718292f2SDouglas Gregor 1958718292f2SDouglas Gregor HadError = true; 1959718292f2SDouglas Gregor return; 1960718292f2SDouglas Gregor } 19618587dfd9SBruno Cardoso Lopes } 1962718292f2SDouglas Gregor 1963718292f2SDouglas Gregor // Start defining this module. 19648587dfd9SBruno Cardoso Lopes if (ShadowingModule) { 19658587dfd9SBruno Cardoso Lopes ActiveModule = 19668587dfd9SBruno Cardoso Lopes Map.createShadowedModule(ModuleName, Framework, ShadowingModule); 19678587dfd9SBruno Cardoso Lopes } else { 1968c192d194SBruno Cardoso Lopes ActiveModule = 1969c192d194SBruno Cardoso Lopes Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit) 19708587dfd9SBruno Cardoso Lopes .first; 19718587dfd9SBruno Cardoso Lopes } 19728587dfd9SBruno Cardoso Lopes 1973eb90e830SDouglas Gregor ActiveModule->DefinitionLoc = ModuleNameLoc; 1974963c5535SDouglas Gregor if (Attrs.IsSystem || IsSystem) 1975a686e1b0SDouglas Gregor ActiveModule->IsSystem = true; 197677944868SRichard Smith if (Attrs.IsExternC) 197777944868SRichard Smith ActiveModule->IsExternC = true; 1978ed84df00SBruno Cardoso Lopes if (Attrs.NoUndeclaredIncludes || 1979ed84df00SBruno Cardoso Lopes (!ActiveModule->Parent && ModuleName == "Darwin")) 1980ed84df00SBruno Cardoso Lopes ActiveModule->NoUndeclaredIncludes = true; 19813c1a41adSRichard Smith ActiveModule->Directory = Directory; 1982718292f2SDouglas Gregor 198390b0a1fcSJordan Rose StringRef MapFileName(ModuleMapFile->getName()); 198490b0a1fcSJordan Rose if (MapFileName.endswith("module.private.modulemap") || 198590b0a1fcSJordan Rose MapFileName.endswith("module_private.map")) { 198690b0a1fcSJordan Rose ActiveModule->ModuleMapIsPrivate = true; 198790b0a1fcSJordan Rose } 198829729919SBruno Cardoso Lopes 198929729919SBruno Cardoso Lopes // Private modules named as FooPrivate, Foo.Private or similar are likely a 199029729919SBruno Cardoso Lopes // user error; provide warnings, notes and fixits to direct users to use 199129729919SBruno Cardoso Lopes // Foo_Private instead. 199229729919SBruno Cardoso Lopes SourceLocation StartLoc = 199329729919SBruno Cardoso Lopes SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()); 199429729919SBruno Cardoso Lopes if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && 199529729919SBruno Cardoso Lopes !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule, 199629729919SBruno Cardoso Lopes StartLoc) && 199729729919SBruno Cardoso Lopes !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name, 199829729919SBruno Cardoso Lopes StartLoc) && 199990b0a1fcSJordan Rose ActiveModule->ModuleMapIsPrivate) 20005f11e128SBruno Cardoso Lopes diagnosePrivateModules(ExplicitLoc, FrameworkLoc); 20014d867640SGraydon Hoare 2002718292f2SDouglas Gregor bool Done = false; 2003718292f2SDouglas Gregor do { 2004718292f2SDouglas Gregor switch (Tok.Kind) { 2005718292f2SDouglas Gregor case MMToken::EndOfFile: 2006718292f2SDouglas Gregor case MMToken::RBrace: 2007718292f2SDouglas Gregor Done = true; 2008718292f2SDouglas Gregor break; 2009718292f2SDouglas Gregor 201035b13eceSDouglas Gregor case MMToken::ConfigMacros: 201135b13eceSDouglas Gregor parseConfigMacros(); 201235b13eceSDouglas Gregor break; 201335b13eceSDouglas Gregor 2014fb912657SDouglas Gregor case MMToken::Conflict: 2015fb912657SDouglas Gregor parseConflict(); 2016fb912657SDouglas Gregor break; 2017fb912657SDouglas Gregor 2018718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 201997292843SDaniel Jasper case MMToken::ExternKeyword: 2020f2161a70SDouglas Gregor case MMToken::FrameworkKeyword: 2021718292f2SDouglas Gregor case MMToken::ModuleKeyword: 2022718292f2SDouglas Gregor parseModuleDecl(); 2023718292f2SDouglas Gregor break; 2024718292f2SDouglas Gregor 20252b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 20262b82c2a5SDouglas Gregor parseExportDecl(); 20272b82c2a5SDouglas Gregor break; 20282b82c2a5SDouglas Gregor 2029f0b11de2SDouglas Gregor case MMToken::ExportAsKeyword: 2030f0b11de2SDouglas Gregor parseExportAsDecl(); 2031f0b11de2SDouglas Gregor break; 2032f0b11de2SDouglas Gregor 2033ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 2034ba7f2f71SDaniel Jasper parseUseDecl(); 2035ba7f2f71SDaniel Jasper break; 2036ba7f2f71SDaniel Jasper 20371fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 20381fb5c3a6SDouglas Gregor parseRequiresDecl(); 20391fb5c3a6SDouglas Gregor break; 20401fb5c3a6SDouglas Gregor 2041202210b3SRichard Smith case MMToken::TextualKeyword: 2042202210b3SRichard Smith parseHeaderDecl(MMToken::TextualKeyword, consumeToken()); 2043306d8920SRichard Smith break; 2044306d8920SRichard Smith 2045524e33e1SDouglas Gregor case MMToken::UmbrellaKeyword: { 2046524e33e1SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 2047524e33e1SDouglas Gregor if (Tok.is(MMToken::HeaderKeyword)) 2048b53e5483SLawrence Crowl parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc); 2049524e33e1SDouglas Gregor else 2050524e33e1SDouglas Gregor parseUmbrellaDirDecl(UmbrellaLoc); 2051718292f2SDouglas Gregor break; 2052524e33e1SDouglas Gregor } 2053718292f2SDouglas Gregor 2054202210b3SRichard Smith case MMToken::ExcludeKeyword: 2055202210b3SRichard Smith parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken()); 205659527666SDouglas Gregor break; 205759527666SDouglas Gregor 2058202210b3SRichard Smith case MMToken::PrivateKeyword: 2059202210b3SRichard Smith parseHeaderDecl(MMToken::PrivateKeyword, consumeToken()); 2060b53e5483SLawrence Crowl break; 2061b53e5483SLawrence Crowl 2062322f633cSDouglas Gregor case MMToken::HeaderKeyword: 2063202210b3SRichard Smith parseHeaderDecl(MMToken::HeaderKeyword, consumeToken()); 2064718292f2SDouglas Gregor break; 2065718292f2SDouglas Gregor 20666ddfca91SDouglas Gregor case MMToken::LinkKeyword: 20676ddfca91SDouglas Gregor parseLinkDecl(); 20686ddfca91SDouglas Gregor break; 20696ddfca91SDouglas Gregor 2070718292f2SDouglas Gregor default: 2071718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 2072718292f2SDouglas Gregor consumeToken(); 2073718292f2SDouglas Gregor break; 2074718292f2SDouglas Gregor } 2075718292f2SDouglas Gregor } while (!Done); 2076718292f2SDouglas Gregor 2077718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 2078718292f2SDouglas Gregor consumeToken(); 2079718292f2SDouglas Gregor else { 2080718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 2081718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 2082718292f2SDouglas Gregor HadError = true; 2083718292f2SDouglas Gregor } 2084718292f2SDouglas Gregor 208511dfe6feSDouglas Gregor // If the active module is a top-level framework, and there are no link 208611dfe6feSDouglas Gregor // libraries, automatically link against the framework. 208711dfe6feSDouglas Gregor if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() && 208811dfe6feSDouglas Gregor ActiveModule->LinkLibraries.empty()) { 208911dfe6feSDouglas Gregor inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager()); 209011dfe6feSDouglas Gregor } 209111dfe6feSDouglas Gregor 2092ec8c9752SBen Langmuir // If the module meets all requirements but is still unavailable, mark the 2093ec8c9752SBen Langmuir // whole tree as unavailable to prevent it from building. 2094ec8c9752SBen Langmuir if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement && 2095ec8c9752SBen Langmuir ActiveModule->Parent) { 2096ec8c9752SBen Langmuir ActiveModule->getTopLevelModule()->markUnavailable(); 2097ec8c9752SBen Langmuir ActiveModule->getTopLevelModule()->MissingHeaders.append( 2098ec8c9752SBen Langmuir ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end()); 2099ec8c9752SBen Langmuir } 2100ec8c9752SBen Langmuir 2101e7ab3669SDouglas Gregor // We're done parsing this module. Pop back to the previous module. 2102e7ab3669SDouglas Gregor ActiveModule = PreviousActiveModule; 2103718292f2SDouglas Gregor } 2104718292f2SDouglas Gregor 21059fc8faf9SAdrian Prantl /// Parse an extern module declaration. 210697292843SDaniel Jasper /// 210797292843SDaniel Jasper /// extern module-declaration: 210897292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 210997292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() { 211097292843SDaniel Jasper assert(Tok.is(MMToken::ExternKeyword)); 2111ae6df27eSRichard Smith SourceLocation ExternLoc = consumeToken(); // 'extern' keyword 211297292843SDaniel Jasper 211397292843SDaniel Jasper // Parse 'module' keyword. 211497292843SDaniel Jasper if (!Tok.is(MMToken::ModuleKeyword)) { 211597292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 211697292843SDaniel Jasper consumeToken(); 211797292843SDaniel Jasper HadError = true; 211897292843SDaniel Jasper return; 211997292843SDaniel Jasper } 212097292843SDaniel Jasper consumeToken(); // 'module' keyword 212197292843SDaniel Jasper 212297292843SDaniel Jasper // Parse the module name. 212397292843SDaniel Jasper ModuleId Id; 212497292843SDaniel Jasper if (parseModuleId(Id)) { 212597292843SDaniel Jasper HadError = true; 212697292843SDaniel Jasper return; 212797292843SDaniel Jasper } 212897292843SDaniel Jasper 212997292843SDaniel Jasper // Parse the referenced module map file name. 213097292843SDaniel Jasper if (!Tok.is(MMToken::StringLiteral)) { 213197292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file); 213297292843SDaniel Jasper HadError = true; 213397292843SDaniel Jasper return; 213497292843SDaniel Jasper } 2135adcd0268SBenjamin Kramer std::string FileName = std::string(Tok.getString()); 213697292843SDaniel Jasper consumeToken(); // filename 213797292843SDaniel Jasper 213897292843SDaniel Jasper StringRef FileNameRef = FileName; 213997292843SDaniel Jasper SmallString<128> ModuleMapFileName; 214097292843SDaniel Jasper if (llvm::sys::path::is_relative(FileNameRef)) { 214197292843SDaniel Jasper ModuleMapFileName += Directory->getName(); 214297292843SDaniel Jasper llvm::sys::path::append(ModuleMapFileName, FileName); 214392e1b62dSYaron Keren FileNameRef = ModuleMapFileName; 214497292843SDaniel Jasper } 21458d323d15SHarlan Haskins if (auto File = SourceMgr.getFileManager().getFile(FileNameRef)) 21469acb99e3SRichard Smith Map.parseModuleMapFile( 21478d323d15SHarlan Haskins *File, /*IsSystem=*/false, 21489acb99e3SRichard Smith Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd 21499acb99e3SRichard Smith ? Directory 21508d323d15SHarlan Haskins : (*File)->getDir(), 2151c192d194SBruno Cardoso Lopes FileID(), nullptr, ExternLoc); 215297292843SDaniel Jasper } 215397292843SDaniel Jasper 21547ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M. 21557ff29148SBen Langmuir /// 21567ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system 21577ff29148SBen Langmuir /// module map files: 21587ff29148SBen Langmuir /// 21597ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which 21607ff29148SBen Langmuir /// should really be mapped to 'textual' now that we have this feature. We 21617ff29148SBen Langmuir /// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to 21627ff29148SBen Langmuir /// true. Later, this bit will be used to map all the headers inside this 21637ff29148SBen Langmuir /// module to 'textual'. 21647ff29148SBen Langmuir /// 21657ff29148SBen Langmuir /// This affects Darwin.C.excluded (for assert.h) and Tcl.Private. 21667ff29148SBen Langmuir /// 21677ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement 21687ff29148SBen Langmuir /// was never correct and causes issues now that we check it, so drop it. 21697ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature, 21707ff29148SBen Langmuir bool &IsRequiresExcludedHack) { 21718013e81dSBenjamin Kramer if (Feature == "excluded" && 21728013e81dSBenjamin Kramer (M->fullModuleNameIs({"Darwin", "C", "excluded"}) || 21738013e81dSBenjamin Kramer M->fullModuleNameIs({"Tcl", "Private"}))) { 21747ff29148SBen Langmuir IsRequiresExcludedHack = true; 21757ff29148SBen Langmuir return false; 21768013e81dSBenjamin Kramer } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) { 21777ff29148SBen Langmuir return false; 21787ff29148SBen Langmuir } 21797ff29148SBen Langmuir 21807ff29148SBen Langmuir return true; 21817ff29148SBen Langmuir } 21827ff29148SBen Langmuir 21839fc8faf9SAdrian Prantl /// Parse a requires declaration. 21841fb5c3a6SDouglas Gregor /// 21851fb5c3a6SDouglas Gregor /// requires-declaration: 21861fb5c3a6SDouglas Gregor /// 'requires' feature-list 21871fb5c3a6SDouglas Gregor /// 21881fb5c3a6SDouglas Gregor /// feature-list: 2189a3feee2aSRichard Smith /// feature ',' feature-list 2190a3feee2aSRichard Smith /// feature 2191a3feee2aSRichard Smith /// 2192a3feee2aSRichard Smith /// feature: 2193a3feee2aSRichard Smith /// '!'[opt] identifier 21941fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() { 21951fb5c3a6SDouglas Gregor assert(Tok.is(MMToken::RequiresKeyword)); 21961fb5c3a6SDouglas Gregor 21971fb5c3a6SDouglas Gregor // Parse 'requires' keyword. 21981fb5c3a6SDouglas Gregor consumeToken(); 21991fb5c3a6SDouglas Gregor 22001fb5c3a6SDouglas Gregor // Parse the feature-list. 22011fb5c3a6SDouglas Gregor do { 2202a3feee2aSRichard Smith bool RequiredState = true; 2203a3feee2aSRichard Smith if (Tok.is(MMToken::Exclaim)) { 2204a3feee2aSRichard Smith RequiredState = false; 2205a3feee2aSRichard Smith consumeToken(); 2206a3feee2aSRichard Smith } 2207a3feee2aSRichard Smith 22081fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 22091fb5c3a6SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature); 22101fb5c3a6SDouglas Gregor HadError = true; 22111fb5c3a6SDouglas Gregor return; 22121fb5c3a6SDouglas Gregor } 22131fb5c3a6SDouglas Gregor 22141fb5c3a6SDouglas Gregor // Consume the feature name. 2215adcd0268SBenjamin Kramer std::string Feature = std::string(Tok.getString()); 22161fb5c3a6SDouglas Gregor consumeToken(); 22171fb5c3a6SDouglas Gregor 22187ff29148SBen Langmuir bool IsRequiresExcludedHack = false; 22197ff29148SBen Langmuir bool ShouldAddRequirement = 22207ff29148SBen Langmuir shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack); 22217ff29148SBen Langmuir 22227ff29148SBen Langmuir if (IsRequiresExcludedHack) 22237ff29148SBen Langmuir UsesRequiresExcludedHack.insert(ActiveModule); 22247ff29148SBen Langmuir 22257ff29148SBen Langmuir if (ShouldAddRequirement) { 22261fb5c3a6SDouglas Gregor // Add this feature. 22277ff29148SBen Langmuir ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts, 22287ff29148SBen Langmuir *Map.Target); 22297ff29148SBen Langmuir } 22301fb5c3a6SDouglas Gregor 22311fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Comma)) 22321fb5c3a6SDouglas Gregor break; 22331fb5c3a6SDouglas Gregor 22341fb5c3a6SDouglas Gregor // Consume the comma. 22351fb5c3a6SDouglas Gregor consumeToken(); 22361fb5c3a6SDouglas Gregor } while (true); 22371fb5c3a6SDouglas Gregor } 22381fb5c3a6SDouglas Gregor 22399fc8faf9SAdrian Prantl /// Parse a header declaration. 2240718292f2SDouglas Gregor /// 2241718292f2SDouglas Gregor /// header-declaration: 2242306d8920SRichard Smith /// 'textual'[opt] 'header' string-literal 2243202210b3SRichard Smith /// 'private' 'textual'[opt] 'header' string-literal 2244202210b3SRichard Smith /// 'exclude' 'header' string-literal 2245202210b3SRichard Smith /// 'umbrella' 'header' string-literal 2246306d8920SRichard Smith /// 2247306d8920SRichard Smith /// FIXME: Support 'private textual header'. 2248b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, 2249b53e5483SLawrence Crowl SourceLocation LeadingLoc) { 2250202210b3SRichard Smith // We've already consumed the first token. 2251202210b3SRichard Smith ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader; 2252202210b3SRichard Smith if (LeadingToken == MMToken::PrivateKeyword) { 2253202210b3SRichard Smith Role = ModuleMap::PrivateHeader; 2254202210b3SRichard Smith // 'private' may optionally be followed by 'textual'. 2255202210b3SRichard Smith if (Tok.is(MMToken::TextualKeyword)) { 2256202210b3SRichard Smith LeadingToken = Tok.Kind; 22571871ed3dSBenjamin Kramer consumeToken(); 2258202210b3SRichard Smith } 2259202210b3SRichard Smith } 22607ff29148SBen Langmuir 2261202210b3SRichard Smith if (LeadingToken == MMToken::TextualKeyword) 2262202210b3SRichard Smith Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 2263202210b3SRichard Smith 22647ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 22657ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 22667ff29148SBen Langmuir // Module::UsesRequiresExcludedHack). 22677ff29148SBen Langmuir Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 22687ff29148SBen Langmuir } 22697ff29148SBen Langmuir 2270202210b3SRichard Smith if (LeadingToken != MMToken::HeaderKeyword) { 2271202210b3SRichard Smith if (!Tok.is(MMToken::HeaderKeyword)) { 2272202210b3SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2273202210b3SRichard Smith << (LeadingToken == MMToken::PrivateKeyword ? "private" : 2274202210b3SRichard Smith LeadingToken == MMToken::ExcludeKeyword ? "exclude" : 2275202210b3SRichard Smith LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella"); 2276202210b3SRichard Smith return; 2277202210b3SRichard Smith } 2278202210b3SRichard Smith consumeToken(); 2279202210b3SRichard Smith } 2280718292f2SDouglas Gregor 2281718292f2SDouglas Gregor // Parse the header name. 2282718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2283718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2284718292f2SDouglas Gregor << "header"; 2285718292f2SDouglas Gregor HadError = true; 2286718292f2SDouglas Gregor return; 2287718292f2SDouglas Gregor } 22883c1a41adSRichard Smith Module::UnresolvedHeaderDirective Header; 2289adcd0268SBenjamin Kramer Header.FileName = std::string(Tok.getString()); 22900761a8a0SDaniel Jasper Header.FileNameLoc = consumeToken(); 22911d60987fSRichard Smith Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword; 2292040e1266SRichard Smith Header.Kind = 2293040e1266SRichard Smith (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded 2294040e1266SRichard Smith : Map.headerRoleToKind(Role)); 2295718292f2SDouglas Gregor 2296524e33e1SDouglas Gregor // Check whether we already have an umbrella. 22971d60987fSRichard Smith if (Header.IsUmbrella && ActiveModule->Umbrella) { 22980761a8a0SDaniel Jasper Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) 2299524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2300322f633cSDouglas Gregor HadError = true; 2301322f633cSDouglas Gregor return; 2302322f633cSDouglas Gregor } 2303322f633cSDouglas Gregor 2304040e1266SRichard Smith // If we were given stat information, parse it so we can skip looking for 2305040e1266SRichard Smith // the file. 2306040e1266SRichard Smith if (Tok.is(MMToken::LBrace)) { 2307040e1266SRichard Smith SourceLocation LBraceLoc = consumeToken(); 23083ec6663bSDouglas Gregor 2309040e1266SRichard Smith while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) { 2310040e1266SRichard Smith enum Attribute { Size, ModTime, Unknown }; 2311040e1266SRichard Smith StringRef Str = Tok.getString(); 2312040e1266SRichard Smith SourceLocation Loc = consumeToken(); 2313040e1266SRichard Smith switch (llvm::StringSwitch<Attribute>(Str) 2314040e1266SRichard Smith .Case("size", Size) 2315040e1266SRichard Smith .Case("mtime", ModTime) 2316040e1266SRichard Smith .Default(Unknown)) { 2317040e1266SRichard Smith case Size: 2318040e1266SRichard Smith if (Header.Size) 2319040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2320040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2321040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2322040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2323040e1266SRichard Smith skipUntil(MMToken::RBrace); 2324040e1266SRichard Smith break; 2325040e1266SRichard Smith } 2326040e1266SRichard Smith Header.Size = Tok.getInteger(); 2327040e1266SRichard Smith consumeToken(); 2328040e1266SRichard Smith break; 2329040e1266SRichard Smith 2330040e1266SRichard Smith case ModTime: 2331040e1266SRichard Smith if (Header.ModTime) 2332040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2333040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2334040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2335040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2336040e1266SRichard Smith skipUntil(MMToken::RBrace); 2337040e1266SRichard Smith break; 2338040e1266SRichard Smith } 2339040e1266SRichard Smith Header.ModTime = Tok.getInteger(); 2340040e1266SRichard Smith consumeToken(); 2341040e1266SRichard Smith break; 2342040e1266SRichard Smith 2343040e1266SRichard Smith case Unknown: 2344040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_expected_header_attribute); 2345040e1266SRichard Smith skipUntil(MMToken::RBrace); 2346040e1266SRichard Smith break; 2347040e1266SRichard Smith } 23483ec6663bSDouglas Gregor } 23495257fc63SDouglas Gregor 2350040e1266SRichard Smith if (Tok.is(MMToken::RBrace)) 2351040e1266SRichard Smith consumeToken(); 2352040e1266SRichard Smith else { 2353040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 2354040e1266SRichard Smith Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 2355322f633cSDouglas Gregor HadError = true; 2356322f633cSDouglas Gregor } 23570101b540SHans Wennborg } 235825d50758SRichard Smith 23599f6020bcSBruno Cardoso Lopes bool NeedsFramework = false; 23609f6020bcSBruno Cardoso Lopes Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework); 23619f6020bcSBruno Cardoso Lopes 23629f6020bcSBruno Cardoso Lopes if (NeedsFramework && ActiveModule) 23639f6020bcSBruno Cardoso Lopes Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword) 23649f6020bcSBruno Cardoso Lopes << ActiveModule->getFullModuleName() 23659f6020bcSBruno Cardoso Lopes << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module"); 2366718292f2SDouglas Gregor } 2367718292f2SDouglas Gregor 236841f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A, 236941f81994SBen Langmuir const Module::Header *B) { 237041f81994SBen Langmuir return A->NameAsWritten.compare(B->NameAsWritten); 237141f81994SBen Langmuir } 237241f81994SBen Langmuir 23739fc8faf9SAdrian Prantl /// Parse an umbrella directory declaration. 2374524e33e1SDouglas Gregor /// 2375524e33e1SDouglas Gregor /// umbrella-dir-declaration: 2376524e33e1SDouglas Gregor /// umbrella string-literal 2377524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { 2378524e33e1SDouglas Gregor // Parse the directory name. 2379524e33e1SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2380524e33e1SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2381524e33e1SDouglas Gregor << "umbrella"; 2382524e33e1SDouglas Gregor HadError = true; 2383524e33e1SDouglas Gregor return; 2384524e33e1SDouglas Gregor } 2385524e33e1SDouglas Gregor 2386adcd0268SBenjamin Kramer std::string DirName = std::string(Tok.getString()); 2387524e33e1SDouglas Gregor SourceLocation DirNameLoc = consumeToken(); 2388524e33e1SDouglas Gregor 2389524e33e1SDouglas Gregor // Check whether we already have an umbrella. 2390524e33e1SDouglas Gregor if (ActiveModule->Umbrella) { 2391524e33e1SDouglas Gregor Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash) 2392524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2393524e33e1SDouglas Gregor HadError = true; 2394524e33e1SDouglas Gregor return; 2395524e33e1SDouglas Gregor } 2396524e33e1SDouglas Gregor 2397524e33e1SDouglas Gregor // Look for this file. 2398d2d442caSCraig Topper const DirectoryEntry *Dir = nullptr; 23998d323d15SHarlan Haskins if (llvm::sys::path::is_absolute(DirName)) { 24008d323d15SHarlan Haskins if (auto D = SourceMgr.getFileManager().getDirectory(DirName)) 24018d323d15SHarlan Haskins Dir = *D; 24028d323d15SHarlan Haskins } else { 24032c1dd271SDylan Noblesmith SmallString<128> PathName; 2404524e33e1SDouglas Gregor PathName = Directory->getName(); 2405524e33e1SDouglas Gregor llvm::sys::path::append(PathName, DirName); 24068d323d15SHarlan Haskins if (auto D = SourceMgr.getFileManager().getDirectory(PathName)) 24078d323d15SHarlan Haskins Dir = *D; 2408524e33e1SDouglas Gregor } 2409524e33e1SDouglas Gregor 2410524e33e1SDouglas Gregor if (!Dir) { 2411a0320b97SVassil Vassilev Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found) 2412524e33e1SDouglas Gregor << DirName; 2413524e33e1SDouglas Gregor return; 2414524e33e1SDouglas Gregor } 2415524e33e1SDouglas Gregor 24167ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 24177ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 24187ff29148SBen Langmuir // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the 24197ff29148SBen Langmuir // directory is relatively expensive, in practice this only applies to the 24207ff29148SBen Langmuir // uncommonly used Tcl module on Darwin platforms. 24217ff29148SBen Langmuir std::error_code EC; 24227ff29148SBen Langmuir SmallVector<Module::Header, 6> Headers; 2423fc51490bSJonas Devlieghere llvm::vfs::FileSystem &FS = 2424db8a7422SDuncan P. N. Exon Smith SourceMgr.getFileManager().getVirtualFileSystem(); 2425fc51490bSJonas Devlieghere for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E; 24267ff29148SBen Langmuir I != E && !EC; I.increment(EC)) { 24278d323d15SHarlan Haskins if (auto FE = SourceMgr.getFileManager().getFile(I->path())) { 2428adcd0268SBenjamin Kramer Module::Header Header = {std::string(I->path()), *FE}; 24297ff29148SBen Langmuir Headers.push_back(std::move(Header)); 24307ff29148SBen Langmuir } 24317ff29148SBen Langmuir } 24327ff29148SBen Langmuir 24337ff29148SBen Langmuir // Sort header paths so that the pcm doesn't depend on iteration order. 243441f81994SBen Langmuir llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders); 243541f81994SBen Langmuir 24367ff29148SBen Langmuir for (auto &Header : Headers) 24377ff29148SBen Langmuir Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader); 24387ff29148SBen Langmuir return; 24397ff29148SBen Langmuir } 24407ff29148SBen Langmuir 2441524e33e1SDouglas Gregor if (Module *OwningModule = Map.UmbrellaDirs[Dir]) { 2442524e33e1SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 2443524e33e1SDouglas Gregor << OwningModule->getFullModuleName(); 2444524e33e1SDouglas Gregor HadError = true; 2445524e33e1SDouglas Gregor return; 2446524e33e1SDouglas Gregor } 2447524e33e1SDouglas Gregor 2448524e33e1SDouglas Gregor // Record this umbrella directory. 24492b63d15fSRichard Smith Map.setUmbrellaDir(ActiveModule, Dir, DirName); 2450524e33e1SDouglas Gregor } 2451524e33e1SDouglas Gregor 24529fc8faf9SAdrian Prantl /// Parse a module export declaration. 24532b82c2a5SDouglas Gregor /// 24542b82c2a5SDouglas Gregor /// export-declaration: 24552b82c2a5SDouglas Gregor /// 'export' wildcard-module-id 24562b82c2a5SDouglas Gregor /// 24572b82c2a5SDouglas Gregor /// wildcard-module-id: 24582b82c2a5SDouglas Gregor /// identifier 24592b82c2a5SDouglas Gregor /// '*' 24602b82c2a5SDouglas Gregor /// identifier '.' wildcard-module-id 24612b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() { 24622b82c2a5SDouglas Gregor assert(Tok.is(MMToken::ExportKeyword)); 24632b82c2a5SDouglas Gregor SourceLocation ExportLoc = consumeToken(); 24642b82c2a5SDouglas Gregor 24652b82c2a5SDouglas Gregor // Parse the module-id with an optional wildcard at the end. 24662b82c2a5SDouglas Gregor ModuleId ParsedModuleId; 24672b82c2a5SDouglas Gregor bool Wildcard = false; 24682b82c2a5SDouglas Gregor do { 2469306d8920SRichard Smith // FIXME: Support string-literal module names here. 24702b82c2a5SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 2471adcd0268SBenjamin Kramer ParsedModuleId.push_back( 2472adcd0268SBenjamin Kramer std::make_pair(std::string(Tok.getString()), Tok.getLocation())); 24732b82c2a5SDouglas Gregor consumeToken(); 24742b82c2a5SDouglas Gregor 24752b82c2a5SDouglas Gregor if (Tok.is(MMToken::Period)) { 24762b82c2a5SDouglas Gregor consumeToken(); 24772b82c2a5SDouglas Gregor continue; 24782b82c2a5SDouglas Gregor } 24792b82c2a5SDouglas Gregor 24802b82c2a5SDouglas Gregor break; 24812b82c2a5SDouglas Gregor } 24822b82c2a5SDouglas Gregor 24832b82c2a5SDouglas Gregor if(Tok.is(MMToken::Star)) { 24842b82c2a5SDouglas Gregor Wildcard = true; 2485f5eedd05SDouglas Gregor consumeToken(); 24862b82c2a5SDouglas Gregor break; 24872b82c2a5SDouglas Gregor } 24882b82c2a5SDouglas Gregor 2489ba7f2f71SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_module_id); 24902b82c2a5SDouglas Gregor HadError = true; 24912b82c2a5SDouglas Gregor return; 24922b82c2a5SDouglas Gregor } while (true); 24932b82c2a5SDouglas Gregor 24942b82c2a5SDouglas Gregor Module::UnresolvedExportDecl Unresolved = { 24952b82c2a5SDouglas Gregor ExportLoc, ParsedModuleId, Wildcard 24962b82c2a5SDouglas Gregor }; 24972b82c2a5SDouglas Gregor ActiveModule->UnresolvedExports.push_back(Unresolved); 24982b82c2a5SDouglas Gregor } 24992b82c2a5SDouglas Gregor 25009fc8faf9SAdrian Prantl /// Parse a module export_as declaration. 2501f0b11de2SDouglas Gregor /// 2502f0b11de2SDouglas Gregor /// export-as-declaration: 2503f0b11de2SDouglas Gregor /// 'export_as' identifier 2504f0b11de2SDouglas Gregor void ModuleMapParser::parseExportAsDecl() { 2505f0b11de2SDouglas Gregor assert(Tok.is(MMToken::ExportAsKeyword)); 2506f0b11de2SDouglas Gregor consumeToken(); 2507f0b11de2SDouglas Gregor 2508f0b11de2SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 2509f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_module_id); 2510f0b11de2SDouglas Gregor HadError = true; 2511f0b11de2SDouglas Gregor return; 2512f0b11de2SDouglas Gregor } 2513f0b11de2SDouglas Gregor 2514f0b11de2SDouglas Gregor if (ActiveModule->Parent) { 2515f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as); 2516f0b11de2SDouglas Gregor consumeToken(); 2517f0b11de2SDouglas Gregor return; 2518f0b11de2SDouglas Gregor } 2519f0b11de2SDouglas Gregor 2520f0b11de2SDouglas Gregor if (!ActiveModule->ExportAsModule.empty()) { 2521f0b11de2SDouglas Gregor if (ActiveModule->ExportAsModule == Tok.getString()) { 2522f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as) 2523f0b11de2SDouglas Gregor << ActiveModule->Name << Tok.getString(); 2524f0b11de2SDouglas Gregor } else { 2525f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as) 2526f0b11de2SDouglas Gregor << ActiveModule->Name << ActiveModule->ExportAsModule 2527f0b11de2SDouglas Gregor << Tok.getString(); 2528f0b11de2SDouglas Gregor } 2529f0b11de2SDouglas Gregor } 2530f0b11de2SDouglas Gregor 2531adcd0268SBenjamin Kramer ActiveModule->ExportAsModule = std::string(Tok.getString()); 2532a3b5f71eSBruno Cardoso Lopes Map.addLinkAsDependency(ActiveModule); 2533a3b5f71eSBruno Cardoso Lopes 2534f0b11de2SDouglas Gregor consumeToken(); 2535f0b11de2SDouglas Gregor } 2536f0b11de2SDouglas Gregor 25379fc8faf9SAdrian Prantl /// Parse a module use declaration. 2538ba7f2f71SDaniel Jasper /// 25398f4d3ff1SRichard Smith /// use-declaration: 25408f4d3ff1SRichard Smith /// 'use' wildcard-module-id 2541ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() { 2542ba7f2f71SDaniel Jasper assert(Tok.is(MMToken::UseKeyword)); 25438f4d3ff1SRichard Smith auto KWLoc = consumeToken(); 2544ba7f2f71SDaniel Jasper // Parse the module-id. 2545ba7f2f71SDaniel Jasper ModuleId ParsedModuleId; 25463cd34c76SDaniel Jasper parseModuleId(ParsedModuleId); 2547ba7f2f71SDaniel Jasper 25488f4d3ff1SRichard Smith if (ActiveModule->Parent) 25498f4d3ff1SRichard Smith Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule); 25508f4d3ff1SRichard Smith else 2551ba7f2f71SDaniel Jasper ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId); 2552ba7f2f71SDaniel Jasper } 2553ba7f2f71SDaniel Jasper 25549fc8faf9SAdrian Prantl /// Parse a link declaration. 25556ddfca91SDouglas Gregor /// 25566ddfca91SDouglas Gregor /// module-declaration: 25576ddfca91SDouglas Gregor /// 'link' 'framework'[opt] string-literal 25586ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() { 25596ddfca91SDouglas Gregor assert(Tok.is(MMToken::LinkKeyword)); 25606ddfca91SDouglas Gregor SourceLocation LinkLoc = consumeToken(); 25616ddfca91SDouglas Gregor 25626ddfca91SDouglas Gregor // Parse the optional 'framework' keyword. 25636ddfca91SDouglas Gregor bool IsFramework = false; 25646ddfca91SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 25656ddfca91SDouglas Gregor consumeToken(); 25666ddfca91SDouglas Gregor IsFramework = true; 25676ddfca91SDouglas Gregor } 25686ddfca91SDouglas Gregor 25696ddfca91SDouglas Gregor // Parse the library name 25706ddfca91SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 25716ddfca91SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name) 25726ddfca91SDouglas Gregor << IsFramework << SourceRange(LinkLoc); 25736ddfca91SDouglas Gregor HadError = true; 25746ddfca91SDouglas Gregor return; 25756ddfca91SDouglas Gregor } 25766ddfca91SDouglas Gregor 2577adcd0268SBenjamin Kramer std::string LibraryName = std::string(Tok.getString()); 25786ddfca91SDouglas Gregor consumeToken(); 25796ddfca91SDouglas Gregor ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName, 25806ddfca91SDouglas Gregor IsFramework)); 25816ddfca91SDouglas Gregor } 25826ddfca91SDouglas Gregor 25839fc8faf9SAdrian Prantl /// Parse a configuration macro declaration. 258435b13eceSDouglas Gregor /// 258535b13eceSDouglas Gregor /// module-declaration: 258635b13eceSDouglas Gregor /// 'config_macros' attributes[opt] config-macro-list? 258735b13eceSDouglas Gregor /// 258835b13eceSDouglas Gregor /// config-macro-list: 258935b13eceSDouglas Gregor /// identifier (',' identifier)? 259035b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() { 259135b13eceSDouglas Gregor assert(Tok.is(MMToken::ConfigMacros)); 259235b13eceSDouglas Gregor SourceLocation ConfigMacrosLoc = consumeToken(); 259335b13eceSDouglas Gregor 259435b13eceSDouglas Gregor // Only top-level modules can have configuration macros. 259535b13eceSDouglas Gregor if (ActiveModule->Parent) { 259635b13eceSDouglas Gregor Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule); 259735b13eceSDouglas Gregor } 259835b13eceSDouglas Gregor 259935b13eceSDouglas Gregor // Parse the optional attributes. 260035b13eceSDouglas Gregor Attributes Attrs; 26015d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 26025d29dee0SDavide Italiano return; 26035d29dee0SDavide Italiano 260435b13eceSDouglas Gregor if (Attrs.IsExhaustive && !ActiveModule->Parent) { 260535b13eceSDouglas Gregor ActiveModule->ConfigMacrosExhaustive = true; 260635b13eceSDouglas Gregor } 260735b13eceSDouglas Gregor 260835b13eceSDouglas Gregor // If we don't have an identifier, we're done. 2609306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 261035b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) 261135b13eceSDouglas Gregor return; 261235b13eceSDouglas Gregor 261335b13eceSDouglas Gregor // Consume the first identifier. 261435b13eceSDouglas Gregor if (!ActiveModule->Parent) { 261535b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 261635b13eceSDouglas Gregor } 261735b13eceSDouglas Gregor consumeToken(); 261835b13eceSDouglas Gregor 261935b13eceSDouglas Gregor do { 262035b13eceSDouglas Gregor // If there's a comma, consume it. 262135b13eceSDouglas Gregor if (!Tok.is(MMToken::Comma)) 262235b13eceSDouglas Gregor break; 262335b13eceSDouglas Gregor consumeToken(); 262435b13eceSDouglas Gregor 262535b13eceSDouglas Gregor // We expect to see a macro name here. 2626306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 262735b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 262835b13eceSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro); 262935b13eceSDouglas Gregor break; 263035b13eceSDouglas Gregor } 263135b13eceSDouglas Gregor 263235b13eceSDouglas Gregor // Consume the macro name. 263335b13eceSDouglas Gregor if (!ActiveModule->Parent) { 263435b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 263535b13eceSDouglas Gregor } 263635b13eceSDouglas Gregor consumeToken(); 263735b13eceSDouglas Gregor } while (true); 263835b13eceSDouglas Gregor } 263935b13eceSDouglas Gregor 26409fc8faf9SAdrian Prantl /// Format a module-id into a string. 2641fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) { 2642fb912657SDouglas Gregor std::string result; 2643fb912657SDouglas Gregor { 2644fb912657SDouglas Gregor llvm::raw_string_ostream OS(result); 2645fb912657SDouglas Gregor 2646fb912657SDouglas Gregor for (unsigned I = 0, N = Id.size(); I != N; ++I) { 2647fb912657SDouglas Gregor if (I) 2648fb912657SDouglas Gregor OS << "."; 2649fb912657SDouglas Gregor OS << Id[I].first; 2650fb912657SDouglas Gregor } 2651fb912657SDouglas Gregor } 2652fb912657SDouglas Gregor 2653fb912657SDouglas Gregor return result; 2654fb912657SDouglas Gregor } 2655fb912657SDouglas Gregor 26569fc8faf9SAdrian Prantl /// Parse a conflict declaration. 2657fb912657SDouglas Gregor /// 2658fb912657SDouglas Gregor /// module-declaration: 2659fb912657SDouglas Gregor /// 'conflict' module-id ',' string-literal 2660fb912657SDouglas Gregor void ModuleMapParser::parseConflict() { 2661fb912657SDouglas Gregor assert(Tok.is(MMToken::Conflict)); 2662fb912657SDouglas Gregor SourceLocation ConflictLoc = consumeToken(); 2663fb912657SDouglas Gregor Module::UnresolvedConflict Conflict; 2664fb912657SDouglas Gregor 2665fb912657SDouglas Gregor // Parse the module-id. 2666fb912657SDouglas Gregor if (parseModuleId(Conflict.Id)) 2667fb912657SDouglas Gregor return; 2668fb912657SDouglas Gregor 2669fb912657SDouglas Gregor // Parse the ','. 2670fb912657SDouglas Gregor if (!Tok.is(MMToken::Comma)) { 2671fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma) 2672fb912657SDouglas Gregor << SourceRange(ConflictLoc); 2673fb912657SDouglas Gregor return; 2674fb912657SDouglas Gregor } 2675fb912657SDouglas Gregor consumeToken(); 2676fb912657SDouglas Gregor 2677fb912657SDouglas Gregor // Parse the message. 2678fb912657SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2679fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message) 2680fb912657SDouglas Gregor << formatModuleId(Conflict.Id); 2681fb912657SDouglas Gregor return; 2682fb912657SDouglas Gregor } 2683fb912657SDouglas Gregor Conflict.Message = Tok.getString().str(); 2684fb912657SDouglas Gregor consumeToken(); 2685fb912657SDouglas Gregor 2686fb912657SDouglas Gregor // Add this unresolved conflict. 2687fb912657SDouglas Gregor ActiveModule->UnresolvedConflicts.push_back(Conflict); 2688fb912657SDouglas Gregor } 2689fb912657SDouglas Gregor 26909fc8faf9SAdrian Prantl /// Parse an inferred module declaration (wildcard modules). 26919194a91dSDouglas Gregor /// 26929194a91dSDouglas Gregor /// module-declaration: 26939194a91dSDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt] 26949194a91dSDouglas Gregor /// { inferred-module-member* } 26959194a91dSDouglas Gregor /// 26969194a91dSDouglas Gregor /// inferred-module-member: 26979194a91dSDouglas Gregor /// 'export' '*' 26989194a91dSDouglas Gregor /// 'exclude' identifier 26999194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { 270073441091SDouglas Gregor assert(Tok.is(MMToken::Star)); 270173441091SDouglas Gregor SourceLocation StarLoc = consumeToken(); 270273441091SDouglas Gregor bool Failed = false; 270373441091SDouglas Gregor 270473441091SDouglas Gregor // Inferred modules must be submodules. 27059194a91dSDouglas Gregor if (!ActiveModule && !Framework) { 270673441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule); 270773441091SDouglas Gregor Failed = true; 270873441091SDouglas Gregor } 270973441091SDouglas Gregor 27109194a91dSDouglas Gregor if (ActiveModule) { 2711524e33e1SDouglas Gregor // Inferred modules must have umbrella directories. 27124898cde4SBen Langmuir if (!Failed && ActiveModule->IsAvailable && 27134898cde4SBen Langmuir !ActiveModule->getUmbrellaDir()) { 271473441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); 271573441091SDouglas Gregor Failed = true; 271673441091SDouglas Gregor } 271773441091SDouglas Gregor 271873441091SDouglas Gregor // Check for redefinition of an inferred module. 2719dd005f69SDouglas Gregor if (!Failed && ActiveModule->InferSubmodules) { 272073441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_redef); 2721dd005f69SDouglas Gregor if (ActiveModule->InferredSubmoduleLoc.isValid()) 2722dd005f69SDouglas Gregor Diags.Report(ActiveModule->InferredSubmoduleLoc, 272373441091SDouglas Gregor diag::note_mmap_prev_definition); 272473441091SDouglas Gregor Failed = true; 272573441091SDouglas Gregor } 272673441091SDouglas Gregor 27279194a91dSDouglas Gregor // Check for the 'framework' keyword, which is not permitted here. 27289194a91dSDouglas Gregor if (Framework) { 27299194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule); 27309194a91dSDouglas Gregor Framework = false; 27319194a91dSDouglas Gregor } 27329194a91dSDouglas Gregor } else if (Explicit) { 27339194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework); 27349194a91dSDouglas Gregor Explicit = false; 27359194a91dSDouglas Gregor } 27369194a91dSDouglas Gregor 273773441091SDouglas Gregor // If there were any problems with this inferred submodule, skip its body. 273873441091SDouglas Gregor if (Failed) { 273973441091SDouglas Gregor if (Tok.is(MMToken::LBrace)) { 274073441091SDouglas Gregor consumeToken(); 274173441091SDouglas Gregor skipUntil(MMToken::RBrace); 274273441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 274373441091SDouglas Gregor consumeToken(); 274473441091SDouglas Gregor } 274573441091SDouglas Gregor HadError = true; 274673441091SDouglas Gregor return; 274773441091SDouglas Gregor } 274873441091SDouglas Gregor 27499194a91dSDouglas Gregor // Parse optional attributes. 27504442605fSBill Wendling Attributes Attrs; 27515d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 27525d29dee0SDavide Italiano return; 27539194a91dSDouglas Gregor 27549194a91dSDouglas Gregor if (ActiveModule) { 275573441091SDouglas Gregor // Note that we have an inferred submodule. 2756dd005f69SDouglas Gregor ActiveModule->InferSubmodules = true; 2757dd005f69SDouglas Gregor ActiveModule->InferredSubmoduleLoc = StarLoc; 2758dd005f69SDouglas Gregor ActiveModule->InferExplicitSubmodules = Explicit; 27599194a91dSDouglas Gregor } else { 27609194a91dSDouglas Gregor // We'll be inferring framework modules for this directory. 27619194a91dSDouglas Gregor Map.InferredDirectories[Directory].InferModules = true; 2762c1d88ea5SBen Langmuir Map.InferredDirectories[Directory].Attrs = Attrs; 2763beee15e7SBen Langmuir Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile; 2764131daca0SRichard Smith // FIXME: Handle the 'framework' keyword. 27659194a91dSDouglas Gregor } 276673441091SDouglas Gregor 276773441091SDouglas Gregor // Parse the opening brace. 276873441091SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 276973441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard); 277073441091SDouglas Gregor HadError = true; 277173441091SDouglas Gregor return; 277273441091SDouglas Gregor } 277373441091SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 277473441091SDouglas Gregor 277573441091SDouglas Gregor // Parse the body of the inferred submodule. 277673441091SDouglas Gregor bool Done = false; 277773441091SDouglas Gregor do { 277873441091SDouglas Gregor switch (Tok.Kind) { 277973441091SDouglas Gregor case MMToken::EndOfFile: 278073441091SDouglas Gregor case MMToken::RBrace: 278173441091SDouglas Gregor Done = true; 278273441091SDouglas Gregor break; 278373441091SDouglas Gregor 2784afd1b1c9SEugene Zelenko case MMToken::ExcludeKeyword: 27859194a91dSDouglas Gregor if (ActiveModule) { 27869194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2787d2d442caSCraig Topper << (ActiveModule != nullptr); 27889194a91dSDouglas Gregor consumeToken(); 27899194a91dSDouglas Gregor break; 27909194a91dSDouglas Gregor } 27919194a91dSDouglas Gregor 27929194a91dSDouglas Gregor consumeToken(); 2793306d8920SRichard Smith // FIXME: Support string-literal module names here. 27949194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 27959194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name); 27969194a91dSDouglas Gregor break; 27979194a91dSDouglas Gregor } 27989194a91dSDouglas Gregor 2799adcd0268SBenjamin Kramer Map.InferredDirectories[Directory].ExcludedModules.push_back( 2800adcd0268SBenjamin Kramer std::string(Tok.getString())); 28019194a91dSDouglas Gregor consumeToken(); 28029194a91dSDouglas Gregor break; 28039194a91dSDouglas Gregor 28049194a91dSDouglas Gregor case MMToken::ExportKeyword: 28059194a91dSDouglas Gregor if (!ActiveModule) { 28069194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2807d2d442caSCraig Topper << (ActiveModule != nullptr); 28089194a91dSDouglas Gregor consumeToken(); 28099194a91dSDouglas Gregor break; 28109194a91dSDouglas Gregor } 28119194a91dSDouglas Gregor 281273441091SDouglas Gregor consumeToken(); 281373441091SDouglas Gregor if (Tok.is(MMToken::Star)) 2814dd005f69SDouglas Gregor ActiveModule->InferExportWildcard = true; 281573441091SDouglas Gregor else 281673441091SDouglas Gregor Diags.Report(Tok.getLocation(), 281773441091SDouglas Gregor diag::err_mmap_expected_export_wildcard); 281873441091SDouglas Gregor consumeToken(); 281973441091SDouglas Gregor break; 282073441091SDouglas Gregor 282173441091SDouglas Gregor case MMToken::ExplicitKeyword: 282273441091SDouglas Gregor case MMToken::ModuleKeyword: 282373441091SDouglas Gregor case MMToken::HeaderKeyword: 2824b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 282573441091SDouglas Gregor case MMToken::UmbrellaKeyword: 282673441091SDouglas Gregor default: 28279194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2828d2d442caSCraig Topper << (ActiveModule != nullptr); 282973441091SDouglas Gregor consumeToken(); 283073441091SDouglas Gregor break; 283173441091SDouglas Gregor } 283273441091SDouglas Gregor } while (!Done); 283373441091SDouglas Gregor 283473441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 283573441091SDouglas Gregor consumeToken(); 283673441091SDouglas Gregor else { 283773441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 283873441091SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 283973441091SDouglas Gregor HadError = true; 284073441091SDouglas Gregor } 284173441091SDouglas Gregor } 284273441091SDouglas Gregor 28439fc8faf9SAdrian Prantl /// Parse optional attributes. 28449194a91dSDouglas Gregor /// 28459194a91dSDouglas Gregor /// attributes: 28469194a91dSDouglas Gregor /// attribute attributes 28479194a91dSDouglas Gregor /// attribute 28489194a91dSDouglas Gregor /// 28499194a91dSDouglas Gregor /// attribute: 28509194a91dSDouglas Gregor /// [ identifier ] 28519194a91dSDouglas Gregor /// 28529194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes. 28539194a91dSDouglas Gregor /// 28549194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise. 28554442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { 28569194a91dSDouglas Gregor bool HadError = false; 28579194a91dSDouglas Gregor 28589194a91dSDouglas Gregor while (Tok.is(MMToken::LSquare)) { 28599194a91dSDouglas Gregor // Consume the '['. 28609194a91dSDouglas Gregor SourceLocation LSquareLoc = consumeToken(); 28619194a91dSDouglas Gregor 28629194a91dSDouglas Gregor // Check whether we have an attribute name here. 28639194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 28649194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute); 28659194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 28669194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 28679194a91dSDouglas Gregor consumeToken(); 28689194a91dSDouglas Gregor HadError = true; 28699194a91dSDouglas Gregor } 28709194a91dSDouglas Gregor 28719194a91dSDouglas Gregor // Decode the attribute name. 28729194a91dSDouglas Gregor AttributeKind Attribute 28739194a91dSDouglas Gregor = llvm::StringSwitch<AttributeKind>(Tok.getString()) 287435b13eceSDouglas Gregor .Case("exhaustive", AT_exhaustive) 287577944868SRichard Smith .Case("extern_c", AT_extern_c) 2876ed84df00SBruno Cardoso Lopes .Case("no_undeclared_includes", AT_no_undeclared_includes) 28779194a91dSDouglas Gregor .Case("system", AT_system) 28789194a91dSDouglas Gregor .Default(AT_unknown); 28799194a91dSDouglas Gregor switch (Attribute) { 28809194a91dSDouglas Gregor case AT_unknown: 28819194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute) 28829194a91dSDouglas Gregor << Tok.getString(); 28839194a91dSDouglas Gregor break; 28849194a91dSDouglas Gregor 28859194a91dSDouglas Gregor case AT_system: 28869194a91dSDouglas Gregor Attrs.IsSystem = true; 28879194a91dSDouglas Gregor break; 288835b13eceSDouglas Gregor 288977944868SRichard Smith case AT_extern_c: 289077944868SRichard Smith Attrs.IsExternC = true; 289177944868SRichard Smith break; 289277944868SRichard Smith 289335b13eceSDouglas Gregor case AT_exhaustive: 289435b13eceSDouglas Gregor Attrs.IsExhaustive = true; 289535b13eceSDouglas Gregor break; 2896ed84df00SBruno Cardoso Lopes 2897ed84df00SBruno Cardoso Lopes case AT_no_undeclared_includes: 2898ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes = true; 2899ed84df00SBruno Cardoso Lopes break; 29009194a91dSDouglas Gregor } 29019194a91dSDouglas Gregor consumeToken(); 29029194a91dSDouglas Gregor 29039194a91dSDouglas Gregor // Consume the ']'. 29049194a91dSDouglas Gregor if (!Tok.is(MMToken::RSquare)) { 29059194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare); 29069194a91dSDouglas Gregor Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match); 29079194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 29089194a91dSDouglas Gregor HadError = true; 29099194a91dSDouglas Gregor } 29109194a91dSDouglas Gregor 29119194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 29129194a91dSDouglas Gregor consumeToken(); 29139194a91dSDouglas Gregor } 29149194a91dSDouglas Gregor 29159194a91dSDouglas Gregor return HadError; 29169194a91dSDouglas Gregor } 29179194a91dSDouglas Gregor 29189fc8faf9SAdrian Prantl /// Parse a module map file. 2919718292f2SDouglas Gregor /// 2920718292f2SDouglas Gregor /// module-map-file: 2921718292f2SDouglas Gregor /// module-declaration* 2922718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 2923718292f2SDouglas Gregor do { 2924718292f2SDouglas Gregor switch (Tok.Kind) { 2925718292f2SDouglas Gregor case MMToken::EndOfFile: 2926718292f2SDouglas Gregor return HadError; 2927718292f2SDouglas Gregor 2928e7ab3669SDouglas Gregor case MMToken::ExplicitKeyword: 292997292843SDaniel Jasper case MMToken::ExternKeyword: 2930718292f2SDouglas Gregor case MMToken::ModuleKeyword: 2931755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 2932718292f2SDouglas Gregor parseModuleDecl(); 2933718292f2SDouglas Gregor break; 2934718292f2SDouglas Gregor 29351fb5c3a6SDouglas Gregor case MMToken::Comma: 293635b13eceSDouglas Gregor case MMToken::ConfigMacros: 2937fb912657SDouglas Gregor case MMToken::Conflict: 2938a3feee2aSRichard Smith case MMToken::Exclaim: 293959527666SDouglas Gregor case MMToken::ExcludeKeyword: 29402b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 2941f0b11de2SDouglas Gregor case MMToken::ExportAsKeyword: 2942718292f2SDouglas Gregor case MMToken::HeaderKeyword: 2943718292f2SDouglas Gregor case MMToken::Identifier: 2944718292f2SDouglas Gregor case MMToken::LBrace: 29456ddfca91SDouglas Gregor case MMToken::LinkKeyword: 2946a686e1b0SDouglas Gregor case MMToken::LSquare: 29472b82c2a5SDouglas Gregor case MMToken::Period: 2948b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 2949718292f2SDouglas Gregor case MMToken::RBrace: 2950a686e1b0SDouglas Gregor case MMToken::RSquare: 29511fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 29522b82c2a5SDouglas Gregor case MMToken::Star: 2953718292f2SDouglas Gregor case MMToken::StringLiteral: 2954040e1266SRichard Smith case MMToken::IntegerLiteral: 2955b8afebe2SRichard Smith case MMToken::TextualKeyword: 2956718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 2957ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 2958718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 2959718292f2SDouglas Gregor HadError = true; 2960718292f2SDouglas Gregor consumeToken(); 2961718292f2SDouglas Gregor break; 2962718292f2SDouglas Gregor } 2963718292f2SDouglas Gregor } while (true); 2964718292f2SDouglas Gregor } 2965718292f2SDouglas Gregor 29669acb99e3SRichard Smith bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem, 2967c192d194SBruno Cardoso Lopes const DirectoryEntry *Dir, FileID ID, 29688128f332SRichard Smith unsigned *Offset, 2969ae6df27eSRichard Smith SourceLocation ExternModuleLoc) { 29708128f332SRichard Smith assert(Target && "Missing target information"); 29714ddf2221SDouglas Gregor llvm::DenseMap<const FileEntry *, bool>::iterator Known 29724ddf2221SDouglas Gregor = ParsedModuleMap.find(File); 29734ddf2221SDouglas Gregor if (Known != ParsedModuleMap.end()) 29744ddf2221SDouglas Gregor return Known->second; 29754ddf2221SDouglas Gregor 29768128f332SRichard Smith // If the module map file wasn't already entered, do so now. 29778128f332SRichard Smith if (ID.isInvalid()) { 2978f3f84616SRichard Smith auto FileCharacter = 2979f3f84616SRichard Smith IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap; 29808128f332SRichard Smith ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter); 29818128f332SRichard Smith } 29828128f332SRichard Smith 29838128f332SRichard Smith assert(Target && "Missing target information"); 29841f76c4e8SManuel Klimek const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID); 2985718292f2SDouglas Gregor if (!Buffer) 29864ddf2221SDouglas Gregor return ParsedModuleMap[File] = true; 29878128f332SRichard Smith assert((!Offset || *Offset <= Buffer->getBufferSize()) && 29888128f332SRichard Smith "invalid buffer offset"); 2989718292f2SDouglas Gregor 2990718292f2SDouglas Gregor // Parse this module map file. 29918128f332SRichard Smith Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts, 29928128f332SRichard Smith Buffer->getBufferStart(), 29938128f332SRichard Smith Buffer->getBufferStart() + (Offset ? *Offset : 0), 29948128f332SRichard Smith Buffer->getBufferEnd()); 29952a6edb30SRichard Smith SourceLocation Start = L.getSourceLocation(); 2996beee15e7SBen Langmuir ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir, 2997c192d194SBruno Cardoso Lopes IsSystem); 2998718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 29994ddf2221SDouglas Gregor ParsedModuleMap[File] = Result; 30002a6edb30SRichard Smith 30018128f332SRichard Smith if (Offset) { 30028128f332SRichard Smith auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation()); 30038128f332SRichard Smith assert(Loc.first == ID && "stopped in a different file?"); 30048128f332SRichard Smith *Offset = Loc.second; 30058128f332SRichard Smith } 30068128f332SRichard Smith 30072a6edb30SRichard Smith // Notify callbacks that we parsed it. 30082a6edb30SRichard Smith for (const auto &Cb : Callbacks) 30092a6edb30SRichard Smith Cb->moduleMapFileRead(Start, *File, IsSystem); 30108587dfd9SBruno Cardoso Lopes 3011718292f2SDouglas Gregor return Result; 3012718292f2SDouglas Gregor } 3013