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 * { 182040e1266SRichard Smith auto *File = SourceMgr.getFileManager().getFile(Filename); 183040e1266SRichard Smith if (!File || 184040e1266SRichard Smith (Header.Size && File->getSize() != *Header.Size) || 185040e1266SRichard Smith (Header.ModTime && File->getModificationTime() != *Header.ModTime)) 186040e1266SRichard Smith return nullptr; 187040e1266SRichard Smith 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 2329f6020bcSBruno Cardoso Lopes if (M && !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 { 265040e1266SRichard Smith Module::Header H = {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); 303040e1266SRichard Smith auto *File = SourceMgr.getFileManager().getFile(Path); 304040e1266SRichard Smith if (!File) 305040e1266SRichard Smith return false; 306040e1266SRichard Smith 307040e1266SRichard Smith auto Role = headerKindToRole(Header.Kind); 308040e1266SRichard Smith Module::Header H = {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. 4334469138eSBen Langmuir Dir = SourceMgr.getFileManager().getDirectory(DirName); 4344469138eSBen Langmuir } while (Dir); 435afd1b1c9SEugene Zelenko return {}; 4364469138eSBen Langmuir } 4374469138eSBen Langmuir 43892669ee4SDaniel Jasper static bool violatesPrivateInclude(Module *RequestingModule, 43992669ee4SDaniel Jasper const FileEntry *IncFileEnt, 4404eb8393cSRichard Smith ModuleMap::KnownHeader Header) { 44192669ee4SDaniel Jasper #ifndef NDEBUG 4424eb8393cSRichard Smith if (Header.getRole() & ModuleMap::PrivateHeader) { 44392669ee4SDaniel Jasper // Check for consistency between the module header role 44492669ee4SDaniel Jasper // as obtained from the lookup and as obtained from the module. 44592669ee4SDaniel Jasper // This check is not cheap, so enable it only for debugging. 4462708e520SRichard Smith bool IsPrivate = false; 4472708e520SRichard Smith SmallVectorImpl<Module::Header> *HeaderList[] = { 4484eb8393cSRichard Smith &Header.getModule()->Headers[Module::HK_Private], 4494eb8393cSRichard Smith &Header.getModule()->Headers[Module::HK_PrivateTextual]}; 4502708e520SRichard Smith for (auto *Hs : HeaderList) 4512708e520SRichard Smith IsPrivate |= 4522708e520SRichard Smith std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) { 4533c1a41adSRichard Smith return H.Entry == IncFileEnt; 4542708e520SRichard Smith }) != Hs->end(); 4554eb8393cSRichard Smith assert(IsPrivate && "inconsistent headers and roles"); 45600bc95ecSRichard Smith } 45792669ee4SDaniel Jasper #endif 4584eb8393cSRichard Smith return !Header.isAccessibleFrom(RequestingModule); 45992669ee4SDaniel Jasper } 46092669ee4SDaniel Jasper 46171e1a64fSBen Langmuir static Module *getTopLevelOrNull(Module *M) { 46271e1a64fSBen Langmuir return M ? M->getTopLevelModule() : nullptr; 46371e1a64fSBen Langmuir } 46471e1a64fSBen Langmuir 46592669ee4SDaniel Jasper void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, 4668d4e90b3SRichard Smith bool RequestingModuleIsModuleInterface, 46792669ee4SDaniel Jasper SourceLocation FilenameLoc, 46892669ee4SDaniel Jasper StringRef Filename, 46992669ee4SDaniel Jasper const FileEntry *File) { 47092669ee4SDaniel Jasper // No errors for indirect modules. This may be a bit of a problem for modules 47192669ee4SDaniel Jasper // with no source files. 47271e1a64fSBen Langmuir if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule)) 47392669ee4SDaniel Jasper return; 47492669ee4SDaniel Jasper 475040e1266SRichard Smith if (RequestingModule) { 47692669ee4SDaniel Jasper resolveUses(RequestingModule, /*Complain=*/false); 477040e1266SRichard Smith resolveHeaderDirectives(RequestingModule); 478040e1266SRichard Smith } 47992669ee4SDaniel Jasper 48071e1a64fSBen Langmuir bool Excluded = false; 481d2d442caSCraig Topper Module *Private = nullptr; 482d2d442caSCraig Topper Module *NotUsed = nullptr; 48371e1a64fSBen Langmuir 48471e1a64fSBen Langmuir HeadersMap::iterator Known = findKnownHeader(File); 48571e1a64fSBen Langmuir if (Known != Headers.end()) { 48671e1a64fSBen Langmuir for (const KnownHeader &Header : Known->second) { 48792669ee4SDaniel Jasper // Remember private headers for later printing of a diagnostic. 4884eb8393cSRichard Smith if (violatesPrivateInclude(RequestingModule, File, Header)) { 48971e1a64fSBen Langmuir Private = Header.getModule(); 49092669ee4SDaniel Jasper continue; 49192669ee4SDaniel Jasper } 49292669ee4SDaniel Jasper 49392669ee4SDaniel Jasper // If uses need to be specified explicitly, we are only allowed to return 49492669ee4SDaniel Jasper // modules that are explicitly used by the requesting module. 49592669ee4SDaniel Jasper if (RequestingModule && LangOpts.ModulesDeclUse && 4968f4d3ff1SRichard Smith !RequestingModule->directlyUses(Header.getModule())) { 49771e1a64fSBen Langmuir NotUsed = Header.getModule(); 49892669ee4SDaniel Jasper continue; 49992669ee4SDaniel Jasper } 50092669ee4SDaniel Jasper 50192669ee4SDaniel Jasper // We have found a module that we can happily use. 50292669ee4SDaniel Jasper return; 50392669ee4SDaniel Jasper } 504feb54b6dSRichard Smith 505feb54b6dSRichard Smith Excluded = true; 50671e1a64fSBen Langmuir } 50792669ee4SDaniel Jasper 50892669ee4SDaniel Jasper // We have found a header, but it is private. 509d2d442caSCraig Topper if (Private) { 51011152dd5SRichard Smith Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module) 51192669ee4SDaniel Jasper << Filename; 51292669ee4SDaniel Jasper return; 51392669ee4SDaniel Jasper } 51492669ee4SDaniel Jasper 51592669ee4SDaniel Jasper // We have found a module, but we don't use it. 516d2d442caSCraig Topper if (NotUsed) { 51711152dd5SRichard Smith Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) 5184ea330c8SDaniel Jasper << RequestingModule->getTopLevelModule()->Name << Filename; 51992669ee4SDaniel Jasper return; 52092669ee4SDaniel Jasper } 52192669ee4SDaniel Jasper 52271e1a64fSBen Langmuir if (Excluded || isHeaderInUmbrellaDirs(File)) 52371e1a64fSBen Langmuir return; 52471e1a64fSBen Langmuir 52571e1a64fSBen Langmuir // At this point, only non-modular includes remain. 52671e1a64fSBen Langmuir 5275904c41eSBenjamin Kramer if (RequestingModule && LangOpts.ModulesStrictDeclUse) { 52811152dd5SRichard Smith Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) 5294ea330c8SDaniel Jasper << RequestingModule->getTopLevelModule()->Name << Filename; 530a67e4d32SManman Ren } else if (RequestingModule && RequestingModuleIsModuleInterface && 531a67e4d32SManman Ren LangOpts.isCompilingModule()) { 532a67e4d32SManman Ren // Do not diagnose when we are not compiling a module. 53371e1a64fSBen Langmuir diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ? 53471e1a64fSBen Langmuir diag::warn_non_modular_include_in_framework_module : 53571e1a64fSBen Langmuir diag::warn_non_modular_include_in_module; 53670a7738fSManman Ren Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName() 53770a7738fSManman Ren << File->getName(); 53871e1a64fSBen Langmuir } 53992669ee4SDaniel Jasper } 54092669ee4SDaniel Jasper 541ec87a50aSRichard Smith static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New, 542ec87a50aSRichard Smith const ModuleMap::KnownHeader &Old) { 5438b7c0398SSean Silva // Prefer available modules. 5448b7c0398SSean Silva if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable()) 5458b7c0398SSean Silva return true; 5468b7c0398SSean Silva 547ec87a50aSRichard Smith // Prefer a public header over a private header. 548ec87a50aSRichard Smith if ((New.getRole() & ModuleMap::PrivateHeader) != 549ec87a50aSRichard Smith (Old.getRole() & ModuleMap::PrivateHeader)) 550ec87a50aSRichard Smith return !(New.getRole() & ModuleMap::PrivateHeader); 551ec87a50aSRichard Smith 552ec87a50aSRichard Smith // Prefer a non-textual header over a textual header. 553ec87a50aSRichard Smith if ((New.getRole() & ModuleMap::TextualHeader) != 554ec87a50aSRichard Smith (Old.getRole() & ModuleMap::TextualHeader)) 555ec87a50aSRichard Smith return !(New.getRole() & ModuleMap::TextualHeader); 556ec87a50aSRichard Smith 557ec87a50aSRichard Smith // Don't have a reason to choose between these. Just keep the first one. 558ec87a50aSRichard Smith return false; 559ec87a50aSRichard Smith } 560ec87a50aSRichard Smith 561ed84df00SBruno Cardoso Lopes ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File, 562ed84df00SBruno Cardoso Lopes bool AllowTextual) { 563306d8920SRichard Smith auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader { 564ed84df00SBruno Cardoso Lopes if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader) 565afd1b1c9SEugene Zelenko return {}; 566306d8920SRichard Smith return R; 567306d8920SRichard Smith }; 568306d8920SRichard Smith 5694881e8b2SSean Silva HeadersMap::iterator Known = findKnownHeader(File); 5701fb5c3a6SDouglas Gregor if (Known != Headers.end()) { 571202210b3SRichard Smith ModuleMap::KnownHeader Result; 57297da9178SDaniel Jasper // Iterate over all modules that 'File' is part of to find the best fit. 5734881e8b2SSean Silva for (KnownHeader &H : Known->second) { 5747e82e019SRichard Smith // Prefer a header from the source module over all others. 5757e82e019SRichard Smith if (H.getModule()->getTopLevelModule() == SourceModule) 5762f633e7cSRichard Smith return MakeResult(H); 5774881e8b2SSean Silva if (!Result || isBetterKnownHeader(H, Result)) 5784881e8b2SSean Silva Result = H; 57997da9178SDaniel Jasper } 580306d8920SRichard Smith return MakeResult(Result); 5811fb5c3a6SDouglas Gregor } 582ab0c8a84SDouglas Gregor 583386bb073SRichard Smith return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File)); 584386bb073SRichard Smith } 585386bb073SRichard Smith 586386bb073SRichard Smith ModuleMap::KnownHeader 587386bb073SRichard Smith ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) { 588386bb073SRichard Smith assert(!Headers.count(File) && "already have a module for this header"); 589386bb073SRichard Smith 590f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs; 5914469138eSBen Langmuir KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs); 5924469138eSBen Langmuir if (H) { 5934469138eSBen Langmuir Module *Result = H.getModule(); 594930a85ccSDouglas Gregor 595930a85ccSDouglas Gregor // Search up the module stack until we find a module with an umbrella 59673141fa9SDouglas Gregor // directory. 597930a85ccSDouglas Gregor Module *UmbrellaModule = Result; 59873141fa9SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 599930a85ccSDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 600930a85ccSDouglas Gregor 601930a85ccSDouglas Gregor if (UmbrellaModule->InferSubmodules) { 6029d6448b1SBen Langmuir const FileEntry *UmbrellaModuleMap = 6039d6448b1SBen Langmuir getModuleMapFileForUniquing(UmbrellaModule); 6049d6448b1SBen Langmuir 605a89c5ac4SDouglas Gregor // Infer submodules for each of the directories we found between 606a89c5ac4SDouglas Gregor // the directory of the umbrella header and the directory where 607a89c5ac4SDouglas Gregor // the actual header is located. 6089458f82dSDouglas Gregor bool Explicit = UmbrellaModule->InferExplicitSubmodules; 6099458f82dSDouglas Gregor 6107033127bSDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 611a89c5ac4SDouglas Gregor // Find or create the module that corresponds to this directory name. 612056396aeSDouglas Gregor SmallString<32> NameBuf; 613056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 6144469138eSBen Langmuir llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf); 6159d6448b1SBen Langmuir Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 6169d6448b1SBen Langmuir Explicit).first; 6179d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = UmbrellaModuleMap; 618ffbafa2aSBen Langmuir Result->IsInferred = true; 619a89c5ac4SDouglas Gregor 620a89c5ac4SDouglas Gregor // Associate the module and the directory. 621a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I-1]] = Result; 622a89c5ac4SDouglas Gregor 623a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 624a89c5ac4SDouglas Gregor // wildcard to the set of exports. 625930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 626d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 627a89c5ac4SDouglas Gregor } 628a89c5ac4SDouglas Gregor 629a89c5ac4SDouglas Gregor // Infer a submodule with the same name as this header file. 630056396aeSDouglas Gregor SmallString<32> NameBuf; 631056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 632056396aeSDouglas Gregor llvm::sys::path::stem(File->getName()), NameBuf); 6339d6448b1SBen Langmuir Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 6349d6448b1SBen Langmuir Explicit).first; 6359d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = UmbrellaModuleMap; 636ffbafa2aSBen Langmuir Result->IsInferred = true; 6373c5305c1SArgyrios Kyrtzidis Result->addTopHeader(File); 638a89c5ac4SDouglas Gregor 639a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 640a89c5ac4SDouglas Gregor // wildcard to the set of exports. 641930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 642d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 643a89c5ac4SDouglas Gregor } else { 644a89c5ac4SDouglas Gregor // Record each of the directories we stepped through as being part of 645a89c5ac4SDouglas Gregor // the module we found, since the umbrella header covers them all. 646a89c5ac4SDouglas Gregor for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I) 647a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I]] = Result; 648a89c5ac4SDouglas Gregor } 649a89c5ac4SDouglas Gregor 650386bb073SRichard Smith KnownHeader Header(Result, NormalHeader); 651386bb073SRichard Smith Headers[File].push_back(Header); 652386bb073SRichard Smith return Header; 653a89c5ac4SDouglas Gregor } 654a89c5ac4SDouglas Gregor 655afd1b1c9SEugene Zelenko return {}; 656ab0c8a84SDouglas Gregor } 657ab0c8a84SDouglas Gregor 658386bb073SRichard Smith ArrayRef<ModuleMap::KnownHeader> 659386bb073SRichard Smith ModuleMap::findAllModulesForHeader(const FileEntry *File) const { 660040e1266SRichard Smith resolveHeaderDirectives(File); 661386bb073SRichard Smith auto It = Headers.find(File); 662386bb073SRichard Smith if (It == Headers.end()) 663386bb073SRichard Smith return None; 664386bb073SRichard Smith return It->second; 665386bb073SRichard Smith } 666386bb073SRichard Smith 667e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const { 668d2d442caSCraig Topper return isHeaderUnavailableInModule(Header, nullptr); 66950996ce1SRichard Smith } 67050996ce1SRichard Smith 67162bcd925SDmitri Gribenko bool 67262bcd925SDmitri Gribenko ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, 67362bcd925SDmitri Gribenko const Module *RequestingModule) const { 674040e1266SRichard Smith resolveHeaderDirectives(Header); 675e4412640SArgyrios Kyrtzidis HeadersMap::const_iterator Known = Headers.find(Header); 67697da9178SDaniel Jasper if (Known != Headers.end()) { 67797da9178SDaniel Jasper for (SmallVectorImpl<KnownHeader>::const_iterator 67897da9178SDaniel Jasper I = Known->second.begin(), 67997da9178SDaniel Jasper E = Known->second.end(); 68097da9178SDaniel Jasper I != E; ++I) { 681052d95a6SBruno Cardoso Lopes 682052d95a6SBruno Cardoso Lopes if (I->isAvailable() && 683052d95a6SBruno Cardoso Lopes (!RequestingModule || 684052d95a6SBruno Cardoso Lopes I->getModule()->isSubModuleOf(RequestingModule))) { 685052d95a6SBruno Cardoso Lopes // When no requesting module is available, the caller is looking if a 686052d95a6SBruno Cardoso Lopes // header is part a module by only looking into the module map. This is 687052d95a6SBruno Cardoso Lopes // done by warn_uncovered_module_header checks; don't consider textual 688052d95a6SBruno Cardoso Lopes // headers part of it in this mode, otherwise we get misleading warnings 689052d95a6SBruno Cardoso Lopes // that a umbrella header is not including a textual header. 690052d95a6SBruno Cardoso Lopes if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader) 691052d95a6SBruno Cardoso Lopes continue; 69297da9178SDaniel Jasper return false; 69397da9178SDaniel Jasper } 694052d95a6SBruno Cardoso Lopes } 69597da9178SDaniel Jasper return true; 69697da9178SDaniel Jasper } 6971fb5c3a6SDouglas Gregor 6981fb5c3a6SDouglas Gregor const DirectoryEntry *Dir = Header->getDir(); 699f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs; 7001fb5c3a6SDouglas Gregor StringRef DirName = Dir->getName(); 7011fb5c3a6SDouglas Gregor 70250996ce1SRichard Smith auto IsUnavailable = [&](const Module *M) { 70350996ce1SRichard Smith return !M->isAvailable() && (!RequestingModule || 70450996ce1SRichard Smith M->isSubModuleOf(RequestingModule)); 70550996ce1SRichard Smith }; 70650996ce1SRichard Smith 7071fb5c3a6SDouglas Gregor // Keep walking up the directory hierarchy, looking for a directory with 7081fb5c3a6SDouglas Gregor // an umbrella header. 7091fb5c3a6SDouglas Gregor do { 710e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir 7111fb5c3a6SDouglas Gregor = UmbrellaDirs.find(Dir); 7121fb5c3a6SDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 7131fb5c3a6SDouglas Gregor Module *Found = KnownDir->second; 71450996ce1SRichard Smith if (IsUnavailable(Found)) 7151fb5c3a6SDouglas Gregor return true; 7161fb5c3a6SDouglas Gregor 7171fb5c3a6SDouglas Gregor // Search up the module stack until we find a module with an umbrella 7181fb5c3a6SDouglas Gregor // directory. 7191fb5c3a6SDouglas Gregor Module *UmbrellaModule = Found; 7201fb5c3a6SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 7211fb5c3a6SDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 7221fb5c3a6SDouglas Gregor 7231fb5c3a6SDouglas Gregor if (UmbrellaModule->InferSubmodules) { 7241fb5c3a6SDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 7251fb5c3a6SDouglas Gregor // Find or create the module that corresponds to this directory name. 726056396aeSDouglas Gregor SmallString<32> NameBuf; 727056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 728056396aeSDouglas Gregor llvm::sys::path::stem(SkippedDirs[I-1]->getName()), 729056396aeSDouglas Gregor NameBuf); 7301fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 7311fb5c3a6SDouglas Gregor if (!Found) 7321fb5c3a6SDouglas Gregor return false; 73350996ce1SRichard Smith if (IsUnavailable(Found)) 7341fb5c3a6SDouglas Gregor return true; 7351fb5c3a6SDouglas Gregor } 7361fb5c3a6SDouglas Gregor 7371fb5c3a6SDouglas Gregor // Infer a submodule with the same name as this header file. 738056396aeSDouglas Gregor SmallString<32> NameBuf; 739056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 740056396aeSDouglas Gregor llvm::sys::path::stem(Header->getName()), 741056396aeSDouglas Gregor NameBuf); 7421fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 7431fb5c3a6SDouglas Gregor if (!Found) 7441fb5c3a6SDouglas Gregor return false; 7451fb5c3a6SDouglas Gregor } 7461fb5c3a6SDouglas Gregor 74750996ce1SRichard Smith return IsUnavailable(Found); 7481fb5c3a6SDouglas Gregor } 7491fb5c3a6SDouglas Gregor 7501fb5c3a6SDouglas Gregor SkippedDirs.push_back(Dir); 7511fb5c3a6SDouglas Gregor 7521fb5c3a6SDouglas Gregor // Retrieve our parent path. 7531fb5c3a6SDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 7541fb5c3a6SDouglas Gregor if (DirName.empty()) 7551fb5c3a6SDouglas Gregor break; 7561fb5c3a6SDouglas Gregor 7571fb5c3a6SDouglas Gregor // Resolve the parent path to a directory entry. 7581f76c4e8SManuel Klimek Dir = SourceMgr.getFileManager().getDirectory(DirName); 7591fb5c3a6SDouglas Gregor } while (Dir); 7601fb5c3a6SDouglas Gregor 7611fb5c3a6SDouglas Gregor return false; 7621fb5c3a6SDouglas Gregor } 7631fb5c3a6SDouglas Gregor 764e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const { 765e4412640SArgyrios Kyrtzidis llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name); 76688bdfb0eSDouglas Gregor if (Known != Modules.end()) 76788bdfb0eSDouglas Gregor return Known->getValue(); 76888bdfb0eSDouglas Gregor 769d2d442caSCraig Topper return nullptr; 77088bdfb0eSDouglas Gregor } 77188bdfb0eSDouglas Gregor 772e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name, 773e4412640SArgyrios Kyrtzidis Module *Context) const { 7742b82c2a5SDouglas Gregor for(; Context; Context = Context->Parent) { 7752b82c2a5SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Context)) 7762b82c2a5SDouglas Gregor return Sub; 7772b82c2a5SDouglas Gregor } 7782b82c2a5SDouglas Gregor 7792b82c2a5SDouglas Gregor return findModule(Name); 7802b82c2a5SDouglas Gregor } 7812b82c2a5SDouglas Gregor 782e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{ 7832b82c2a5SDouglas Gregor if (!Context) 7842b82c2a5SDouglas Gregor return findModule(Name); 7852b82c2a5SDouglas Gregor 786eb90e830SDouglas Gregor return Context->findSubmodule(Name); 7872b82c2a5SDouglas Gregor } 7882b82c2a5SDouglas Gregor 789c192d194SBruno Cardoso Lopes std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name, 790c192d194SBruno Cardoso Lopes Module *Parent, 791c192d194SBruno Cardoso Lopes bool IsFramework, 792c192d194SBruno Cardoso Lopes bool IsExplicit) { 79369021974SDouglas Gregor // Try to find an existing module with this name. 794eb90e830SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Parent)) 795eb90e830SDouglas Gregor return std::make_pair(Sub, false); 79669021974SDouglas Gregor 79769021974SDouglas Gregor // Create a new module with this name. 7989ffe5a35SDavid Blaikie Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, 7999ffe5a35SDavid Blaikie IsExplicit, NumCreatedModules++); 8006f722b4eSArgyrios Kyrtzidis if (!Parent) { 8017e82e019SRichard Smith if (LangOpts.CurrentModule == Name) 8027e82e019SRichard Smith SourceModule = Result; 80369021974SDouglas Gregor Modules[Name] = Result; 804c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID; 8056f722b4eSArgyrios Kyrtzidis } 80669021974SDouglas Gregor return std::make_pair(Result, true); 80769021974SDouglas Gregor } 80869021974SDouglas Gregor 809dd8b5337SRichard Smith Module *ModuleMap::createGlobalModuleForInterfaceUnit(SourceLocation Loc) { 810d6509cf2SRichard Smith PendingSubmodules.emplace_back( 811056bf77fSRichard Smith new Module("<global>", Loc, nullptr, /*IsFramework*/ false, 812056bf77fSRichard Smith /*IsExplicit*/ true, NumCreatedModules++)); 813d6509cf2SRichard Smith PendingSubmodules.back()->Kind = Module::GlobalModuleFragment; 814d6509cf2SRichard Smith return PendingSubmodules.back().get(); 815dd8b5337SRichard Smith } 816dd8b5337SRichard Smith 817bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc, 818dd8b5337SRichard Smith StringRef Name, 819dd8b5337SRichard Smith Module *GlobalModule) { 820bbcc9f04SRichard Smith assert(LangOpts.CurrentModule == Name && "module name mismatch"); 821bbcc9f04SRichard Smith assert(!Modules[Name] && "redefining existing module"); 822bbcc9f04SRichard Smith 823bbcc9f04SRichard Smith auto *Result = 824bbcc9f04SRichard Smith new Module(Name, Loc, nullptr, /*IsFramework*/ false, 825bbcc9f04SRichard Smith /*IsExplicit*/ false, NumCreatedModules++); 826145e15a3SRichard Smith Result->Kind = Module::ModuleInterfaceUnit; 827bbcc9f04SRichard Smith Modules[Name] = SourceModule = Result; 828bbcc9f04SRichard Smith 829dd8b5337SRichard Smith // Reparent the current global module fragment as a submodule of this module. 830d6509cf2SRichard Smith for (auto &Submodule : PendingSubmodules) { 831d6509cf2SRichard Smith Submodule->setParent(Result); 832d6509cf2SRichard Smith Submodule.release(); // now owned by parent 833d6509cf2SRichard Smith } 834d6509cf2SRichard Smith PendingSubmodules.clear(); 835dd8b5337SRichard Smith 836bbcc9f04SRichard Smith // Mark the main source file as being within the newly-created module so that 837bbcc9f04SRichard Smith // declarations and macros are properly visibility-restricted to it. 838bbcc9f04SRichard Smith auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()); 839bbcc9f04SRichard Smith assert(MainFile && "no input file for module interface"); 840bbcc9f04SRichard Smith Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader)); 841bbcc9f04SRichard Smith 842bbcc9f04SRichard Smith return Result; 843bbcc9f04SRichard Smith } 844bbcc9f04SRichard Smith 845d6509cf2SRichard Smith Module *ModuleMap::createHeaderModule(StringRef Name, 846d6509cf2SRichard Smith ArrayRef<Module::Header> Headers) { 847d6509cf2SRichard Smith assert(LangOpts.CurrentModule == Name && "module name mismatch"); 848d6509cf2SRichard Smith assert(!Modules[Name] && "redefining existing module"); 849d6509cf2SRichard Smith 850d6509cf2SRichard Smith auto *Result = 851d6509cf2SRichard Smith new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false, 852d6509cf2SRichard Smith /*IsExplicit*/ false, NumCreatedModules++); 853d6509cf2SRichard Smith Result->Kind = Module::ModuleInterfaceUnit; 854d6509cf2SRichard Smith Modules[Name] = SourceModule = Result; 855d6509cf2SRichard Smith 856d6509cf2SRichard Smith for (const Module::Header &H : Headers) { 857d6509cf2SRichard Smith auto *M = new Module(H.NameAsWritten, SourceLocation(), Result, 858d6509cf2SRichard Smith /*IsFramework*/ false, 859d6509cf2SRichard Smith /*IsExplicit*/ true, NumCreatedModules++); 860d6509cf2SRichard Smith // Header modules are implicitly 'export *'. 861d6509cf2SRichard Smith M->Exports.push_back(Module::ExportDecl(nullptr, true)); 862d6509cf2SRichard Smith addHeader(M, H, NormalHeader); 863d6509cf2SRichard Smith } 864d6509cf2SRichard Smith 865d6509cf2SRichard Smith return Result; 866d6509cf2SRichard Smith } 867d6509cf2SRichard Smith 8689fc8faf9SAdrian Prantl /// For a framework module, infer the framework against which we 86911dfe6feSDouglas Gregor /// should link. 87011dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir, 87111dfe6feSDouglas Gregor FileManager &FileMgr) { 87211dfe6feSDouglas Gregor assert(Mod->IsFramework && "Can only infer linking for framework modules"); 87311dfe6feSDouglas Gregor assert(!Mod->isSubFramework() && 87411dfe6feSDouglas Gregor "Can only infer linking for top-level frameworks"); 87511dfe6feSDouglas Gregor 87611dfe6feSDouglas Gregor SmallString<128> LibName; 87711dfe6feSDouglas Gregor LibName += FrameworkDir->getName(); 87811dfe6feSDouglas Gregor llvm::sys::path::append(LibName, Mod->Name); 8798aaae5a9SJuergen Ributzka 8808aaae5a9SJuergen Ributzka // The library name of a framework has more than one possible extension since 8818aaae5a9SJuergen Ributzka // the introduction of the text-based dynamic library format. We need to check 8828aaae5a9SJuergen Ributzka // for both before we give up. 8838013e81dSBenjamin Kramer for (const char *extension : {"", ".tbd"}) { 8848aaae5a9SJuergen Ributzka llvm::sys::path::replace_extension(LibName, extension); 88511dfe6feSDouglas Gregor if (FileMgr.getFile(LibName)) { 88611dfe6feSDouglas Gregor Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name, 88711dfe6feSDouglas Gregor /*IsFramework=*/true)); 8888aaae5a9SJuergen Ributzka return; 8898aaae5a9SJuergen Ributzka } 89011dfe6feSDouglas Gregor } 89111dfe6feSDouglas Gregor } 89211dfe6feSDouglas Gregor 893a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 894a525400dSBen Langmuir bool IsSystem, Module *Parent) { 895c1d88ea5SBen Langmuir Attributes Attrs; 896c1d88ea5SBen Langmuir Attrs.IsSystem = IsSystem; 897a525400dSBen Langmuir return inferFrameworkModule(FrameworkDir, Attrs, Parent); 898c1d88ea5SBen Langmuir } 899c1d88ea5SBen Langmuir 900a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 901c1d88ea5SBen Langmuir Attributes Attrs, Module *Parent) { 902a525400dSBen Langmuir // Note: as an egregious but useful hack we use the real path here, because 903a525400dSBen Langmuir // we might be looking at an embedded framework that symlinks out to a 904a525400dSBen Langmuir // top-level framework, and we need to infer as if we were naming the 905a525400dSBen Langmuir // top-level framework. 906a525400dSBen Langmuir StringRef FrameworkDirName = 907a525400dSBen Langmuir SourceMgr.getFileManager().getCanonicalName(FrameworkDir); 908a525400dSBen Langmuir 909a525400dSBen Langmuir // In case this is a case-insensitive filesystem, use the canonical 910a525400dSBen Langmuir // directory name as the ModuleName, since modules are case-sensitive. 911a525400dSBen Langmuir // FIXME: we should be able to give a fix-it hint for the correct spelling. 912a525400dSBen Langmuir SmallString<32> ModuleNameStorage; 913a525400dSBen Langmuir StringRef ModuleName = sanitizeFilenameAsIdentifier( 914a525400dSBen Langmuir llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage); 915c1d88ea5SBen Langmuir 91656c64013SDouglas Gregor // Check whether we've already found this module. 917e89dbc1dSDouglas Gregor if (Module *Mod = lookupModuleQualified(ModuleName, Parent)) 918e89dbc1dSDouglas Gregor return Mod; 919e89dbc1dSDouglas Gregor 9201f76c4e8SManuel Klimek FileManager &FileMgr = SourceMgr.getFileManager(); 92156c64013SDouglas Gregor 9229194a91dSDouglas Gregor // If the framework has a parent path from which we're allowed to infer 9239194a91dSDouglas Gregor // a framework module, do so. 924beee15e7SBen Langmuir const FileEntry *ModuleMapFile = nullptr; 9259194a91dSDouglas Gregor if (!Parent) { 9264ddf2221SDouglas Gregor // Determine whether we're allowed to infer a module map. 9279194a91dSDouglas Gregor bool canInfer = false; 9284ddf2221SDouglas Gregor if (llvm::sys::path::has_parent_path(FrameworkDirName)) { 9299194a91dSDouglas Gregor // Figure out the parent path. 9304ddf2221SDouglas Gregor StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName); 9319194a91dSDouglas Gregor if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) { 9329194a91dSDouglas Gregor // Check whether we have already looked into the parent directory 9339194a91dSDouglas Gregor // for a module map. 934e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator 9359194a91dSDouglas Gregor inferred = InferredDirectories.find(ParentDir); 9369194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) { 9379194a91dSDouglas Gregor // We haven't looked here before. Load a module map, if there is 9389194a91dSDouglas Gregor // one. 939984e1df7SBen Langmuir bool IsFrameworkDir = Parent.endswith(".framework"); 940984e1df7SBen Langmuir if (const FileEntry *ModMapFile = 941984e1df7SBen Langmuir HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) { 942c1d88ea5SBen Langmuir parseModuleMapFile(ModMapFile, Attrs.IsSystem, ParentDir); 9439194a91dSDouglas Gregor inferred = InferredDirectories.find(ParentDir); 9449194a91dSDouglas Gregor } 9459194a91dSDouglas Gregor 9469194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) 9479194a91dSDouglas Gregor inferred = InferredDirectories.insert( 9489194a91dSDouglas Gregor std::make_pair(ParentDir, InferredDirectory())).first; 9499194a91dSDouglas Gregor } 9509194a91dSDouglas Gregor 9519194a91dSDouglas Gregor if (inferred->second.InferModules) { 9529194a91dSDouglas Gregor // We're allowed to infer for this directory, but make sure it's okay 9539194a91dSDouglas Gregor // to infer this particular module. 9544ddf2221SDouglas Gregor StringRef Name = llvm::sys::path::stem(FrameworkDirName); 9559194a91dSDouglas Gregor canInfer = std::find(inferred->second.ExcludedModules.begin(), 9569194a91dSDouglas Gregor inferred->second.ExcludedModules.end(), 9579194a91dSDouglas Gregor Name) == inferred->second.ExcludedModules.end(); 9589194a91dSDouglas Gregor 959c1d88ea5SBen Langmuir Attrs.IsSystem |= inferred->second.Attrs.IsSystem; 960c1d88ea5SBen Langmuir Attrs.IsExternC |= inferred->second.Attrs.IsExternC; 961c1d88ea5SBen Langmuir Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive; 962ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes |= 963ed84df00SBruno Cardoso Lopes inferred->second.Attrs.NoUndeclaredIncludes; 964beee15e7SBen Langmuir ModuleMapFile = inferred->second.ModuleMapFile; 9659194a91dSDouglas Gregor } 9669194a91dSDouglas Gregor } 9679194a91dSDouglas Gregor } 9689194a91dSDouglas Gregor 9699194a91dSDouglas Gregor // If we're not allowed to infer a framework module, don't. 9709194a91dSDouglas Gregor if (!canInfer) 971d2d442caSCraig Topper return nullptr; 972beee15e7SBen Langmuir } else 9739d6448b1SBen Langmuir ModuleMapFile = getModuleMapFileForUniquing(Parent); 9749194a91dSDouglas Gregor 9759194a91dSDouglas Gregor 97656c64013SDouglas Gregor // Look for an umbrella header. 9772c1dd271SDylan Noblesmith SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 97817381a06SBenjamin Kramer llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h"); 979e89dbc1dSDouglas Gregor const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName); 98056c64013SDouglas Gregor 98156c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the 98256c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good 98356c64013SDouglas Gregor // idea. 98456c64013SDouglas Gregor if (!UmbrellaHeader) 985d2d442caSCraig Topper return nullptr; 98656c64013SDouglas Gregor 9879d6448b1SBen Langmuir Module *Result = new Module(ModuleName, SourceLocation(), Parent, 988a7e2cc68SRichard Smith /*IsFramework=*/true, /*IsExplicit=*/false, 989a7e2cc68SRichard Smith NumCreatedModules++); 9909d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = ModuleMapFile; 9919d6448b1SBen Langmuir Result->IsInferred = true; 9927e82e019SRichard Smith if (!Parent) { 9937e82e019SRichard Smith if (LangOpts.CurrentModule == ModuleName) 994ba7f2f71SDaniel Jasper SourceModule = Result; 9957e82e019SRichard Smith Modules[ModuleName] = Result; 996c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID; 997ba7f2f71SDaniel Jasper } 998c1d88ea5SBen Langmuir 999c1d88ea5SBen Langmuir Result->IsSystem |= Attrs.IsSystem; 1000c1d88ea5SBen Langmuir Result->IsExternC |= Attrs.IsExternC; 1001c1d88ea5SBen Langmuir Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive; 1002ed84df00SBruno Cardoso Lopes Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes; 10032b63d15fSRichard Smith Result->Directory = FrameworkDir; 1004a686e1b0SDouglas Gregor 1005322f633cSDouglas Gregor // umbrella header "umbrella-header-name" 10062b63d15fSRichard Smith // 10072b63d15fSRichard Smith // The "Headers/" component of the name is implied because this is 10082b63d15fSRichard Smith // a framework module. 10092b63d15fSRichard Smith setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h"); 1010d8bd7537SDouglas Gregor 1011d8bd7537SDouglas Gregor // export * 1012d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 1013d8bd7537SDouglas Gregor 1014a89c5ac4SDouglas Gregor // module * { export * } 1015a89c5ac4SDouglas Gregor Result->InferSubmodules = true; 1016a89c5ac4SDouglas Gregor Result->InferExportWildcard = true; 1017a89c5ac4SDouglas Gregor 1018e89dbc1dSDouglas Gregor // Look for subframeworks. 1019c080917eSRafael Espindola std::error_code EC; 10202c1dd271SDylan Noblesmith SmallString<128> SubframeworksDirName 1021ddaa69cbSDouglas Gregor = StringRef(FrameworkDir->getName()); 1022e89dbc1dSDouglas Gregor llvm::sys::path::append(SubframeworksDirName, "Frameworks"); 10232d4d8cb3SBenjamin Kramer llvm::sys::path::native(SubframeworksDirName); 1024*db8a7422SDuncan P. N. Exon Smith llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem(); 1025fc51490bSJonas Devlieghere for (llvm::vfs::directory_iterator 1026fc51490bSJonas Devlieghere Dir = FS.dir_begin(SubframeworksDirName, EC), 1027b171a59bSBruno Cardoso Lopes DirEnd; 1028e89dbc1dSDouglas Gregor Dir != DirEnd && !EC; Dir.increment(EC)) { 10290ae00567SSam McCall if (!StringRef(Dir->path()).endswith(".framework")) 1030e89dbc1dSDouglas Gregor continue; 1031f2161a70SDouglas Gregor 1032b171a59bSBruno Cardoso Lopes if (const DirectoryEntry *SubframeworkDir = 10330ae00567SSam McCall FileMgr.getDirectory(Dir->path())) { 103407c22b78SDouglas Gregor // Note: as an egregious but useful hack, we use the real path here and 103507c22b78SDouglas Gregor // check whether it is actually a subdirectory of the parent directory. 103607c22b78SDouglas Gregor // This will not be the case if the 'subframework' is actually a symlink 103707c22b78SDouglas Gregor // out to a top-level framework. 1038e00c8b20SDouglas Gregor StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir); 103907c22b78SDouglas Gregor bool FoundParent = false; 104007c22b78SDouglas Gregor do { 104107c22b78SDouglas Gregor // Get the parent directory name. 104207c22b78SDouglas Gregor SubframeworkDirName 104307c22b78SDouglas Gregor = llvm::sys::path::parent_path(SubframeworkDirName); 104407c22b78SDouglas Gregor if (SubframeworkDirName.empty()) 104507c22b78SDouglas Gregor break; 104607c22b78SDouglas Gregor 104707c22b78SDouglas Gregor if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) { 104807c22b78SDouglas Gregor FoundParent = true; 104907c22b78SDouglas Gregor break; 105007c22b78SDouglas Gregor } 105107c22b78SDouglas Gregor } while (true); 105207c22b78SDouglas Gregor 105307c22b78SDouglas Gregor if (!FoundParent) 105407c22b78SDouglas Gregor continue; 105507c22b78SDouglas Gregor 1056e89dbc1dSDouglas Gregor // FIXME: Do we want to warn about subframeworks without umbrella headers? 1057a525400dSBen Langmuir inferFrameworkModule(SubframeworkDir, Attrs, Result); 1058e89dbc1dSDouglas Gregor } 1059e89dbc1dSDouglas Gregor } 1060e89dbc1dSDouglas Gregor 106111dfe6feSDouglas Gregor // If the module is a top-level framework, automatically link against the 106211dfe6feSDouglas Gregor // framework. 106311dfe6feSDouglas Gregor if (!Result->isSubFramework()) { 106411dfe6feSDouglas Gregor inferFrameworkLink(Result, FrameworkDir, FileMgr); 106511dfe6feSDouglas Gregor } 106611dfe6feSDouglas Gregor 106756c64013SDouglas Gregor return Result; 106856c64013SDouglas Gregor } 106956c64013SDouglas Gregor 10708587dfd9SBruno Cardoso Lopes Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework, 10718587dfd9SBruno Cardoso Lopes Module *ShadowingModule) { 10728587dfd9SBruno Cardoso Lopes 10738587dfd9SBruno Cardoso Lopes // Create a new module with this name. 10748587dfd9SBruno Cardoso Lopes Module *Result = 10758587dfd9SBruno Cardoso Lopes new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework, 10768587dfd9SBruno Cardoso Lopes /*IsExplicit=*/false, NumCreatedModules++); 10778587dfd9SBruno Cardoso Lopes Result->ShadowingModule = ShadowingModule; 10788587dfd9SBruno Cardoso Lopes Result->IsAvailable = false; 1079c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID; 10808587dfd9SBruno Cardoso Lopes ShadowModules.push_back(Result); 10818587dfd9SBruno Cardoso Lopes 10828587dfd9SBruno Cardoso Lopes return Result; 10838587dfd9SBruno Cardoso Lopes } 10848587dfd9SBruno Cardoso Lopes 10852b63d15fSRichard Smith void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader, 10862b63d15fSRichard Smith Twine NameAsWritten) { 108797da9178SDaniel Jasper Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader)); 108873141fa9SDouglas Gregor Mod->Umbrella = UmbrellaHeader; 10892b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 10907033127bSDouglas Gregor UmbrellaDirs[UmbrellaHeader->getDir()] = Mod; 1091b3a0fa48SBruno Cardoso Lopes 1092b3a0fa48SBruno Cardoso Lopes // Notify callbacks that we just added a new header. 1093b3a0fa48SBruno Cardoso Lopes for (const auto &Cb : Callbacks) 1094b3a0fa48SBruno Cardoso Lopes Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader); 1095a89c5ac4SDouglas Gregor } 1096a89c5ac4SDouglas Gregor 10972b63d15fSRichard Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, 10982b63d15fSRichard Smith Twine NameAsWritten) { 1099524e33e1SDouglas Gregor Mod->Umbrella = UmbrellaDir; 11002b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 1101524e33e1SDouglas Gregor UmbrellaDirs[UmbrellaDir] = Mod; 1102524e33e1SDouglas Gregor } 1103524e33e1SDouglas Gregor 1104040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod, 11059f6020bcSBruno Cardoso Lopes Module::UnresolvedHeaderDirective Header, 11069f6020bcSBruno Cardoso Lopes bool &NeedsFramework) { 1107040e1266SRichard Smith // If there is a builtin counterpart to this file, add it now so it can 1108040e1266SRichard Smith // wrap the system header. 1109040e1266SRichard Smith if (resolveAsBuiltinHeader(Mod, Header)) { 1110040e1266SRichard Smith // If we have both a builtin and system version of the file, the 1111040e1266SRichard Smith // builtin version may want to inject macros into the system header, so 1112040e1266SRichard Smith // force the system header to be treated as a textual header in this 1113040e1266SRichard Smith // case. 1114040e1266SRichard Smith Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole( 1115040e1266SRichard Smith headerKindToRole(Header.Kind) | ModuleMap::TextualHeader)); 1116040e1266SRichard Smith Header.HasBuiltinHeader = true; 11173c1a41adSRichard Smith } 1118040e1266SRichard Smith 1119040e1266SRichard Smith // If possible, don't stat the header until we need to. This requires the 1120040e1266SRichard Smith // user to have provided us with some stat information about the file. 1121040e1266SRichard Smith // FIXME: Add support for lazily stat'ing umbrella headers and excluded 1122040e1266SRichard Smith // headers. 1123040e1266SRichard Smith if ((Header.Size || Header.ModTime) && !Header.IsUmbrella && 1124040e1266SRichard Smith Header.Kind != Module::HK_Excluded) { 1125040e1266SRichard Smith // We expect more variation in mtime than size, so if we're given both, 1126040e1266SRichard Smith // use the mtime as the key. 1127040e1266SRichard Smith if (Header.ModTime) 1128040e1266SRichard Smith LazyHeadersByModTime[*Header.ModTime].push_back(Mod); 1129040e1266SRichard Smith else 1130040e1266SRichard Smith LazyHeadersBySize[*Header.Size].push_back(Mod); 1131040e1266SRichard Smith Mod->UnresolvedHeaders.push_back(Header); 1132040e1266SRichard Smith return; 1133040e1266SRichard Smith } 1134040e1266SRichard Smith 1135040e1266SRichard Smith // We don't have stat information or can't defer looking this file up. 1136040e1266SRichard Smith // Perform the lookup now. 11379f6020bcSBruno Cardoso Lopes resolveHeader(Mod, Header, NeedsFramework); 1138040e1266SRichard Smith } 1139040e1266SRichard Smith 1140040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const { 1141040e1266SRichard Smith auto BySize = LazyHeadersBySize.find(File->getSize()); 1142040e1266SRichard Smith if (BySize != LazyHeadersBySize.end()) { 1143040e1266SRichard Smith for (auto *M : BySize->second) 1144040e1266SRichard Smith resolveHeaderDirectives(M); 1145040e1266SRichard Smith LazyHeadersBySize.erase(BySize); 1146040e1266SRichard Smith } 1147040e1266SRichard Smith 1148040e1266SRichard Smith auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime()); 1149040e1266SRichard Smith if (ByModTime != LazyHeadersByModTime.end()) { 1150040e1266SRichard Smith for (auto *M : ByModTime->second) 1151040e1266SRichard Smith resolveHeaderDirectives(M); 1152040e1266SRichard Smith LazyHeadersByModTime.erase(ByModTime); 1153040e1266SRichard Smith } 1154040e1266SRichard Smith } 1155040e1266SRichard Smith 1156040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(Module *Mod) const { 11579f6020bcSBruno Cardoso Lopes bool NeedsFramework = false; 1158040e1266SRichard Smith for (auto &Header : Mod->UnresolvedHeaders) 1159040e1266SRichard Smith // This operation is logically const; we're just changing how we represent 1160040e1266SRichard Smith // the header information for this file. 11619f6020bcSBruno Cardoso Lopes const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework); 1162040e1266SRichard Smith Mod->UnresolvedHeaders.clear(); 11630e98d938SNAKAMURA Takumi } 1164202210b3SRichard Smith 11653c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header, 1166d8879c85SRichard Smith ModuleHeaderRole Role, bool Imported) { 1167386bb073SRichard Smith KnownHeader KH(Mod, Role); 11683c1a41adSRichard Smith 1169386bb073SRichard Smith // Only add each header to the headers list once. 1170386bb073SRichard Smith // FIXME: Should we diagnose if a header is listed twice in the 1171386bb073SRichard Smith // same module definition? 1172386bb073SRichard Smith auto &HeaderList = Headers[Header.Entry]; 1173386bb073SRichard Smith for (auto H : HeaderList) 1174386bb073SRichard Smith if (H == KH) 1175386bb073SRichard Smith return; 1176386bb073SRichard Smith 1177386bb073SRichard Smith HeaderList.push_back(KH); 11781ec383c7SPiotr Padlewski Mod->Headers[headerRoleToKind(Role)].push_back(Header); 1179386bb073SRichard Smith 11807e82e019SRichard Smith bool isCompilingModuleHeader = 1181bbcc9f04SRichard Smith LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule; 1182d8879c85SRichard Smith if (!Imported || isCompilingModuleHeader) { 1183d8879c85SRichard Smith // When we import HeaderFileInfo, the external source is expected to 1184d8879c85SRichard Smith // set the isModuleHeader flag itself. 1185d8879c85SRichard Smith HeaderInfo.MarkFileModuleHeader(Header.Entry, Role, 1186d8879c85SRichard Smith isCompilingModuleHeader); 1187d8879c85SRichard Smith } 1188e62cfd7cSBruno Cardoso Lopes 1189e62cfd7cSBruno Cardoso Lopes // Notify callbacks that we just added a new header. 1190e62cfd7cSBruno Cardoso Lopes for (const auto &Cb : Callbacks) 1191f0841790SBruno Cardoso Lopes Cb->moduleMapAddHeader(Header.Entry->getName()); 1192a89c5ac4SDouglas Gregor } 1193a89c5ac4SDouglas Gregor 11943c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) { 1195feb54b6dSRichard Smith // Add this as a known header so we won't implicitly add it to any 1196feb54b6dSRichard Smith // umbrella directory module. 1197feb54b6dSRichard Smith // FIXME: Should we only exclude it from umbrella modules within the 1198feb54b6dSRichard Smith // specified module? 11993c1a41adSRichard Smith (void) Headers[Header.Entry]; 12003c1a41adSRichard Smith 12013c1a41adSRichard Smith Mod->Headers[Module::HK_Excluded].push_back(std::move(Header)); 1202feb54b6dSRichard Smith } 1203feb54b6dSRichard Smith 1204514b636aSDouglas Gregor const FileEntry * 12054b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const { 12061f76c4e8SManuel Klimek if (Module->DefinitionLoc.isInvalid()) 1207d2d442caSCraig Topper return nullptr; 1208514b636aSDouglas Gregor 12091f76c4e8SManuel Klimek return SourceMgr.getFileEntryForID( 12101f76c4e8SManuel Klimek SourceMgr.getFileID(Module->DefinitionLoc)); 1211514b636aSDouglas Gregor } 1212514b636aSDouglas Gregor 12134b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const { 12149d6448b1SBen Langmuir if (M->IsInferred) { 12159d6448b1SBen Langmuir assert(InferredModuleAllowedBy.count(M) && "missing inferred module map"); 12169d6448b1SBen Langmuir return InferredModuleAllowedBy.find(M)->second; 12179d6448b1SBen Langmuir } 12189d6448b1SBen Langmuir return getContainingModuleMapFile(M); 12199d6448b1SBen Langmuir } 12209d6448b1SBen Langmuir 12219d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) { 12229d6448b1SBen Langmuir assert(M->IsInferred && "module not inferred"); 12239d6448b1SBen Langmuir InferredModuleAllowedBy[M] = ModMap; 12249d6448b1SBen Langmuir } 12259d6448b1SBen Langmuir 1226cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() { 1227718292f2SDouglas Gregor llvm::errs() << "Modules:"; 1228718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 1229718292f2SDouglas Gregor MEnd = Modules.end(); 1230718292f2SDouglas Gregor M != MEnd; ++M) 1231d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 1232718292f2SDouglas Gregor 1233718292f2SDouglas Gregor llvm::errs() << "Headers:"; 123459527666SDouglas Gregor for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end(); 1235718292f2SDouglas Gregor H != HEnd; ++H) { 123697da9178SDaniel Jasper llvm::errs() << " \"" << H->first->getName() << "\" -> "; 123797da9178SDaniel Jasper for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(), 123897da9178SDaniel Jasper E = H->second.end(); 123997da9178SDaniel Jasper I != E; ++I) { 124097da9178SDaniel Jasper if (I != H->second.begin()) 124197da9178SDaniel Jasper llvm::errs() << ","; 124297da9178SDaniel Jasper llvm::errs() << I->getModule()->getFullModuleName(); 124397da9178SDaniel Jasper } 124497da9178SDaniel Jasper llvm::errs() << "\n"; 1245718292f2SDouglas Gregor } 1246718292f2SDouglas Gregor } 1247718292f2SDouglas Gregor 12482b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) { 124942413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedExports); 125042413141SRichard Smith Mod->UnresolvedExports.clear(); 125142413141SRichard Smith for (auto &UE : Unresolved) { 125242413141SRichard Smith Module::ExportDecl Export = resolveExport(Mod, UE, Complain); 1253f5eedd05SDouglas Gregor if (Export.getPointer() || Export.getInt()) 12542b82c2a5SDouglas Gregor Mod->Exports.push_back(Export); 12552b82c2a5SDouglas Gregor else 125642413141SRichard Smith Mod->UnresolvedExports.push_back(UE); 12572b82c2a5SDouglas Gregor } 125842413141SRichard Smith return !Mod->UnresolvedExports.empty(); 12592b82c2a5SDouglas Gregor } 12602b82c2a5SDouglas Gregor 1261ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) { 126242413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedDirectUses); 126342413141SRichard Smith Mod->UnresolvedDirectUses.clear(); 126442413141SRichard Smith for (auto &UDU : Unresolved) { 126542413141SRichard Smith Module *DirectUse = resolveModuleId(UDU, Mod, Complain); 1266ba7f2f71SDaniel Jasper if (DirectUse) 1267ba7f2f71SDaniel Jasper Mod->DirectUses.push_back(DirectUse); 1268ba7f2f71SDaniel Jasper else 126942413141SRichard Smith Mod->UnresolvedDirectUses.push_back(UDU); 1270ba7f2f71SDaniel Jasper } 127142413141SRichard Smith return !Mod->UnresolvedDirectUses.empty(); 1272ba7f2f71SDaniel Jasper } 1273ba7f2f71SDaniel Jasper 1274fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) { 127542413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedConflicts); 127642413141SRichard Smith Mod->UnresolvedConflicts.clear(); 127742413141SRichard Smith for (auto &UC : Unresolved) { 127842413141SRichard Smith if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) { 1279fb912657SDouglas Gregor Module::Conflict Conflict; 1280fb912657SDouglas Gregor Conflict.Other = OtherMod; 128142413141SRichard Smith Conflict.Message = UC.Message; 1282fb912657SDouglas Gregor Mod->Conflicts.push_back(Conflict); 128342413141SRichard Smith } else 128442413141SRichard Smith Mod->UnresolvedConflicts.push_back(UC); 1285fb912657SDouglas Gregor } 128642413141SRichard Smith return !Mod->UnresolvedConflicts.empty(); 1287fb912657SDouglas Gregor } 1288fb912657SDouglas Gregor 1289718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1290718292f2SDouglas Gregor // Module map file parser 1291718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1292718292f2SDouglas Gregor 1293718292f2SDouglas Gregor namespace clang { 1294afd1b1c9SEugene Zelenko 12959fc8faf9SAdrian Prantl /// A token in a module map file. 1296718292f2SDouglas Gregor struct MMToken { 1297718292f2SDouglas Gregor enum TokenKind { 12981fb5c3a6SDouglas Gregor Comma, 129935b13eceSDouglas Gregor ConfigMacros, 1300fb912657SDouglas Gregor Conflict, 1301718292f2SDouglas Gregor EndOfFile, 1302718292f2SDouglas Gregor HeaderKeyword, 1303718292f2SDouglas Gregor Identifier, 1304a3feee2aSRichard Smith Exclaim, 130559527666SDouglas Gregor ExcludeKeyword, 1306718292f2SDouglas Gregor ExplicitKeyword, 13072b82c2a5SDouglas Gregor ExportKeyword, 1308f0b11de2SDouglas Gregor ExportAsKeyword, 130997292843SDaniel Jasper ExternKeyword, 1310755b2055SDouglas Gregor FrameworkKeyword, 13116ddfca91SDouglas Gregor LinkKeyword, 1312718292f2SDouglas Gregor ModuleKeyword, 13132b82c2a5SDouglas Gregor Period, 1314b53e5483SLawrence Crowl PrivateKeyword, 1315718292f2SDouglas Gregor UmbrellaKeyword, 1316ba7f2f71SDaniel Jasper UseKeyword, 13171fb5c3a6SDouglas Gregor RequiresKeyword, 13182b82c2a5SDouglas Gregor Star, 1319718292f2SDouglas Gregor StringLiteral, 1320040e1266SRichard Smith IntegerLiteral, 1321306d8920SRichard Smith TextualKeyword, 1322718292f2SDouglas Gregor LBrace, 1323a686e1b0SDouglas Gregor RBrace, 1324a686e1b0SDouglas Gregor LSquare, 1325a686e1b0SDouglas Gregor RSquare 1326718292f2SDouglas Gregor } Kind; 1327718292f2SDouglas Gregor 1328718292f2SDouglas Gregor unsigned Location; 1329718292f2SDouglas Gregor unsigned StringLength; 1330040e1266SRichard Smith union { 1331040e1266SRichard Smith // If Kind != IntegerLiteral. 1332718292f2SDouglas Gregor const char *StringData; 1333afd1b1c9SEugene Zelenko 1334040e1266SRichard Smith // If Kind == IntegerLiteral. 1335040e1266SRichard Smith uint64_t IntegerValue; 1336040e1266SRichard Smith }; 1337718292f2SDouglas Gregor 1338718292f2SDouglas Gregor void clear() { 1339718292f2SDouglas Gregor Kind = EndOfFile; 1340718292f2SDouglas Gregor Location = 0; 1341718292f2SDouglas Gregor StringLength = 0; 1342d2d442caSCraig Topper StringData = nullptr; 1343718292f2SDouglas Gregor } 1344718292f2SDouglas Gregor 1345718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 1346718292f2SDouglas Gregor 1347718292f2SDouglas Gregor SourceLocation getLocation() const { 1348718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 1349718292f2SDouglas Gregor } 1350718292f2SDouglas Gregor 1351040e1266SRichard Smith uint64_t getInteger() const { 1352040e1266SRichard Smith return Kind == IntegerLiteral ? IntegerValue : 0; 1353040e1266SRichard Smith } 1354040e1266SRichard Smith 1355718292f2SDouglas Gregor StringRef getString() const { 1356040e1266SRichard Smith return Kind == IntegerLiteral ? StringRef() 1357040e1266SRichard Smith : StringRef(StringData, StringLength); 1358718292f2SDouglas Gregor } 1359718292f2SDouglas Gregor }; 1360718292f2SDouglas Gregor 1361718292f2SDouglas Gregor class ModuleMapParser { 1362718292f2SDouglas Gregor Lexer &L; 1363718292f2SDouglas Gregor SourceManager &SourceMgr; 1364bc10b9fbSDouglas Gregor 13659fc8faf9SAdrian Prantl /// Default target information, used only for string literal 1366bc10b9fbSDouglas Gregor /// parsing. 1367bc10b9fbSDouglas Gregor const TargetInfo *Target; 1368bc10b9fbSDouglas Gregor 1369718292f2SDouglas Gregor DiagnosticsEngine &Diags; 1370718292f2SDouglas Gregor ModuleMap ⤅ 1371718292f2SDouglas Gregor 13729fc8faf9SAdrian Prantl /// The current module map file. 1373beee15e7SBen Langmuir const FileEntry *ModuleMapFile; 1374beee15e7SBen Langmuir 13759f6020bcSBruno Cardoso Lopes /// Source location of most recent parsed module declaration 13769f6020bcSBruno Cardoso Lopes SourceLocation CurrModuleDeclLoc; 13779f6020bcSBruno Cardoso Lopes 13789fc8faf9SAdrian Prantl /// The directory that file names in this module map file should 13799acb99e3SRichard Smith /// be resolved relative to. 13805257fc63SDouglas Gregor const DirectoryEntry *Directory; 13815257fc63SDouglas Gregor 13829fc8faf9SAdrian Prantl /// Whether this module map is in a system header directory. 1383963c5535SDouglas Gregor bool IsSystem; 1384963c5535SDouglas Gregor 13859fc8faf9SAdrian Prantl /// Whether an error occurred. 1386afd1b1c9SEugene Zelenko bool HadError = false; 1387718292f2SDouglas Gregor 13889fc8faf9SAdrian Prantl /// Stores string data for the various string literals referenced 1389718292f2SDouglas Gregor /// during parsing. 1390718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 1391718292f2SDouglas Gregor 13929fc8faf9SAdrian Prantl /// The current token. 1393718292f2SDouglas Gregor MMToken Tok; 1394718292f2SDouglas Gregor 13959fc8faf9SAdrian Prantl /// The active module. 1396afd1b1c9SEugene Zelenko Module *ActiveModule = nullptr; 1397718292f2SDouglas Gregor 13989fc8faf9SAdrian Prantl /// Whether a module uses the 'requires excluded' hack to mark its 13997ff29148SBen Langmuir /// contents as 'textual'. 14007ff29148SBen Langmuir /// 14017ff29148SBen Langmuir /// On older Darwin SDK versions, 'requires excluded' is used to mark the 14027ff29148SBen Langmuir /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as 14037ff29148SBen Langmuir /// non-modular headers. For backwards compatibility, we continue to 14047ff29148SBen Langmuir /// support this idiom for just these modules, and map the headers to 14057ff29148SBen Langmuir /// 'textual' to match the original intent. 14067ff29148SBen Langmuir llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack; 14077ff29148SBen Langmuir 14089fc8faf9SAdrian Prantl /// Consume the current token and return its location. 1409718292f2SDouglas Gregor SourceLocation consumeToken(); 1410718292f2SDouglas Gregor 14119fc8faf9SAdrian Prantl /// Skip tokens until we reach the a token with the given kind 1412718292f2SDouglas Gregor /// (or the end of the file). 1413718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 1414718292f2SDouglas Gregor 1415afd1b1c9SEugene Zelenko using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>; 1416afd1b1c9SEugene Zelenko 1417e7ab3669SDouglas Gregor bool parseModuleId(ModuleId &Id); 1418718292f2SDouglas Gregor void parseModuleDecl(); 141997292843SDaniel Jasper void parseExternModuleDecl(); 14201fb5c3a6SDouglas Gregor void parseRequiresDecl(); 1421afd1b1c9SEugene Zelenko void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc); 1422524e33e1SDouglas Gregor void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc); 14232b82c2a5SDouglas Gregor void parseExportDecl(); 1424f0b11de2SDouglas Gregor void parseExportAsDecl(); 1425ba7f2f71SDaniel Jasper void parseUseDecl(); 14266ddfca91SDouglas Gregor void parseLinkDecl(); 142735b13eceSDouglas Gregor void parseConfigMacros(); 1428fb912657SDouglas Gregor void parseConflict(); 14299194a91dSDouglas Gregor void parseInferredModuleDecl(bool Framework, bool Explicit); 1430c1d88ea5SBen Langmuir 14315f11e128SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra 14325f11e128SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH 14335f11e128SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written 14345f11e128SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits. 14355f11e128SBruno Cardoso Lopes void diagnosePrivateModules(SourceLocation ExplicitLoc, 14365f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc); 14375f11e128SBruno Cardoso Lopes 1438afd1b1c9SEugene Zelenko using Attributes = ModuleMap::Attributes; 1439afd1b1c9SEugene Zelenko 14404442605fSBill Wendling bool parseOptionalAttributes(Attributes &Attrs); 1441718292f2SDouglas Gregor 1442718292f2SDouglas Gregor public: 1443718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 14448587dfd9SBruno Cardoso Lopes const TargetInfo *Target, DiagnosticsEngine &Diags, 14458587dfd9SBruno Cardoso Lopes ModuleMap &Map, const FileEntry *ModuleMapFile, 1446c192d194SBruno Cardoso Lopes const DirectoryEntry *Directory, bool IsSystem) 1447bc10b9fbSDouglas Gregor : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map), 1448beee15e7SBen Langmuir ModuleMapFile(ModuleMapFile), Directory(Directory), 1449c192d194SBruno Cardoso Lopes IsSystem(IsSystem) { 1450718292f2SDouglas Gregor Tok.clear(); 1451718292f2SDouglas Gregor consumeToken(); 1452718292f2SDouglas Gregor } 1453718292f2SDouglas Gregor 1454718292f2SDouglas Gregor bool parseModuleMapFile(); 14558128f332SRichard Smith 14568128f332SRichard Smith bool terminatedByDirective() { return false; } 14578128f332SRichard Smith SourceLocation getLocation() { return Tok.getLocation(); } 1458718292f2SDouglas Gregor }; 1459afd1b1c9SEugene Zelenko 1460afd1b1c9SEugene Zelenko } // namespace clang 1461718292f2SDouglas Gregor 1462718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 1463718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 1464718292f2SDouglas Gregor 14658128f332SRichard Smith retry: 14668128f332SRichard Smith Tok.clear(); 1467718292f2SDouglas Gregor Token LToken; 1468718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 1469718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 1470718292f2SDouglas Gregor switch (LToken.getKind()) { 14712d57cea2SAlp Toker case tok::raw_identifier: { 14722d57cea2SAlp Toker StringRef RI = LToken.getRawIdentifier(); 14732d57cea2SAlp Toker Tok.StringData = RI.data(); 14742d57cea2SAlp Toker Tok.StringLength = RI.size(); 14752d57cea2SAlp Toker Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI) 147635b13eceSDouglas Gregor .Case("config_macros", MMToken::ConfigMacros) 1477fb912657SDouglas Gregor .Case("conflict", MMToken::Conflict) 147859527666SDouglas Gregor .Case("exclude", MMToken::ExcludeKeyword) 1479718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 14802b82c2a5SDouglas Gregor .Case("export", MMToken::ExportKeyword) 1481f0b11de2SDouglas Gregor .Case("export_as", MMToken::ExportAsKeyword) 148297292843SDaniel Jasper .Case("extern", MMToken::ExternKeyword) 1483755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 148435b13eceSDouglas Gregor .Case("header", MMToken::HeaderKeyword) 14856ddfca91SDouglas Gregor .Case("link", MMToken::LinkKeyword) 1486718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 1487b53e5483SLawrence Crowl .Case("private", MMToken::PrivateKeyword) 14881fb5c3a6SDouglas Gregor .Case("requires", MMToken::RequiresKeyword) 1489306d8920SRichard Smith .Case("textual", MMToken::TextualKeyword) 1490718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 1491ba7f2f71SDaniel Jasper .Case("use", MMToken::UseKeyword) 1492718292f2SDouglas Gregor .Default(MMToken::Identifier); 1493718292f2SDouglas Gregor break; 14942d57cea2SAlp Toker } 1495718292f2SDouglas Gregor 14961fb5c3a6SDouglas Gregor case tok::comma: 14971fb5c3a6SDouglas Gregor Tok.Kind = MMToken::Comma; 14981fb5c3a6SDouglas Gregor break; 14991fb5c3a6SDouglas Gregor 1500718292f2SDouglas Gregor case tok::eof: 1501718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 1502718292f2SDouglas Gregor break; 1503718292f2SDouglas Gregor 1504718292f2SDouglas Gregor case tok::l_brace: 1505718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 1506718292f2SDouglas Gregor break; 1507718292f2SDouglas Gregor 1508a686e1b0SDouglas Gregor case tok::l_square: 1509a686e1b0SDouglas Gregor Tok.Kind = MMToken::LSquare; 1510a686e1b0SDouglas Gregor break; 1511a686e1b0SDouglas Gregor 15122b82c2a5SDouglas Gregor case tok::period: 15132b82c2a5SDouglas Gregor Tok.Kind = MMToken::Period; 15142b82c2a5SDouglas Gregor break; 15152b82c2a5SDouglas Gregor 1516718292f2SDouglas Gregor case tok::r_brace: 1517718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 1518718292f2SDouglas Gregor break; 1519718292f2SDouglas Gregor 1520a686e1b0SDouglas Gregor case tok::r_square: 1521a686e1b0SDouglas Gregor Tok.Kind = MMToken::RSquare; 1522a686e1b0SDouglas Gregor break; 1523a686e1b0SDouglas Gregor 15242b82c2a5SDouglas Gregor case tok::star: 15252b82c2a5SDouglas Gregor Tok.Kind = MMToken::Star; 15262b82c2a5SDouglas Gregor break; 15272b82c2a5SDouglas Gregor 1528a3feee2aSRichard Smith case tok::exclaim: 1529a3feee2aSRichard Smith Tok.Kind = MMToken::Exclaim; 1530a3feee2aSRichard Smith break; 1531a3feee2aSRichard Smith 1532718292f2SDouglas Gregor case tok::string_literal: { 1533d67aea28SRichard Smith if (LToken.hasUDSuffix()) { 1534d67aea28SRichard Smith Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl); 1535d67aea28SRichard Smith HadError = true; 1536d67aea28SRichard Smith goto retry; 1537d67aea28SRichard Smith } 1538d67aea28SRichard Smith 1539718292f2SDouglas Gregor // Parse the string literal. 1540718292f2SDouglas Gregor LangOptions LangOpts; 15419d5583efSCraig Topper StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target); 1542718292f2SDouglas Gregor if (StringLiteral.hadError) 1543718292f2SDouglas Gregor goto retry; 1544718292f2SDouglas Gregor 1545718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 1546718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 1547718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 1548718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 1549718292f2SDouglas Gregor Saved[Length] = 0; 1550718292f2SDouglas Gregor 1551718292f2SDouglas Gregor // Form the token. 1552718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 1553718292f2SDouglas Gregor Tok.StringData = Saved; 1554718292f2SDouglas Gregor Tok.StringLength = Length; 1555718292f2SDouglas Gregor break; 1556718292f2SDouglas Gregor } 1557718292f2SDouglas Gregor 1558040e1266SRichard Smith case tok::numeric_constant: { 1559040e1266SRichard Smith // We don't support any suffixes or other complications. 1560040e1266SRichard Smith SmallString<32> SpellingBuffer; 1561040e1266SRichard Smith SpellingBuffer.resize(LToken.getLength() + 1); 1562040e1266SRichard Smith const char *Start = SpellingBuffer.data(); 1563040e1266SRichard Smith unsigned Length = 1564040e1266SRichard Smith Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts()); 1565040e1266SRichard Smith uint64_t Value; 1566040e1266SRichard Smith if (StringRef(Start, Length).getAsInteger(0, Value)) { 1567040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1568040e1266SRichard Smith HadError = true; 1569040e1266SRichard Smith goto retry; 1570040e1266SRichard Smith } 1571040e1266SRichard Smith 1572040e1266SRichard Smith Tok.Kind = MMToken::IntegerLiteral; 1573040e1266SRichard Smith Tok.IntegerValue = Value; 1574040e1266SRichard Smith break; 1575040e1266SRichard Smith } 1576040e1266SRichard Smith 1577718292f2SDouglas Gregor case tok::comment: 1578718292f2SDouglas Gregor goto retry; 1579718292f2SDouglas Gregor 15808128f332SRichard Smith case tok::hash: 15818128f332SRichard Smith // A module map can be terminated prematurely by 15828128f332SRichard Smith // #pragma clang module contents 15838128f332SRichard Smith // When building the module, we'll treat the rest of the file as the 15848128f332SRichard Smith // contents of the module. 15858128f332SRichard Smith { 15868128f332SRichard Smith auto NextIsIdent = [&](StringRef Str) -> bool { 15878128f332SRichard Smith L.LexFromRawLexer(LToken); 15888128f332SRichard Smith return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) && 15898128f332SRichard Smith LToken.getRawIdentifier() == Str; 15908128f332SRichard Smith }; 15918128f332SRichard Smith if (NextIsIdent("pragma") && NextIsIdent("clang") && 15928128f332SRichard Smith NextIsIdent("module") && NextIsIdent("contents")) { 15938128f332SRichard Smith Tok.Kind = MMToken::EndOfFile; 15948128f332SRichard Smith break; 15958128f332SRichard Smith } 15968128f332SRichard Smith } 15978128f332SRichard Smith LLVM_FALLTHROUGH; 15988128f332SRichard Smith 1599718292f2SDouglas Gregor default: 16008128f332SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1601718292f2SDouglas Gregor HadError = true; 1602718292f2SDouglas Gregor goto retry; 1603718292f2SDouglas Gregor } 1604718292f2SDouglas Gregor 1605718292f2SDouglas Gregor return Result; 1606718292f2SDouglas Gregor } 1607718292f2SDouglas Gregor 1608718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 1609718292f2SDouglas Gregor unsigned braceDepth = 0; 1610a686e1b0SDouglas Gregor unsigned squareDepth = 0; 1611718292f2SDouglas Gregor do { 1612718292f2SDouglas Gregor switch (Tok.Kind) { 1613718292f2SDouglas Gregor case MMToken::EndOfFile: 1614718292f2SDouglas Gregor return; 1615718292f2SDouglas Gregor 1616718292f2SDouglas Gregor case MMToken::LBrace: 1617a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1618718292f2SDouglas Gregor return; 1619718292f2SDouglas Gregor 1620718292f2SDouglas Gregor ++braceDepth; 1621718292f2SDouglas Gregor break; 1622718292f2SDouglas Gregor 1623a686e1b0SDouglas Gregor case MMToken::LSquare: 1624a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1625a686e1b0SDouglas Gregor return; 1626a686e1b0SDouglas Gregor 1627a686e1b0SDouglas Gregor ++squareDepth; 1628a686e1b0SDouglas Gregor break; 1629a686e1b0SDouglas Gregor 1630718292f2SDouglas Gregor case MMToken::RBrace: 1631718292f2SDouglas Gregor if (braceDepth > 0) 1632718292f2SDouglas Gregor --braceDepth; 1633718292f2SDouglas Gregor else if (Tok.is(K)) 1634718292f2SDouglas Gregor return; 1635718292f2SDouglas Gregor break; 1636718292f2SDouglas Gregor 1637a686e1b0SDouglas Gregor case MMToken::RSquare: 1638a686e1b0SDouglas Gregor if (squareDepth > 0) 1639a686e1b0SDouglas Gregor --squareDepth; 1640a686e1b0SDouglas Gregor else if (Tok.is(K)) 1641a686e1b0SDouglas Gregor return; 1642a686e1b0SDouglas Gregor break; 1643a686e1b0SDouglas Gregor 1644718292f2SDouglas Gregor default: 1645a686e1b0SDouglas Gregor if (braceDepth == 0 && squareDepth == 0 && Tok.is(K)) 1646718292f2SDouglas Gregor return; 1647718292f2SDouglas Gregor break; 1648718292f2SDouglas Gregor } 1649718292f2SDouglas Gregor 1650718292f2SDouglas Gregor consumeToken(); 1651718292f2SDouglas Gregor } while (true); 1652718292f2SDouglas Gregor } 1653718292f2SDouglas Gregor 16549fc8faf9SAdrian Prantl /// Parse a module-id. 1655e7ab3669SDouglas Gregor /// 1656e7ab3669SDouglas Gregor /// module-id: 1657e7ab3669SDouglas Gregor /// identifier 1658e7ab3669SDouglas Gregor /// identifier '.' module-id 1659e7ab3669SDouglas Gregor /// 1660e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise. 1661e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) { 1662e7ab3669SDouglas Gregor Id.clear(); 1663e7ab3669SDouglas Gregor do { 16643cd34c76SDaniel Jasper if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) { 1665e7ab3669SDouglas Gregor Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation())); 1666e7ab3669SDouglas Gregor consumeToken(); 1667e7ab3669SDouglas Gregor } else { 1668e7ab3669SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 1669e7ab3669SDouglas Gregor return true; 1670e7ab3669SDouglas Gregor } 1671e7ab3669SDouglas Gregor 1672e7ab3669SDouglas Gregor if (!Tok.is(MMToken::Period)) 1673e7ab3669SDouglas Gregor break; 1674e7ab3669SDouglas Gregor 1675e7ab3669SDouglas Gregor consumeToken(); 1676e7ab3669SDouglas Gregor } while (true); 1677e7ab3669SDouglas Gregor 1678e7ab3669SDouglas Gregor return false; 1679e7ab3669SDouglas Gregor } 1680e7ab3669SDouglas Gregor 1681a686e1b0SDouglas Gregor namespace { 1682afd1b1c9SEugene Zelenko 16839fc8faf9SAdrian Prantl /// Enumerates the known attributes. 1684a686e1b0SDouglas Gregor enum AttributeKind { 16859fc8faf9SAdrian Prantl /// An unknown attribute. 1686a686e1b0SDouglas Gregor AT_unknown, 1687afd1b1c9SEugene Zelenko 16889fc8faf9SAdrian Prantl /// The 'system' attribute. 168935b13eceSDouglas Gregor AT_system, 1690afd1b1c9SEugene Zelenko 16919fc8faf9SAdrian Prantl /// The 'extern_c' attribute. 169277944868SRichard Smith AT_extern_c, 1693afd1b1c9SEugene Zelenko 16949fc8faf9SAdrian Prantl /// The 'exhaustive' attribute. 1695ed84df00SBruno Cardoso Lopes AT_exhaustive, 1696afd1b1c9SEugene Zelenko 16979fc8faf9SAdrian Prantl /// The 'no_undeclared_includes' attribute. 1698ed84df00SBruno Cardoso Lopes AT_no_undeclared_includes 1699a686e1b0SDouglas Gregor }; 1700afd1b1c9SEugene Zelenko 1701afd1b1c9SEugene Zelenko } // namespace 1702a686e1b0SDouglas Gregor 170329729919SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra 170429729919SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH 170529729919SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written 170629729919SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits. 17075f11e128SBruno Cardoso Lopes void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc, 17085f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc) { 170929729919SBruno Cardoso Lopes auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical, 17107d29486dSBruno Cardoso Lopes const Module *M, SourceRange ReplLoc) { 171129729919SBruno Cardoso Lopes auto D = Diags.Report(ActiveModule->DefinitionLoc, 171229729919SBruno Cardoso Lopes diag::note_mmap_rename_top_level_private_module); 171329729919SBruno Cardoso Lopes D << BadName << M->Name; 17147d29486dSBruno Cardoso Lopes D << FixItHint::CreateReplacement(ReplLoc, Canonical); 171529729919SBruno Cardoso Lopes }; 171629729919SBruno Cardoso Lopes 171729729919SBruno Cardoso Lopes for (auto E = Map.module_begin(); E != Map.module_end(); ++E) { 171829729919SBruno Cardoso Lopes auto const *M = E->getValue(); 171929729919SBruno Cardoso Lopes if (M->Directory != ActiveModule->Directory) 172029729919SBruno Cardoso Lopes continue; 172129729919SBruno Cardoso Lopes 172229729919SBruno Cardoso Lopes SmallString<128> FullName(ActiveModule->getFullModuleName()); 172329729919SBruno Cardoso Lopes if (!FullName.startswith(M->Name) && !FullName.endswith("Private")) 172429729919SBruno Cardoso Lopes continue; 17255f11e128SBruno Cardoso Lopes SmallString<128> FixedPrivModDecl; 172629729919SBruno Cardoso Lopes SmallString<128> Canonical(M->Name); 172729729919SBruno Cardoso Lopes Canonical.append("_Private"); 172829729919SBruno Cardoso Lopes 172929729919SBruno Cardoso Lopes // Foo.Private -> Foo_Private 173029729919SBruno Cardoso Lopes if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent && 173129729919SBruno Cardoso Lopes M->Name == ActiveModule->Parent->Name) { 173229729919SBruno Cardoso Lopes Diags.Report(ActiveModule->DefinitionLoc, 173329729919SBruno Cardoso Lopes diag::warn_mmap_mismatched_private_submodule) 173429729919SBruno Cardoso Lopes << FullName; 17355f11e128SBruno Cardoso Lopes 17365f11e128SBruno Cardoso Lopes SourceLocation FixItInitBegin = CurrModuleDeclLoc; 17375f11e128SBruno Cardoso Lopes if (FrameworkLoc.isValid()) 17385f11e128SBruno Cardoso Lopes FixItInitBegin = FrameworkLoc; 17395f11e128SBruno Cardoso Lopes if (ExplicitLoc.isValid()) 17405f11e128SBruno Cardoso Lopes FixItInitBegin = ExplicitLoc; 17415f11e128SBruno Cardoso Lopes 17425f11e128SBruno Cardoso Lopes if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework) 17435f11e128SBruno Cardoso Lopes FixedPrivModDecl.append("framework "); 17445f11e128SBruno Cardoso Lopes FixedPrivModDecl.append("module "); 17455f11e128SBruno Cardoso Lopes FixedPrivModDecl.append(Canonical); 17465f11e128SBruno Cardoso Lopes 17475f11e128SBruno Cardoso Lopes GenNoteAndFixIt(FullName, FixedPrivModDecl, M, 17485f11e128SBruno Cardoso Lopes SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc)); 174929729919SBruno Cardoso Lopes continue; 175029729919SBruno Cardoso Lopes } 175129729919SBruno Cardoso Lopes 175229729919SBruno Cardoso Lopes // FooPrivate and whatnots -> Foo_Private 175329729919SBruno Cardoso Lopes if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name && 175429729919SBruno Cardoso Lopes ActiveModule->Name != Canonical) { 175529729919SBruno Cardoso Lopes Diags.Report(ActiveModule->DefinitionLoc, 175629729919SBruno Cardoso Lopes diag::warn_mmap_mismatched_private_module_name) 175729729919SBruno Cardoso Lopes << ActiveModule->Name; 17587d29486dSBruno Cardoso Lopes GenNoteAndFixIt(ActiveModule->Name, Canonical, M, 17597d29486dSBruno Cardoso Lopes SourceRange(ActiveModule->DefinitionLoc)); 176029729919SBruno Cardoso Lopes } 176129729919SBruno Cardoso Lopes } 176229729919SBruno Cardoso Lopes } 176329729919SBruno Cardoso Lopes 17649fc8faf9SAdrian Prantl /// Parse a module declaration. 1765718292f2SDouglas Gregor /// 1766718292f2SDouglas Gregor /// module-declaration: 176797292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 1768a686e1b0SDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt] 1769a686e1b0SDouglas Gregor /// { module-member* } 1770a686e1b0SDouglas Gregor /// 1771718292f2SDouglas Gregor /// module-member: 17721fb5c3a6SDouglas Gregor /// requires-declaration 1773718292f2SDouglas Gregor /// header-declaration 1774e7ab3669SDouglas Gregor /// submodule-declaration 17752b82c2a5SDouglas Gregor /// export-declaration 1776f0b11de2SDouglas Gregor /// export-as-declaration 17776ddfca91SDouglas Gregor /// link-declaration 177873441091SDouglas Gregor /// 177973441091SDouglas Gregor /// submodule-declaration: 178073441091SDouglas Gregor /// module-declaration 178173441091SDouglas Gregor /// inferred-submodule-declaration 1782718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 1783755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 178497292843SDaniel Jasper Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword)); 178597292843SDaniel Jasper if (Tok.is(MMToken::ExternKeyword)) { 178697292843SDaniel Jasper parseExternModuleDecl(); 178797292843SDaniel Jasper return; 178897292843SDaniel Jasper } 178997292843SDaniel Jasper 1790f2161a70SDouglas Gregor // Parse 'explicit' or 'framework' keyword, if present. 1791e7ab3669SDouglas Gregor SourceLocation ExplicitLoc; 17925f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc; 1793718292f2SDouglas Gregor bool Explicit = false; 1794f2161a70SDouglas Gregor bool Framework = false; 1795755b2055SDouglas Gregor 1796f2161a70SDouglas Gregor // Parse 'explicit' keyword, if present. 1797f2161a70SDouglas Gregor if (Tok.is(MMToken::ExplicitKeyword)) { 1798e7ab3669SDouglas Gregor ExplicitLoc = consumeToken(); 1799f2161a70SDouglas Gregor Explicit = true; 1800f2161a70SDouglas Gregor } 1801f2161a70SDouglas Gregor 1802f2161a70SDouglas Gregor // Parse 'framework' keyword, if present. 1803755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 18045f11e128SBruno Cardoso Lopes FrameworkLoc = consumeToken(); 1805755b2055SDouglas Gregor Framework = true; 1806755b2055SDouglas Gregor } 1807718292f2SDouglas Gregor 1808718292f2SDouglas Gregor // Parse 'module' keyword. 1809718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 1810d6343c99SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 1811718292f2SDouglas Gregor consumeToken(); 1812718292f2SDouglas Gregor HadError = true; 1813718292f2SDouglas Gregor return; 1814718292f2SDouglas Gregor } 18159f6020bcSBruno Cardoso Lopes CurrModuleDeclLoc = consumeToken(); // 'module' keyword 1816718292f2SDouglas Gregor 181773441091SDouglas Gregor // If we have a wildcard for the module name, this is an inferred submodule. 181873441091SDouglas Gregor // Parse it. 181973441091SDouglas Gregor if (Tok.is(MMToken::Star)) 18209194a91dSDouglas Gregor return parseInferredModuleDecl(Framework, Explicit); 182173441091SDouglas Gregor 1822718292f2SDouglas Gregor // Parse the module name. 1823e7ab3669SDouglas Gregor ModuleId Id; 1824e7ab3669SDouglas Gregor if (parseModuleId(Id)) { 1825718292f2SDouglas Gregor HadError = true; 1826718292f2SDouglas Gregor return; 1827718292f2SDouglas Gregor } 1828e7ab3669SDouglas Gregor 1829e7ab3669SDouglas Gregor if (ActiveModule) { 1830e7ab3669SDouglas Gregor if (Id.size() > 1) { 1831e7ab3669SDouglas Gregor Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id) 1832e7ab3669SDouglas Gregor << SourceRange(Id.front().second, Id.back().second); 1833e7ab3669SDouglas Gregor 1834e7ab3669SDouglas Gregor HadError = true; 1835e7ab3669SDouglas Gregor return; 1836e7ab3669SDouglas Gregor } 1837e7ab3669SDouglas Gregor } else if (Id.size() == 1 && Explicit) { 1838e7ab3669SDouglas Gregor // Top-level modules can't be explicit. 1839e7ab3669SDouglas Gregor Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level); 1840e7ab3669SDouglas Gregor Explicit = false; 1841e7ab3669SDouglas Gregor ExplicitLoc = SourceLocation(); 1842e7ab3669SDouglas Gregor HadError = true; 1843e7ab3669SDouglas Gregor } 1844e7ab3669SDouglas Gregor 1845e7ab3669SDouglas Gregor Module *PreviousActiveModule = ActiveModule; 1846e7ab3669SDouglas Gregor if (Id.size() > 1) { 1847e7ab3669SDouglas Gregor // This module map defines a submodule. Go find the module of which it 1848e7ab3669SDouglas Gregor // is a submodule. 1849d2d442caSCraig Topper ActiveModule = nullptr; 18504b8a9e95SBen Langmuir const Module *TopLevelModule = nullptr; 1851e7ab3669SDouglas Gregor for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) { 1852e7ab3669SDouglas Gregor if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) { 18534b8a9e95SBen Langmuir if (I == 0) 18544b8a9e95SBen Langmuir TopLevelModule = Next; 1855e7ab3669SDouglas Gregor ActiveModule = Next; 1856e7ab3669SDouglas Gregor continue; 1857e7ab3669SDouglas Gregor } 1858e7ab3669SDouglas Gregor 1859e7ab3669SDouglas Gregor if (ActiveModule) { 1860e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified) 18615b5d21eaSRichard Smith << Id[I].first 18625b5d21eaSRichard Smith << ActiveModule->getTopLevelModule()->getFullModuleName(); 1863e7ab3669SDouglas Gregor } else { 1864e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_expected_module_name); 1865e7ab3669SDouglas Gregor } 1866e7ab3669SDouglas Gregor HadError = true; 1867e7ab3669SDouglas Gregor return; 1868e7ab3669SDouglas Gregor } 18694b8a9e95SBen Langmuir 18704b8a9e95SBen Langmuir if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) { 18714b8a9e95SBen Langmuir assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) && 18724b8a9e95SBen Langmuir "submodule defined in same file as 'module *' that allowed its " 18734b8a9e95SBen Langmuir "top-level module"); 18744b8a9e95SBen Langmuir Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile); 18754b8a9e95SBen Langmuir } 1876e7ab3669SDouglas Gregor } 1877e7ab3669SDouglas Gregor 1878e7ab3669SDouglas Gregor StringRef ModuleName = Id.back().first; 1879e7ab3669SDouglas Gregor SourceLocation ModuleNameLoc = Id.back().second; 1880718292f2SDouglas Gregor 1881a686e1b0SDouglas Gregor // Parse the optional attribute list. 18824442605fSBill Wendling Attributes Attrs; 18835d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 18845d29dee0SDavide Italiano return; 18855d29dee0SDavide Italiano 1886718292f2SDouglas Gregor // Parse the opening brace. 1887718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 1888718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 1889718292f2SDouglas Gregor << ModuleName; 1890718292f2SDouglas Gregor HadError = true; 1891718292f2SDouglas Gregor return; 1892718292f2SDouglas Gregor } 1893718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 1894718292f2SDouglas Gregor 1895718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 18968587dfd9SBruno Cardoso Lopes Module *ShadowingModule = nullptr; 1897eb90e830SDouglas Gregor if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { 18984a3751ffSRichard Smith // We might see a (re)definition of a module that we already have a 18994a3751ffSRichard Smith // definition for in two cases: 19004a3751ffSRichard Smith // - If we loaded one definition from an AST file and we've just found a 19014a3751ffSRichard Smith // corresponding definition in a module map file, or 19024a3751ffSRichard Smith bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid(); 19034a3751ffSRichard Smith // - If we're building a (preprocessed) module and we've just loaded the 19044a3751ffSRichard Smith // module map file from which it was created. 19054a3751ffSRichard Smith bool ParsedAsMainInput = 19064a3751ffSRichard Smith Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap && 19074a3751ffSRichard Smith Map.LangOpts.CurrentModule == ModuleName && 19084a3751ffSRichard Smith SourceMgr.getDecomposedLoc(ModuleNameLoc).first != 19094a3751ffSRichard Smith SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first; 19104a3751ffSRichard Smith if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) { 1911fcc54a3bSDouglas Gregor // Skip the module definition. 1912fcc54a3bSDouglas Gregor skipUntil(MMToken::RBrace); 1913fcc54a3bSDouglas Gregor if (Tok.is(MMToken::RBrace)) 1914fcc54a3bSDouglas Gregor consumeToken(); 1915fcc54a3bSDouglas Gregor else { 1916fcc54a3bSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 1917fcc54a3bSDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 1918fcc54a3bSDouglas Gregor HadError = true; 1919fcc54a3bSDouglas Gregor } 1920fcc54a3bSDouglas Gregor return; 1921fcc54a3bSDouglas Gregor } 1922fcc54a3bSDouglas Gregor 1923c192d194SBruno Cardoso Lopes if (!Existing->Parent && Map.mayShadowNewModule(Existing)) { 19248587dfd9SBruno Cardoso Lopes ShadowingModule = Existing; 19258587dfd9SBruno Cardoso Lopes } else { 19268587dfd9SBruno Cardoso Lopes // This is not a shawdowed module decl, it is an illegal redefinition. 1927718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 1928718292f2SDouglas Gregor << ModuleName; 1929eb90e830SDouglas Gregor Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition); 1930718292f2SDouglas Gregor 1931718292f2SDouglas Gregor // Skip the module definition. 1932718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 1933718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 1934718292f2SDouglas Gregor consumeToken(); 1935718292f2SDouglas Gregor 1936718292f2SDouglas Gregor HadError = true; 1937718292f2SDouglas Gregor return; 1938718292f2SDouglas Gregor } 19398587dfd9SBruno Cardoso Lopes } 1940718292f2SDouglas Gregor 1941718292f2SDouglas Gregor // Start defining this module. 19428587dfd9SBruno Cardoso Lopes if (ShadowingModule) { 19438587dfd9SBruno Cardoso Lopes ActiveModule = 19448587dfd9SBruno Cardoso Lopes Map.createShadowedModule(ModuleName, Framework, ShadowingModule); 19458587dfd9SBruno Cardoso Lopes } else { 1946c192d194SBruno Cardoso Lopes ActiveModule = 1947c192d194SBruno Cardoso Lopes Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit) 19488587dfd9SBruno Cardoso Lopes .first; 19498587dfd9SBruno Cardoso Lopes } 19508587dfd9SBruno Cardoso Lopes 1951eb90e830SDouglas Gregor ActiveModule->DefinitionLoc = ModuleNameLoc; 1952963c5535SDouglas Gregor if (Attrs.IsSystem || IsSystem) 1953a686e1b0SDouglas Gregor ActiveModule->IsSystem = true; 195477944868SRichard Smith if (Attrs.IsExternC) 195577944868SRichard Smith ActiveModule->IsExternC = true; 1956ed84df00SBruno Cardoso Lopes if (Attrs.NoUndeclaredIncludes || 1957ed84df00SBruno Cardoso Lopes (!ActiveModule->Parent && ModuleName == "Darwin")) 1958ed84df00SBruno Cardoso Lopes ActiveModule->NoUndeclaredIncludes = true; 19593c1a41adSRichard Smith ActiveModule->Directory = Directory; 1960718292f2SDouglas Gregor 196190b0a1fcSJordan Rose StringRef MapFileName(ModuleMapFile->getName()); 196290b0a1fcSJordan Rose if (MapFileName.endswith("module.private.modulemap") || 196390b0a1fcSJordan Rose MapFileName.endswith("module_private.map")) { 196490b0a1fcSJordan Rose ActiveModule->ModuleMapIsPrivate = true; 196590b0a1fcSJordan Rose } 196629729919SBruno Cardoso Lopes 196729729919SBruno Cardoso Lopes // Private modules named as FooPrivate, Foo.Private or similar are likely a 196829729919SBruno Cardoso Lopes // user error; provide warnings, notes and fixits to direct users to use 196929729919SBruno Cardoso Lopes // Foo_Private instead. 197029729919SBruno Cardoso Lopes SourceLocation StartLoc = 197129729919SBruno Cardoso Lopes SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()); 197229729919SBruno Cardoso Lopes if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && 197329729919SBruno Cardoso Lopes !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule, 197429729919SBruno Cardoso Lopes StartLoc) && 197529729919SBruno Cardoso Lopes !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name, 197629729919SBruno Cardoso Lopes StartLoc) && 197790b0a1fcSJordan Rose ActiveModule->ModuleMapIsPrivate) 19785f11e128SBruno Cardoso Lopes diagnosePrivateModules(ExplicitLoc, FrameworkLoc); 19794d867640SGraydon Hoare 1980718292f2SDouglas Gregor bool Done = false; 1981718292f2SDouglas Gregor do { 1982718292f2SDouglas Gregor switch (Tok.Kind) { 1983718292f2SDouglas Gregor case MMToken::EndOfFile: 1984718292f2SDouglas Gregor case MMToken::RBrace: 1985718292f2SDouglas Gregor Done = true; 1986718292f2SDouglas Gregor break; 1987718292f2SDouglas Gregor 198835b13eceSDouglas Gregor case MMToken::ConfigMacros: 198935b13eceSDouglas Gregor parseConfigMacros(); 199035b13eceSDouglas Gregor break; 199135b13eceSDouglas Gregor 1992fb912657SDouglas Gregor case MMToken::Conflict: 1993fb912657SDouglas Gregor parseConflict(); 1994fb912657SDouglas Gregor break; 1995fb912657SDouglas Gregor 1996718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 199797292843SDaniel Jasper case MMToken::ExternKeyword: 1998f2161a70SDouglas Gregor case MMToken::FrameworkKeyword: 1999718292f2SDouglas Gregor case MMToken::ModuleKeyword: 2000718292f2SDouglas Gregor parseModuleDecl(); 2001718292f2SDouglas Gregor break; 2002718292f2SDouglas Gregor 20032b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 20042b82c2a5SDouglas Gregor parseExportDecl(); 20052b82c2a5SDouglas Gregor break; 20062b82c2a5SDouglas Gregor 2007f0b11de2SDouglas Gregor case MMToken::ExportAsKeyword: 2008f0b11de2SDouglas Gregor parseExportAsDecl(); 2009f0b11de2SDouglas Gregor break; 2010f0b11de2SDouglas Gregor 2011ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 2012ba7f2f71SDaniel Jasper parseUseDecl(); 2013ba7f2f71SDaniel Jasper break; 2014ba7f2f71SDaniel Jasper 20151fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 20161fb5c3a6SDouglas Gregor parseRequiresDecl(); 20171fb5c3a6SDouglas Gregor break; 20181fb5c3a6SDouglas Gregor 2019202210b3SRichard Smith case MMToken::TextualKeyword: 2020202210b3SRichard Smith parseHeaderDecl(MMToken::TextualKeyword, consumeToken()); 2021306d8920SRichard Smith break; 2022306d8920SRichard Smith 2023524e33e1SDouglas Gregor case MMToken::UmbrellaKeyword: { 2024524e33e1SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 2025524e33e1SDouglas Gregor if (Tok.is(MMToken::HeaderKeyword)) 2026b53e5483SLawrence Crowl parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc); 2027524e33e1SDouglas Gregor else 2028524e33e1SDouglas Gregor parseUmbrellaDirDecl(UmbrellaLoc); 2029718292f2SDouglas Gregor break; 2030524e33e1SDouglas Gregor } 2031718292f2SDouglas Gregor 2032202210b3SRichard Smith case MMToken::ExcludeKeyword: 2033202210b3SRichard Smith parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken()); 203459527666SDouglas Gregor break; 203559527666SDouglas Gregor 2036202210b3SRichard Smith case MMToken::PrivateKeyword: 2037202210b3SRichard Smith parseHeaderDecl(MMToken::PrivateKeyword, consumeToken()); 2038b53e5483SLawrence Crowl break; 2039b53e5483SLawrence Crowl 2040322f633cSDouglas Gregor case MMToken::HeaderKeyword: 2041202210b3SRichard Smith parseHeaderDecl(MMToken::HeaderKeyword, consumeToken()); 2042718292f2SDouglas Gregor break; 2043718292f2SDouglas Gregor 20446ddfca91SDouglas Gregor case MMToken::LinkKeyword: 20456ddfca91SDouglas Gregor parseLinkDecl(); 20466ddfca91SDouglas Gregor break; 20476ddfca91SDouglas Gregor 2048718292f2SDouglas Gregor default: 2049718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 2050718292f2SDouglas Gregor consumeToken(); 2051718292f2SDouglas Gregor break; 2052718292f2SDouglas Gregor } 2053718292f2SDouglas Gregor } while (!Done); 2054718292f2SDouglas Gregor 2055718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 2056718292f2SDouglas Gregor consumeToken(); 2057718292f2SDouglas Gregor else { 2058718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 2059718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 2060718292f2SDouglas Gregor HadError = true; 2061718292f2SDouglas Gregor } 2062718292f2SDouglas Gregor 206311dfe6feSDouglas Gregor // If the active module is a top-level framework, and there are no link 206411dfe6feSDouglas Gregor // libraries, automatically link against the framework. 206511dfe6feSDouglas Gregor if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() && 206611dfe6feSDouglas Gregor ActiveModule->LinkLibraries.empty()) { 206711dfe6feSDouglas Gregor inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager()); 206811dfe6feSDouglas Gregor } 206911dfe6feSDouglas Gregor 2070ec8c9752SBen Langmuir // If the module meets all requirements but is still unavailable, mark the 2071ec8c9752SBen Langmuir // whole tree as unavailable to prevent it from building. 2072ec8c9752SBen Langmuir if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement && 2073ec8c9752SBen Langmuir ActiveModule->Parent) { 2074ec8c9752SBen Langmuir ActiveModule->getTopLevelModule()->markUnavailable(); 2075ec8c9752SBen Langmuir ActiveModule->getTopLevelModule()->MissingHeaders.append( 2076ec8c9752SBen Langmuir ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end()); 2077ec8c9752SBen Langmuir } 2078ec8c9752SBen Langmuir 2079e7ab3669SDouglas Gregor // We're done parsing this module. Pop back to the previous module. 2080e7ab3669SDouglas Gregor ActiveModule = PreviousActiveModule; 2081718292f2SDouglas Gregor } 2082718292f2SDouglas Gregor 20839fc8faf9SAdrian Prantl /// Parse an extern module declaration. 208497292843SDaniel Jasper /// 208597292843SDaniel Jasper /// extern module-declaration: 208697292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 208797292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() { 208897292843SDaniel Jasper assert(Tok.is(MMToken::ExternKeyword)); 2089ae6df27eSRichard Smith SourceLocation ExternLoc = consumeToken(); // 'extern' keyword 209097292843SDaniel Jasper 209197292843SDaniel Jasper // Parse 'module' keyword. 209297292843SDaniel Jasper if (!Tok.is(MMToken::ModuleKeyword)) { 209397292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 209497292843SDaniel Jasper consumeToken(); 209597292843SDaniel Jasper HadError = true; 209697292843SDaniel Jasper return; 209797292843SDaniel Jasper } 209897292843SDaniel Jasper consumeToken(); // 'module' keyword 209997292843SDaniel Jasper 210097292843SDaniel Jasper // Parse the module name. 210197292843SDaniel Jasper ModuleId Id; 210297292843SDaniel Jasper if (parseModuleId(Id)) { 210397292843SDaniel Jasper HadError = true; 210497292843SDaniel Jasper return; 210597292843SDaniel Jasper } 210697292843SDaniel Jasper 210797292843SDaniel Jasper // Parse the referenced module map file name. 210897292843SDaniel Jasper if (!Tok.is(MMToken::StringLiteral)) { 210997292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file); 211097292843SDaniel Jasper HadError = true; 211197292843SDaniel Jasper return; 211297292843SDaniel Jasper } 211397292843SDaniel Jasper std::string FileName = Tok.getString(); 211497292843SDaniel Jasper consumeToken(); // filename 211597292843SDaniel Jasper 211697292843SDaniel Jasper StringRef FileNameRef = FileName; 211797292843SDaniel Jasper SmallString<128> ModuleMapFileName; 211897292843SDaniel Jasper if (llvm::sys::path::is_relative(FileNameRef)) { 211997292843SDaniel Jasper ModuleMapFileName += Directory->getName(); 212097292843SDaniel Jasper llvm::sys::path::append(ModuleMapFileName, FileName); 212192e1b62dSYaron Keren FileNameRef = ModuleMapFileName; 212297292843SDaniel Jasper } 212397292843SDaniel Jasper if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef)) 21249acb99e3SRichard Smith Map.parseModuleMapFile( 21259acb99e3SRichard Smith File, /*IsSystem=*/false, 21269acb99e3SRichard Smith Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd 21279acb99e3SRichard Smith ? Directory 21288128f332SRichard Smith : File->getDir(), 2129c192d194SBruno Cardoso Lopes FileID(), nullptr, ExternLoc); 213097292843SDaniel Jasper } 213197292843SDaniel Jasper 21327ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M. 21337ff29148SBen Langmuir /// 21347ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system 21357ff29148SBen Langmuir /// module map files: 21367ff29148SBen Langmuir /// 21377ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which 21387ff29148SBen Langmuir /// should really be mapped to 'textual' now that we have this feature. We 21397ff29148SBen Langmuir /// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to 21407ff29148SBen Langmuir /// true. Later, this bit will be used to map all the headers inside this 21417ff29148SBen Langmuir /// module to 'textual'. 21427ff29148SBen Langmuir /// 21437ff29148SBen Langmuir /// This affects Darwin.C.excluded (for assert.h) and Tcl.Private. 21447ff29148SBen Langmuir /// 21457ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement 21467ff29148SBen Langmuir /// was never correct and causes issues now that we check it, so drop it. 21477ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature, 21487ff29148SBen Langmuir bool &IsRequiresExcludedHack) { 21498013e81dSBenjamin Kramer if (Feature == "excluded" && 21508013e81dSBenjamin Kramer (M->fullModuleNameIs({"Darwin", "C", "excluded"}) || 21518013e81dSBenjamin Kramer M->fullModuleNameIs({"Tcl", "Private"}))) { 21527ff29148SBen Langmuir IsRequiresExcludedHack = true; 21537ff29148SBen Langmuir return false; 21548013e81dSBenjamin Kramer } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) { 21557ff29148SBen Langmuir return false; 21567ff29148SBen Langmuir } 21577ff29148SBen Langmuir 21587ff29148SBen Langmuir return true; 21597ff29148SBen Langmuir } 21607ff29148SBen Langmuir 21619fc8faf9SAdrian Prantl /// Parse a requires declaration. 21621fb5c3a6SDouglas Gregor /// 21631fb5c3a6SDouglas Gregor /// requires-declaration: 21641fb5c3a6SDouglas Gregor /// 'requires' feature-list 21651fb5c3a6SDouglas Gregor /// 21661fb5c3a6SDouglas Gregor /// feature-list: 2167a3feee2aSRichard Smith /// feature ',' feature-list 2168a3feee2aSRichard Smith /// feature 2169a3feee2aSRichard Smith /// 2170a3feee2aSRichard Smith /// feature: 2171a3feee2aSRichard Smith /// '!'[opt] identifier 21721fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() { 21731fb5c3a6SDouglas Gregor assert(Tok.is(MMToken::RequiresKeyword)); 21741fb5c3a6SDouglas Gregor 21751fb5c3a6SDouglas Gregor // Parse 'requires' keyword. 21761fb5c3a6SDouglas Gregor consumeToken(); 21771fb5c3a6SDouglas Gregor 21781fb5c3a6SDouglas Gregor // Parse the feature-list. 21791fb5c3a6SDouglas Gregor do { 2180a3feee2aSRichard Smith bool RequiredState = true; 2181a3feee2aSRichard Smith if (Tok.is(MMToken::Exclaim)) { 2182a3feee2aSRichard Smith RequiredState = false; 2183a3feee2aSRichard Smith consumeToken(); 2184a3feee2aSRichard Smith } 2185a3feee2aSRichard Smith 21861fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 21871fb5c3a6SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature); 21881fb5c3a6SDouglas Gregor HadError = true; 21891fb5c3a6SDouglas Gregor return; 21901fb5c3a6SDouglas Gregor } 21911fb5c3a6SDouglas Gregor 21921fb5c3a6SDouglas Gregor // Consume the feature name. 21931fb5c3a6SDouglas Gregor std::string Feature = Tok.getString(); 21941fb5c3a6SDouglas Gregor consumeToken(); 21951fb5c3a6SDouglas Gregor 21967ff29148SBen Langmuir bool IsRequiresExcludedHack = false; 21977ff29148SBen Langmuir bool ShouldAddRequirement = 21987ff29148SBen Langmuir shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack); 21997ff29148SBen Langmuir 22007ff29148SBen Langmuir if (IsRequiresExcludedHack) 22017ff29148SBen Langmuir UsesRequiresExcludedHack.insert(ActiveModule); 22027ff29148SBen Langmuir 22037ff29148SBen Langmuir if (ShouldAddRequirement) { 22041fb5c3a6SDouglas Gregor // Add this feature. 22057ff29148SBen Langmuir ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts, 22067ff29148SBen Langmuir *Map.Target); 22077ff29148SBen Langmuir } 22081fb5c3a6SDouglas Gregor 22091fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Comma)) 22101fb5c3a6SDouglas Gregor break; 22111fb5c3a6SDouglas Gregor 22121fb5c3a6SDouglas Gregor // Consume the comma. 22131fb5c3a6SDouglas Gregor consumeToken(); 22141fb5c3a6SDouglas Gregor } while (true); 22151fb5c3a6SDouglas Gregor } 22161fb5c3a6SDouglas Gregor 22179fc8faf9SAdrian Prantl /// Parse a header declaration. 2218718292f2SDouglas Gregor /// 2219718292f2SDouglas Gregor /// header-declaration: 2220306d8920SRichard Smith /// 'textual'[opt] 'header' string-literal 2221202210b3SRichard Smith /// 'private' 'textual'[opt] 'header' string-literal 2222202210b3SRichard Smith /// 'exclude' 'header' string-literal 2223202210b3SRichard Smith /// 'umbrella' 'header' string-literal 2224306d8920SRichard Smith /// 2225306d8920SRichard Smith /// FIXME: Support 'private textual header'. 2226b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, 2227b53e5483SLawrence Crowl SourceLocation LeadingLoc) { 2228202210b3SRichard Smith // We've already consumed the first token. 2229202210b3SRichard Smith ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader; 2230202210b3SRichard Smith if (LeadingToken == MMToken::PrivateKeyword) { 2231202210b3SRichard Smith Role = ModuleMap::PrivateHeader; 2232202210b3SRichard Smith // 'private' may optionally be followed by 'textual'. 2233202210b3SRichard Smith if (Tok.is(MMToken::TextualKeyword)) { 2234202210b3SRichard Smith LeadingToken = Tok.Kind; 22351871ed3dSBenjamin Kramer consumeToken(); 2236202210b3SRichard Smith } 2237202210b3SRichard Smith } 22387ff29148SBen Langmuir 2239202210b3SRichard Smith if (LeadingToken == MMToken::TextualKeyword) 2240202210b3SRichard Smith Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 2241202210b3SRichard Smith 22427ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 22437ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 22447ff29148SBen Langmuir // Module::UsesRequiresExcludedHack). 22457ff29148SBen Langmuir Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 22467ff29148SBen Langmuir } 22477ff29148SBen Langmuir 2248202210b3SRichard Smith if (LeadingToken != MMToken::HeaderKeyword) { 2249202210b3SRichard Smith if (!Tok.is(MMToken::HeaderKeyword)) { 2250202210b3SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2251202210b3SRichard Smith << (LeadingToken == MMToken::PrivateKeyword ? "private" : 2252202210b3SRichard Smith LeadingToken == MMToken::ExcludeKeyword ? "exclude" : 2253202210b3SRichard Smith LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella"); 2254202210b3SRichard Smith return; 2255202210b3SRichard Smith } 2256202210b3SRichard Smith consumeToken(); 2257202210b3SRichard Smith } 2258718292f2SDouglas Gregor 2259718292f2SDouglas Gregor // Parse the header name. 2260718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2261718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2262718292f2SDouglas Gregor << "header"; 2263718292f2SDouglas Gregor HadError = true; 2264718292f2SDouglas Gregor return; 2265718292f2SDouglas Gregor } 22663c1a41adSRichard Smith Module::UnresolvedHeaderDirective Header; 22670761a8a0SDaniel Jasper Header.FileName = Tok.getString(); 22680761a8a0SDaniel Jasper Header.FileNameLoc = consumeToken(); 22691d60987fSRichard Smith Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword; 2270040e1266SRichard Smith Header.Kind = 2271040e1266SRichard Smith (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded 2272040e1266SRichard Smith : Map.headerRoleToKind(Role)); 2273718292f2SDouglas Gregor 2274524e33e1SDouglas Gregor // Check whether we already have an umbrella. 22751d60987fSRichard Smith if (Header.IsUmbrella && ActiveModule->Umbrella) { 22760761a8a0SDaniel Jasper Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) 2277524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2278322f633cSDouglas Gregor HadError = true; 2279322f633cSDouglas Gregor return; 2280322f633cSDouglas Gregor } 2281322f633cSDouglas Gregor 2282040e1266SRichard Smith // If we were given stat information, parse it so we can skip looking for 2283040e1266SRichard Smith // the file. 2284040e1266SRichard Smith if (Tok.is(MMToken::LBrace)) { 2285040e1266SRichard Smith SourceLocation LBraceLoc = consumeToken(); 22863ec6663bSDouglas Gregor 2287040e1266SRichard Smith while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) { 2288040e1266SRichard Smith enum Attribute { Size, ModTime, Unknown }; 2289040e1266SRichard Smith StringRef Str = Tok.getString(); 2290040e1266SRichard Smith SourceLocation Loc = consumeToken(); 2291040e1266SRichard Smith switch (llvm::StringSwitch<Attribute>(Str) 2292040e1266SRichard Smith .Case("size", Size) 2293040e1266SRichard Smith .Case("mtime", ModTime) 2294040e1266SRichard Smith .Default(Unknown)) { 2295040e1266SRichard Smith case Size: 2296040e1266SRichard Smith if (Header.Size) 2297040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2298040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2299040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2300040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2301040e1266SRichard Smith skipUntil(MMToken::RBrace); 2302040e1266SRichard Smith break; 2303040e1266SRichard Smith } 2304040e1266SRichard Smith Header.Size = Tok.getInteger(); 2305040e1266SRichard Smith consumeToken(); 2306040e1266SRichard Smith break; 2307040e1266SRichard Smith 2308040e1266SRichard Smith case ModTime: 2309040e1266SRichard Smith if (Header.ModTime) 2310040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2311040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2312040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2313040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2314040e1266SRichard Smith skipUntil(MMToken::RBrace); 2315040e1266SRichard Smith break; 2316040e1266SRichard Smith } 2317040e1266SRichard Smith Header.ModTime = Tok.getInteger(); 2318040e1266SRichard Smith consumeToken(); 2319040e1266SRichard Smith break; 2320040e1266SRichard Smith 2321040e1266SRichard Smith case Unknown: 2322040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_expected_header_attribute); 2323040e1266SRichard Smith skipUntil(MMToken::RBrace); 2324040e1266SRichard Smith break; 2325040e1266SRichard Smith } 23263ec6663bSDouglas Gregor } 23275257fc63SDouglas Gregor 2328040e1266SRichard Smith if (Tok.is(MMToken::RBrace)) 2329040e1266SRichard Smith consumeToken(); 2330040e1266SRichard Smith else { 2331040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 2332040e1266SRichard Smith Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 2333322f633cSDouglas Gregor HadError = true; 2334322f633cSDouglas Gregor } 23350101b540SHans Wennborg } 233625d50758SRichard Smith 23379f6020bcSBruno Cardoso Lopes bool NeedsFramework = false; 23389f6020bcSBruno Cardoso Lopes Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework); 23399f6020bcSBruno Cardoso Lopes 23409f6020bcSBruno Cardoso Lopes if (NeedsFramework && ActiveModule) 23419f6020bcSBruno Cardoso Lopes Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword) 23429f6020bcSBruno Cardoso Lopes << ActiveModule->getFullModuleName() 23439f6020bcSBruno Cardoso Lopes << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module"); 2344718292f2SDouglas Gregor } 2345718292f2SDouglas Gregor 234641f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A, 234741f81994SBen Langmuir const Module::Header *B) { 234841f81994SBen Langmuir return A->NameAsWritten.compare(B->NameAsWritten); 234941f81994SBen Langmuir } 235041f81994SBen Langmuir 23519fc8faf9SAdrian Prantl /// Parse an umbrella directory declaration. 2352524e33e1SDouglas Gregor /// 2353524e33e1SDouglas Gregor /// umbrella-dir-declaration: 2354524e33e1SDouglas Gregor /// umbrella string-literal 2355524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { 2356524e33e1SDouglas Gregor // Parse the directory name. 2357524e33e1SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2358524e33e1SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2359524e33e1SDouglas Gregor << "umbrella"; 2360524e33e1SDouglas Gregor HadError = true; 2361524e33e1SDouglas Gregor return; 2362524e33e1SDouglas Gregor } 2363524e33e1SDouglas Gregor 2364524e33e1SDouglas Gregor std::string DirName = Tok.getString(); 2365524e33e1SDouglas Gregor SourceLocation DirNameLoc = consumeToken(); 2366524e33e1SDouglas Gregor 2367524e33e1SDouglas Gregor // Check whether we already have an umbrella. 2368524e33e1SDouglas Gregor if (ActiveModule->Umbrella) { 2369524e33e1SDouglas Gregor Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash) 2370524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2371524e33e1SDouglas Gregor HadError = true; 2372524e33e1SDouglas Gregor return; 2373524e33e1SDouglas Gregor } 2374524e33e1SDouglas Gregor 2375524e33e1SDouglas Gregor // Look for this file. 2376d2d442caSCraig Topper const DirectoryEntry *Dir = nullptr; 2377524e33e1SDouglas Gregor if (llvm::sys::path::is_absolute(DirName)) 2378524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(DirName); 2379524e33e1SDouglas Gregor else { 23802c1dd271SDylan Noblesmith SmallString<128> PathName; 2381524e33e1SDouglas Gregor PathName = Directory->getName(); 2382524e33e1SDouglas Gregor llvm::sys::path::append(PathName, DirName); 2383524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(PathName); 2384524e33e1SDouglas Gregor } 2385524e33e1SDouglas Gregor 2386524e33e1SDouglas Gregor if (!Dir) { 2387a0320b97SVassil Vassilev Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found) 2388524e33e1SDouglas Gregor << DirName; 2389524e33e1SDouglas Gregor return; 2390524e33e1SDouglas Gregor } 2391524e33e1SDouglas Gregor 23927ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 23937ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 23947ff29148SBen Langmuir // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the 23957ff29148SBen Langmuir // directory is relatively expensive, in practice this only applies to the 23967ff29148SBen Langmuir // uncommonly used Tcl module on Darwin platforms. 23977ff29148SBen Langmuir std::error_code EC; 23987ff29148SBen Langmuir SmallVector<Module::Header, 6> Headers; 2399fc51490bSJonas Devlieghere llvm::vfs::FileSystem &FS = 2400*db8a7422SDuncan P. N. Exon Smith SourceMgr.getFileManager().getVirtualFileSystem(); 2401fc51490bSJonas Devlieghere for (llvm::vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E; 24027ff29148SBen Langmuir I != E && !EC; I.increment(EC)) { 24030ae00567SSam McCall if (const FileEntry *FE = SourceMgr.getFileManager().getFile(I->path())) { 24047ff29148SBen Langmuir 24050ae00567SSam McCall Module::Header Header = {I->path(), FE}; 24067ff29148SBen Langmuir Headers.push_back(std::move(Header)); 24077ff29148SBen Langmuir } 24087ff29148SBen Langmuir } 24097ff29148SBen Langmuir 24107ff29148SBen Langmuir // Sort header paths so that the pcm doesn't depend on iteration order. 241141f81994SBen Langmuir llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders); 241241f81994SBen Langmuir 24137ff29148SBen Langmuir for (auto &Header : Headers) 24147ff29148SBen Langmuir Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader); 24157ff29148SBen Langmuir return; 24167ff29148SBen Langmuir } 24177ff29148SBen Langmuir 2418524e33e1SDouglas Gregor if (Module *OwningModule = Map.UmbrellaDirs[Dir]) { 2419524e33e1SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 2420524e33e1SDouglas Gregor << OwningModule->getFullModuleName(); 2421524e33e1SDouglas Gregor HadError = true; 2422524e33e1SDouglas Gregor return; 2423524e33e1SDouglas Gregor } 2424524e33e1SDouglas Gregor 2425524e33e1SDouglas Gregor // Record this umbrella directory. 24262b63d15fSRichard Smith Map.setUmbrellaDir(ActiveModule, Dir, DirName); 2427524e33e1SDouglas Gregor } 2428524e33e1SDouglas Gregor 24299fc8faf9SAdrian Prantl /// Parse a module export declaration. 24302b82c2a5SDouglas Gregor /// 24312b82c2a5SDouglas Gregor /// export-declaration: 24322b82c2a5SDouglas Gregor /// 'export' wildcard-module-id 24332b82c2a5SDouglas Gregor /// 24342b82c2a5SDouglas Gregor /// wildcard-module-id: 24352b82c2a5SDouglas Gregor /// identifier 24362b82c2a5SDouglas Gregor /// '*' 24372b82c2a5SDouglas Gregor /// identifier '.' wildcard-module-id 24382b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() { 24392b82c2a5SDouglas Gregor assert(Tok.is(MMToken::ExportKeyword)); 24402b82c2a5SDouglas Gregor SourceLocation ExportLoc = consumeToken(); 24412b82c2a5SDouglas Gregor 24422b82c2a5SDouglas Gregor // Parse the module-id with an optional wildcard at the end. 24432b82c2a5SDouglas Gregor ModuleId ParsedModuleId; 24442b82c2a5SDouglas Gregor bool Wildcard = false; 24452b82c2a5SDouglas Gregor do { 2446306d8920SRichard Smith // FIXME: Support string-literal module names here. 24472b82c2a5SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 24482b82c2a5SDouglas Gregor ParsedModuleId.push_back(std::make_pair(Tok.getString(), 24492b82c2a5SDouglas Gregor Tok.getLocation())); 24502b82c2a5SDouglas Gregor consumeToken(); 24512b82c2a5SDouglas Gregor 24522b82c2a5SDouglas Gregor if (Tok.is(MMToken::Period)) { 24532b82c2a5SDouglas Gregor consumeToken(); 24542b82c2a5SDouglas Gregor continue; 24552b82c2a5SDouglas Gregor } 24562b82c2a5SDouglas Gregor 24572b82c2a5SDouglas Gregor break; 24582b82c2a5SDouglas Gregor } 24592b82c2a5SDouglas Gregor 24602b82c2a5SDouglas Gregor if(Tok.is(MMToken::Star)) { 24612b82c2a5SDouglas Gregor Wildcard = true; 2462f5eedd05SDouglas Gregor consumeToken(); 24632b82c2a5SDouglas Gregor break; 24642b82c2a5SDouglas Gregor } 24652b82c2a5SDouglas Gregor 2466ba7f2f71SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_module_id); 24672b82c2a5SDouglas Gregor HadError = true; 24682b82c2a5SDouglas Gregor return; 24692b82c2a5SDouglas Gregor } while (true); 24702b82c2a5SDouglas Gregor 24712b82c2a5SDouglas Gregor Module::UnresolvedExportDecl Unresolved = { 24722b82c2a5SDouglas Gregor ExportLoc, ParsedModuleId, Wildcard 24732b82c2a5SDouglas Gregor }; 24742b82c2a5SDouglas Gregor ActiveModule->UnresolvedExports.push_back(Unresolved); 24752b82c2a5SDouglas Gregor } 24762b82c2a5SDouglas Gregor 24779fc8faf9SAdrian Prantl /// Parse a module export_as declaration. 2478f0b11de2SDouglas Gregor /// 2479f0b11de2SDouglas Gregor /// export-as-declaration: 2480f0b11de2SDouglas Gregor /// 'export_as' identifier 2481f0b11de2SDouglas Gregor void ModuleMapParser::parseExportAsDecl() { 2482f0b11de2SDouglas Gregor assert(Tok.is(MMToken::ExportAsKeyword)); 2483f0b11de2SDouglas Gregor consumeToken(); 2484f0b11de2SDouglas Gregor 2485f0b11de2SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 2486f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_module_id); 2487f0b11de2SDouglas Gregor HadError = true; 2488f0b11de2SDouglas Gregor return; 2489f0b11de2SDouglas Gregor } 2490f0b11de2SDouglas Gregor 2491f0b11de2SDouglas Gregor if (ActiveModule->Parent) { 2492f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as); 2493f0b11de2SDouglas Gregor consumeToken(); 2494f0b11de2SDouglas Gregor return; 2495f0b11de2SDouglas Gregor } 2496f0b11de2SDouglas Gregor 2497f0b11de2SDouglas Gregor if (!ActiveModule->ExportAsModule.empty()) { 2498f0b11de2SDouglas Gregor if (ActiveModule->ExportAsModule == Tok.getString()) { 2499f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as) 2500f0b11de2SDouglas Gregor << ActiveModule->Name << Tok.getString(); 2501f0b11de2SDouglas Gregor } else { 2502f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as) 2503f0b11de2SDouglas Gregor << ActiveModule->Name << ActiveModule->ExportAsModule 2504f0b11de2SDouglas Gregor << Tok.getString(); 2505f0b11de2SDouglas Gregor } 2506f0b11de2SDouglas Gregor } 2507f0b11de2SDouglas Gregor 2508f0b11de2SDouglas Gregor ActiveModule->ExportAsModule = Tok.getString(); 2509a3b5f71eSBruno Cardoso Lopes Map.addLinkAsDependency(ActiveModule); 2510a3b5f71eSBruno Cardoso Lopes 2511f0b11de2SDouglas Gregor consumeToken(); 2512f0b11de2SDouglas Gregor } 2513f0b11de2SDouglas Gregor 25149fc8faf9SAdrian Prantl /// Parse a module use declaration. 2515ba7f2f71SDaniel Jasper /// 25168f4d3ff1SRichard Smith /// use-declaration: 25178f4d3ff1SRichard Smith /// 'use' wildcard-module-id 2518ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() { 2519ba7f2f71SDaniel Jasper assert(Tok.is(MMToken::UseKeyword)); 25208f4d3ff1SRichard Smith auto KWLoc = consumeToken(); 2521ba7f2f71SDaniel Jasper // Parse the module-id. 2522ba7f2f71SDaniel Jasper ModuleId ParsedModuleId; 25233cd34c76SDaniel Jasper parseModuleId(ParsedModuleId); 2524ba7f2f71SDaniel Jasper 25258f4d3ff1SRichard Smith if (ActiveModule->Parent) 25268f4d3ff1SRichard Smith Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule); 25278f4d3ff1SRichard Smith else 2528ba7f2f71SDaniel Jasper ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId); 2529ba7f2f71SDaniel Jasper } 2530ba7f2f71SDaniel Jasper 25319fc8faf9SAdrian Prantl /// Parse a link declaration. 25326ddfca91SDouglas Gregor /// 25336ddfca91SDouglas Gregor /// module-declaration: 25346ddfca91SDouglas Gregor /// 'link' 'framework'[opt] string-literal 25356ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() { 25366ddfca91SDouglas Gregor assert(Tok.is(MMToken::LinkKeyword)); 25376ddfca91SDouglas Gregor SourceLocation LinkLoc = consumeToken(); 25386ddfca91SDouglas Gregor 25396ddfca91SDouglas Gregor // Parse the optional 'framework' keyword. 25406ddfca91SDouglas Gregor bool IsFramework = false; 25416ddfca91SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 25426ddfca91SDouglas Gregor consumeToken(); 25436ddfca91SDouglas Gregor IsFramework = true; 25446ddfca91SDouglas Gregor } 25456ddfca91SDouglas Gregor 25466ddfca91SDouglas Gregor // Parse the library name 25476ddfca91SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 25486ddfca91SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name) 25496ddfca91SDouglas Gregor << IsFramework << SourceRange(LinkLoc); 25506ddfca91SDouglas Gregor HadError = true; 25516ddfca91SDouglas Gregor return; 25526ddfca91SDouglas Gregor } 25536ddfca91SDouglas Gregor 25546ddfca91SDouglas Gregor std::string LibraryName = Tok.getString(); 25556ddfca91SDouglas Gregor consumeToken(); 25566ddfca91SDouglas Gregor ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName, 25576ddfca91SDouglas Gregor IsFramework)); 25586ddfca91SDouglas Gregor } 25596ddfca91SDouglas Gregor 25609fc8faf9SAdrian Prantl /// Parse a configuration macro declaration. 256135b13eceSDouglas Gregor /// 256235b13eceSDouglas Gregor /// module-declaration: 256335b13eceSDouglas Gregor /// 'config_macros' attributes[opt] config-macro-list? 256435b13eceSDouglas Gregor /// 256535b13eceSDouglas Gregor /// config-macro-list: 256635b13eceSDouglas Gregor /// identifier (',' identifier)? 256735b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() { 256835b13eceSDouglas Gregor assert(Tok.is(MMToken::ConfigMacros)); 256935b13eceSDouglas Gregor SourceLocation ConfigMacrosLoc = consumeToken(); 257035b13eceSDouglas Gregor 257135b13eceSDouglas Gregor // Only top-level modules can have configuration macros. 257235b13eceSDouglas Gregor if (ActiveModule->Parent) { 257335b13eceSDouglas Gregor Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule); 257435b13eceSDouglas Gregor } 257535b13eceSDouglas Gregor 257635b13eceSDouglas Gregor // Parse the optional attributes. 257735b13eceSDouglas Gregor Attributes Attrs; 25785d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 25795d29dee0SDavide Italiano return; 25805d29dee0SDavide Italiano 258135b13eceSDouglas Gregor if (Attrs.IsExhaustive && !ActiveModule->Parent) { 258235b13eceSDouglas Gregor ActiveModule->ConfigMacrosExhaustive = true; 258335b13eceSDouglas Gregor } 258435b13eceSDouglas Gregor 258535b13eceSDouglas Gregor // If we don't have an identifier, we're done. 2586306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 258735b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) 258835b13eceSDouglas Gregor return; 258935b13eceSDouglas Gregor 259035b13eceSDouglas Gregor // Consume the first identifier. 259135b13eceSDouglas Gregor if (!ActiveModule->Parent) { 259235b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 259335b13eceSDouglas Gregor } 259435b13eceSDouglas Gregor consumeToken(); 259535b13eceSDouglas Gregor 259635b13eceSDouglas Gregor do { 259735b13eceSDouglas Gregor // If there's a comma, consume it. 259835b13eceSDouglas Gregor if (!Tok.is(MMToken::Comma)) 259935b13eceSDouglas Gregor break; 260035b13eceSDouglas Gregor consumeToken(); 260135b13eceSDouglas Gregor 260235b13eceSDouglas Gregor // We expect to see a macro name here. 2603306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 260435b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 260535b13eceSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro); 260635b13eceSDouglas Gregor break; 260735b13eceSDouglas Gregor } 260835b13eceSDouglas Gregor 260935b13eceSDouglas Gregor // Consume the macro name. 261035b13eceSDouglas Gregor if (!ActiveModule->Parent) { 261135b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 261235b13eceSDouglas Gregor } 261335b13eceSDouglas Gregor consumeToken(); 261435b13eceSDouglas Gregor } while (true); 261535b13eceSDouglas Gregor } 261635b13eceSDouglas Gregor 26179fc8faf9SAdrian Prantl /// Format a module-id into a string. 2618fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) { 2619fb912657SDouglas Gregor std::string result; 2620fb912657SDouglas Gregor { 2621fb912657SDouglas Gregor llvm::raw_string_ostream OS(result); 2622fb912657SDouglas Gregor 2623fb912657SDouglas Gregor for (unsigned I = 0, N = Id.size(); I != N; ++I) { 2624fb912657SDouglas Gregor if (I) 2625fb912657SDouglas Gregor OS << "."; 2626fb912657SDouglas Gregor OS << Id[I].first; 2627fb912657SDouglas Gregor } 2628fb912657SDouglas Gregor } 2629fb912657SDouglas Gregor 2630fb912657SDouglas Gregor return result; 2631fb912657SDouglas Gregor } 2632fb912657SDouglas Gregor 26339fc8faf9SAdrian Prantl /// Parse a conflict declaration. 2634fb912657SDouglas Gregor /// 2635fb912657SDouglas Gregor /// module-declaration: 2636fb912657SDouglas Gregor /// 'conflict' module-id ',' string-literal 2637fb912657SDouglas Gregor void ModuleMapParser::parseConflict() { 2638fb912657SDouglas Gregor assert(Tok.is(MMToken::Conflict)); 2639fb912657SDouglas Gregor SourceLocation ConflictLoc = consumeToken(); 2640fb912657SDouglas Gregor Module::UnresolvedConflict Conflict; 2641fb912657SDouglas Gregor 2642fb912657SDouglas Gregor // Parse the module-id. 2643fb912657SDouglas Gregor if (parseModuleId(Conflict.Id)) 2644fb912657SDouglas Gregor return; 2645fb912657SDouglas Gregor 2646fb912657SDouglas Gregor // Parse the ','. 2647fb912657SDouglas Gregor if (!Tok.is(MMToken::Comma)) { 2648fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma) 2649fb912657SDouglas Gregor << SourceRange(ConflictLoc); 2650fb912657SDouglas Gregor return; 2651fb912657SDouglas Gregor } 2652fb912657SDouglas Gregor consumeToken(); 2653fb912657SDouglas Gregor 2654fb912657SDouglas Gregor // Parse the message. 2655fb912657SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2656fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message) 2657fb912657SDouglas Gregor << formatModuleId(Conflict.Id); 2658fb912657SDouglas Gregor return; 2659fb912657SDouglas Gregor } 2660fb912657SDouglas Gregor Conflict.Message = Tok.getString().str(); 2661fb912657SDouglas Gregor consumeToken(); 2662fb912657SDouglas Gregor 2663fb912657SDouglas Gregor // Add this unresolved conflict. 2664fb912657SDouglas Gregor ActiveModule->UnresolvedConflicts.push_back(Conflict); 2665fb912657SDouglas Gregor } 2666fb912657SDouglas Gregor 26679fc8faf9SAdrian Prantl /// Parse an inferred module declaration (wildcard modules). 26689194a91dSDouglas Gregor /// 26699194a91dSDouglas Gregor /// module-declaration: 26709194a91dSDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt] 26719194a91dSDouglas Gregor /// { inferred-module-member* } 26729194a91dSDouglas Gregor /// 26739194a91dSDouglas Gregor /// inferred-module-member: 26749194a91dSDouglas Gregor /// 'export' '*' 26759194a91dSDouglas Gregor /// 'exclude' identifier 26769194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { 267773441091SDouglas Gregor assert(Tok.is(MMToken::Star)); 267873441091SDouglas Gregor SourceLocation StarLoc = consumeToken(); 267973441091SDouglas Gregor bool Failed = false; 268073441091SDouglas Gregor 268173441091SDouglas Gregor // Inferred modules must be submodules. 26829194a91dSDouglas Gregor if (!ActiveModule && !Framework) { 268373441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule); 268473441091SDouglas Gregor Failed = true; 268573441091SDouglas Gregor } 268673441091SDouglas Gregor 26879194a91dSDouglas Gregor if (ActiveModule) { 2688524e33e1SDouglas Gregor // Inferred modules must have umbrella directories. 26894898cde4SBen Langmuir if (!Failed && ActiveModule->IsAvailable && 26904898cde4SBen Langmuir !ActiveModule->getUmbrellaDir()) { 269173441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); 269273441091SDouglas Gregor Failed = true; 269373441091SDouglas Gregor } 269473441091SDouglas Gregor 269573441091SDouglas Gregor // Check for redefinition of an inferred module. 2696dd005f69SDouglas Gregor if (!Failed && ActiveModule->InferSubmodules) { 269773441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_redef); 2698dd005f69SDouglas Gregor if (ActiveModule->InferredSubmoduleLoc.isValid()) 2699dd005f69SDouglas Gregor Diags.Report(ActiveModule->InferredSubmoduleLoc, 270073441091SDouglas Gregor diag::note_mmap_prev_definition); 270173441091SDouglas Gregor Failed = true; 270273441091SDouglas Gregor } 270373441091SDouglas Gregor 27049194a91dSDouglas Gregor // Check for the 'framework' keyword, which is not permitted here. 27059194a91dSDouglas Gregor if (Framework) { 27069194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule); 27079194a91dSDouglas Gregor Framework = false; 27089194a91dSDouglas Gregor } 27099194a91dSDouglas Gregor } else if (Explicit) { 27109194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework); 27119194a91dSDouglas Gregor Explicit = false; 27129194a91dSDouglas Gregor } 27139194a91dSDouglas Gregor 271473441091SDouglas Gregor // If there were any problems with this inferred submodule, skip its body. 271573441091SDouglas Gregor if (Failed) { 271673441091SDouglas Gregor if (Tok.is(MMToken::LBrace)) { 271773441091SDouglas Gregor consumeToken(); 271873441091SDouglas Gregor skipUntil(MMToken::RBrace); 271973441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 272073441091SDouglas Gregor consumeToken(); 272173441091SDouglas Gregor } 272273441091SDouglas Gregor HadError = true; 272373441091SDouglas Gregor return; 272473441091SDouglas Gregor } 272573441091SDouglas Gregor 27269194a91dSDouglas Gregor // Parse optional attributes. 27274442605fSBill Wendling Attributes Attrs; 27285d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 27295d29dee0SDavide Italiano return; 27309194a91dSDouglas Gregor 27319194a91dSDouglas Gregor if (ActiveModule) { 273273441091SDouglas Gregor // Note that we have an inferred submodule. 2733dd005f69SDouglas Gregor ActiveModule->InferSubmodules = true; 2734dd005f69SDouglas Gregor ActiveModule->InferredSubmoduleLoc = StarLoc; 2735dd005f69SDouglas Gregor ActiveModule->InferExplicitSubmodules = Explicit; 27369194a91dSDouglas Gregor } else { 27379194a91dSDouglas Gregor // We'll be inferring framework modules for this directory. 27389194a91dSDouglas Gregor Map.InferredDirectories[Directory].InferModules = true; 2739c1d88ea5SBen Langmuir Map.InferredDirectories[Directory].Attrs = Attrs; 2740beee15e7SBen Langmuir Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile; 2741131daca0SRichard Smith // FIXME: Handle the 'framework' keyword. 27429194a91dSDouglas Gregor } 274373441091SDouglas Gregor 274473441091SDouglas Gregor // Parse the opening brace. 274573441091SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 274673441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard); 274773441091SDouglas Gregor HadError = true; 274873441091SDouglas Gregor return; 274973441091SDouglas Gregor } 275073441091SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 275173441091SDouglas Gregor 275273441091SDouglas Gregor // Parse the body of the inferred submodule. 275373441091SDouglas Gregor bool Done = false; 275473441091SDouglas Gregor do { 275573441091SDouglas Gregor switch (Tok.Kind) { 275673441091SDouglas Gregor case MMToken::EndOfFile: 275773441091SDouglas Gregor case MMToken::RBrace: 275873441091SDouglas Gregor Done = true; 275973441091SDouglas Gregor break; 276073441091SDouglas Gregor 2761afd1b1c9SEugene Zelenko case MMToken::ExcludeKeyword: 27629194a91dSDouglas Gregor if (ActiveModule) { 27639194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2764d2d442caSCraig Topper << (ActiveModule != nullptr); 27659194a91dSDouglas Gregor consumeToken(); 27669194a91dSDouglas Gregor break; 27679194a91dSDouglas Gregor } 27689194a91dSDouglas Gregor 27699194a91dSDouglas Gregor consumeToken(); 2770306d8920SRichard Smith // FIXME: Support string-literal module names here. 27719194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 27729194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name); 27739194a91dSDouglas Gregor break; 27749194a91dSDouglas Gregor } 27759194a91dSDouglas Gregor 27769194a91dSDouglas Gregor Map.InferredDirectories[Directory].ExcludedModules 27779194a91dSDouglas Gregor .push_back(Tok.getString()); 27789194a91dSDouglas Gregor consumeToken(); 27799194a91dSDouglas Gregor break; 27809194a91dSDouglas Gregor 27819194a91dSDouglas Gregor case MMToken::ExportKeyword: 27829194a91dSDouglas Gregor if (!ActiveModule) { 27839194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2784d2d442caSCraig Topper << (ActiveModule != nullptr); 27859194a91dSDouglas Gregor consumeToken(); 27869194a91dSDouglas Gregor break; 27879194a91dSDouglas Gregor } 27889194a91dSDouglas Gregor 278973441091SDouglas Gregor consumeToken(); 279073441091SDouglas Gregor if (Tok.is(MMToken::Star)) 2791dd005f69SDouglas Gregor ActiveModule->InferExportWildcard = true; 279273441091SDouglas Gregor else 279373441091SDouglas Gregor Diags.Report(Tok.getLocation(), 279473441091SDouglas Gregor diag::err_mmap_expected_export_wildcard); 279573441091SDouglas Gregor consumeToken(); 279673441091SDouglas Gregor break; 279773441091SDouglas Gregor 279873441091SDouglas Gregor case MMToken::ExplicitKeyword: 279973441091SDouglas Gregor case MMToken::ModuleKeyword: 280073441091SDouglas Gregor case MMToken::HeaderKeyword: 2801b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 280273441091SDouglas Gregor case MMToken::UmbrellaKeyword: 280373441091SDouglas Gregor default: 28049194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2805d2d442caSCraig Topper << (ActiveModule != nullptr); 280673441091SDouglas Gregor consumeToken(); 280773441091SDouglas Gregor break; 280873441091SDouglas Gregor } 280973441091SDouglas Gregor } while (!Done); 281073441091SDouglas Gregor 281173441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 281273441091SDouglas Gregor consumeToken(); 281373441091SDouglas Gregor else { 281473441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 281573441091SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 281673441091SDouglas Gregor HadError = true; 281773441091SDouglas Gregor } 281873441091SDouglas Gregor } 281973441091SDouglas Gregor 28209fc8faf9SAdrian Prantl /// Parse optional attributes. 28219194a91dSDouglas Gregor /// 28229194a91dSDouglas Gregor /// attributes: 28239194a91dSDouglas Gregor /// attribute attributes 28249194a91dSDouglas Gregor /// attribute 28259194a91dSDouglas Gregor /// 28269194a91dSDouglas Gregor /// attribute: 28279194a91dSDouglas Gregor /// [ identifier ] 28289194a91dSDouglas Gregor /// 28299194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes. 28309194a91dSDouglas Gregor /// 28319194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise. 28324442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { 28339194a91dSDouglas Gregor bool HadError = false; 28349194a91dSDouglas Gregor 28359194a91dSDouglas Gregor while (Tok.is(MMToken::LSquare)) { 28369194a91dSDouglas Gregor // Consume the '['. 28379194a91dSDouglas Gregor SourceLocation LSquareLoc = consumeToken(); 28389194a91dSDouglas Gregor 28399194a91dSDouglas Gregor // Check whether we have an attribute name here. 28409194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 28419194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute); 28429194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 28439194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 28449194a91dSDouglas Gregor consumeToken(); 28459194a91dSDouglas Gregor HadError = true; 28469194a91dSDouglas Gregor } 28479194a91dSDouglas Gregor 28489194a91dSDouglas Gregor // Decode the attribute name. 28499194a91dSDouglas Gregor AttributeKind Attribute 28509194a91dSDouglas Gregor = llvm::StringSwitch<AttributeKind>(Tok.getString()) 285135b13eceSDouglas Gregor .Case("exhaustive", AT_exhaustive) 285277944868SRichard Smith .Case("extern_c", AT_extern_c) 2853ed84df00SBruno Cardoso Lopes .Case("no_undeclared_includes", AT_no_undeclared_includes) 28549194a91dSDouglas Gregor .Case("system", AT_system) 28559194a91dSDouglas Gregor .Default(AT_unknown); 28569194a91dSDouglas Gregor switch (Attribute) { 28579194a91dSDouglas Gregor case AT_unknown: 28589194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute) 28599194a91dSDouglas Gregor << Tok.getString(); 28609194a91dSDouglas Gregor break; 28619194a91dSDouglas Gregor 28629194a91dSDouglas Gregor case AT_system: 28639194a91dSDouglas Gregor Attrs.IsSystem = true; 28649194a91dSDouglas Gregor break; 286535b13eceSDouglas Gregor 286677944868SRichard Smith case AT_extern_c: 286777944868SRichard Smith Attrs.IsExternC = true; 286877944868SRichard Smith break; 286977944868SRichard Smith 287035b13eceSDouglas Gregor case AT_exhaustive: 287135b13eceSDouglas Gregor Attrs.IsExhaustive = true; 287235b13eceSDouglas Gregor break; 2873ed84df00SBruno Cardoso Lopes 2874ed84df00SBruno Cardoso Lopes case AT_no_undeclared_includes: 2875ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes = true; 2876ed84df00SBruno Cardoso Lopes break; 28779194a91dSDouglas Gregor } 28789194a91dSDouglas Gregor consumeToken(); 28799194a91dSDouglas Gregor 28809194a91dSDouglas Gregor // Consume the ']'. 28819194a91dSDouglas Gregor if (!Tok.is(MMToken::RSquare)) { 28829194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare); 28839194a91dSDouglas Gregor Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match); 28849194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 28859194a91dSDouglas Gregor HadError = true; 28869194a91dSDouglas Gregor } 28879194a91dSDouglas Gregor 28889194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 28899194a91dSDouglas Gregor consumeToken(); 28909194a91dSDouglas Gregor } 28919194a91dSDouglas Gregor 28929194a91dSDouglas Gregor return HadError; 28939194a91dSDouglas Gregor } 28949194a91dSDouglas Gregor 28959fc8faf9SAdrian Prantl /// Parse a module map file. 2896718292f2SDouglas Gregor /// 2897718292f2SDouglas Gregor /// module-map-file: 2898718292f2SDouglas Gregor /// module-declaration* 2899718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 2900718292f2SDouglas Gregor do { 2901718292f2SDouglas Gregor switch (Tok.Kind) { 2902718292f2SDouglas Gregor case MMToken::EndOfFile: 2903718292f2SDouglas Gregor return HadError; 2904718292f2SDouglas Gregor 2905e7ab3669SDouglas Gregor case MMToken::ExplicitKeyword: 290697292843SDaniel Jasper case MMToken::ExternKeyword: 2907718292f2SDouglas Gregor case MMToken::ModuleKeyword: 2908755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 2909718292f2SDouglas Gregor parseModuleDecl(); 2910718292f2SDouglas Gregor break; 2911718292f2SDouglas Gregor 29121fb5c3a6SDouglas Gregor case MMToken::Comma: 291335b13eceSDouglas Gregor case MMToken::ConfigMacros: 2914fb912657SDouglas Gregor case MMToken::Conflict: 2915a3feee2aSRichard Smith case MMToken::Exclaim: 291659527666SDouglas Gregor case MMToken::ExcludeKeyword: 29172b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 2918f0b11de2SDouglas Gregor case MMToken::ExportAsKeyword: 2919718292f2SDouglas Gregor case MMToken::HeaderKeyword: 2920718292f2SDouglas Gregor case MMToken::Identifier: 2921718292f2SDouglas Gregor case MMToken::LBrace: 29226ddfca91SDouglas Gregor case MMToken::LinkKeyword: 2923a686e1b0SDouglas Gregor case MMToken::LSquare: 29242b82c2a5SDouglas Gregor case MMToken::Period: 2925b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 2926718292f2SDouglas Gregor case MMToken::RBrace: 2927a686e1b0SDouglas Gregor case MMToken::RSquare: 29281fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 29292b82c2a5SDouglas Gregor case MMToken::Star: 2930718292f2SDouglas Gregor case MMToken::StringLiteral: 2931040e1266SRichard Smith case MMToken::IntegerLiteral: 2932b8afebe2SRichard Smith case MMToken::TextualKeyword: 2933718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 2934ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 2935718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 2936718292f2SDouglas Gregor HadError = true; 2937718292f2SDouglas Gregor consumeToken(); 2938718292f2SDouglas Gregor break; 2939718292f2SDouglas Gregor } 2940718292f2SDouglas Gregor } while (true); 2941718292f2SDouglas Gregor } 2942718292f2SDouglas Gregor 29439acb99e3SRichard Smith bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem, 2944c192d194SBruno Cardoso Lopes const DirectoryEntry *Dir, FileID ID, 29458128f332SRichard Smith unsigned *Offset, 2946ae6df27eSRichard Smith SourceLocation ExternModuleLoc) { 29478128f332SRichard Smith assert(Target && "Missing target information"); 29484ddf2221SDouglas Gregor llvm::DenseMap<const FileEntry *, bool>::iterator Known 29494ddf2221SDouglas Gregor = ParsedModuleMap.find(File); 29504ddf2221SDouglas Gregor if (Known != ParsedModuleMap.end()) 29514ddf2221SDouglas Gregor return Known->second; 29524ddf2221SDouglas Gregor 29538128f332SRichard Smith // If the module map file wasn't already entered, do so now. 29548128f332SRichard Smith if (ID.isInvalid()) { 2955f3f84616SRichard Smith auto FileCharacter = 2956f3f84616SRichard Smith IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap; 29578128f332SRichard Smith ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter); 29588128f332SRichard Smith } 29598128f332SRichard Smith 29608128f332SRichard Smith assert(Target && "Missing target information"); 29611f76c4e8SManuel Klimek const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID); 2962718292f2SDouglas Gregor if (!Buffer) 29634ddf2221SDouglas Gregor return ParsedModuleMap[File] = true; 29648128f332SRichard Smith assert((!Offset || *Offset <= Buffer->getBufferSize()) && 29658128f332SRichard Smith "invalid buffer offset"); 2966718292f2SDouglas Gregor 2967718292f2SDouglas Gregor // Parse this module map file. 29688128f332SRichard Smith Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts, 29698128f332SRichard Smith Buffer->getBufferStart(), 29708128f332SRichard Smith Buffer->getBufferStart() + (Offset ? *Offset : 0), 29718128f332SRichard Smith Buffer->getBufferEnd()); 29722a6edb30SRichard Smith SourceLocation Start = L.getSourceLocation(); 2973beee15e7SBen Langmuir ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir, 2974c192d194SBruno Cardoso Lopes IsSystem); 2975718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 29764ddf2221SDouglas Gregor ParsedModuleMap[File] = Result; 29772a6edb30SRichard Smith 29788128f332SRichard Smith if (Offset) { 29798128f332SRichard Smith auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation()); 29808128f332SRichard Smith assert(Loc.first == ID && "stopped in a different file?"); 29818128f332SRichard Smith *Offset = Loc.second; 29828128f332SRichard Smith } 29838128f332SRichard Smith 29842a6edb30SRichard Smith // Notify callbacks that we parsed it. 29852a6edb30SRichard Smith for (const auto &Cb : Callbacks) 29862a6edb30SRichard Smith Cb->moduleMapFileRead(Start, *File, IsSystem); 29878587dfd9SBruno Cardoso Lopes 2988718292f2SDouglas Gregor return Result; 2989718292f2SDouglas Gregor } 2990