1afd1b1c9SEugene Zelenko //===- ModuleMap.cpp - Describe the layout of modules ---------------------===// 2718292f2SDouglas Gregor // 3718292f2SDouglas Gregor // The LLVM Compiler Infrastructure 4718292f2SDouglas Gregor // 5718292f2SDouglas Gregor // This file is distributed under the University of Illinois Open Source 6718292f2SDouglas Gregor // License. See LICENSE.TXT for details. 7718292f2SDouglas Gregor // 8718292f2SDouglas Gregor //===----------------------------------------------------------------------===// 9718292f2SDouglas Gregor // 10718292f2SDouglas Gregor // This file defines the ModuleMap implementation, which describes the layout 11718292f2SDouglas Gregor // of a module as it relates to headers. 12718292f2SDouglas Gregor // 13718292f2SDouglas Gregor //===----------------------------------------------------------------------===// 14afd1b1c9SEugene Zelenko 15718292f2SDouglas Gregor #include "clang/Lex/ModuleMap.h" 16a7d03840SJordan Rose #include "clang/Basic/CharInfo.h" 17718292f2SDouglas Gregor #include "clang/Basic/Diagnostic.h" 18718292f2SDouglas Gregor #include "clang/Basic/FileManager.h" 19afd1b1c9SEugene Zelenko #include "clang/Basic/LLVM.h" 20afd1b1c9SEugene Zelenko #include "clang/Basic/LangOptions.h" 21afd1b1c9SEugene Zelenko #include "clang/Basic/Module.h" 22afd1b1c9SEugene Zelenko #include "clang/Basic/SourceLocation.h" 23afd1b1c9SEugene Zelenko #include "clang/Basic/SourceManager.h" 24718292f2SDouglas Gregor #include "clang/Basic/TargetInfo.h" 25afd1b1c9SEugene Zelenko #include "clang/Basic/VirtualFileSystem.h" 26b146baabSArgyrios Kyrtzidis #include "clang/Lex/HeaderSearch.h" 279acb99e3SRichard Smith #include "clang/Lex/HeaderSearchOptions.h" 283a02247dSChandler Carruth #include "clang/Lex/LexDiagnostic.h" 293a02247dSChandler Carruth #include "clang/Lex/Lexer.h" 303a02247dSChandler Carruth #include "clang/Lex/LiteralSupport.h" 31afd1b1c9SEugene Zelenko #include "clang/Lex/Token.h" 32afd1b1c9SEugene Zelenko #include "llvm/ADT/DenseMap.h" 33afd1b1c9SEugene Zelenko #include "llvm/ADT/None.h" 34afd1b1c9SEugene Zelenko #include "llvm/ADT/STLExtras.h" 35afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallPtrSet.h" 36afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallString.h" 37afd1b1c9SEugene Zelenko #include "llvm/ADT/SmallVector.h" 38afd1b1c9SEugene Zelenko #include "llvm/ADT/StringMap.h" 393a02247dSChandler Carruth #include "llvm/ADT/StringRef.h" 403a02247dSChandler Carruth #include "llvm/ADT/StringSwitch.h" 41718292f2SDouglas Gregor #include "llvm/Support/Allocator.h" 42afd1b1c9SEugene Zelenko #include "llvm/Support/Compiler.h" 43afd1b1c9SEugene Zelenko #include "llvm/Support/ErrorHandling.h" 44afd1b1c9SEugene Zelenko #include "llvm/Support/MemoryBuffer.h" 45552c169eSRafael Espindola #include "llvm/Support/Path.h" 46718292f2SDouglas Gregor #include "llvm/Support/raw_ostream.h" 47afd1b1c9SEugene Zelenko #include <algorithm> 48afd1b1c9SEugene Zelenko #include <cassert> 49afd1b1c9SEugene Zelenko #include <cstdint> 50afd1b1c9SEugene Zelenko #include <cstring> 51afd1b1c9SEugene Zelenko #include <string> 52afd1b1c9SEugene Zelenko #include <system_error> 53afd1b1c9SEugene Zelenko #include <utility> 54afd1b1c9SEugene Zelenko 55718292f2SDouglas Gregor using namespace clang; 56718292f2SDouglas Gregor 57a3b5f71eSBruno Cardoso Lopes void ModuleMap::resolveLinkAsDependencies(Module *Mod) { 58a3b5f71eSBruno Cardoso Lopes auto PendingLinkAs = PendingLinkAsModule.find(Mod->Name); 59a3b5f71eSBruno Cardoso Lopes if (PendingLinkAs != PendingLinkAsModule.end()) { 60a3b5f71eSBruno Cardoso Lopes for (auto &Name : PendingLinkAs->second) { 61a3b5f71eSBruno Cardoso Lopes auto *M = findModule(Name.getKey()); 62a3b5f71eSBruno Cardoso Lopes if (M) 63a3b5f71eSBruno Cardoso Lopes M->UseExportAsModuleLinkName = true; 64a3b5f71eSBruno Cardoso Lopes } 65a3b5f71eSBruno Cardoso Lopes } 66a3b5f71eSBruno Cardoso Lopes } 67a3b5f71eSBruno Cardoso Lopes 68a3b5f71eSBruno Cardoso Lopes void ModuleMap::addLinkAsDependency(Module *Mod) { 69a3b5f71eSBruno Cardoso Lopes if (findModule(Mod->ExportAsModule)) 70a3b5f71eSBruno Cardoso Lopes Mod->UseExportAsModuleLinkName = true; 71a3b5f71eSBruno Cardoso Lopes else 72a3b5f71eSBruno Cardoso Lopes PendingLinkAsModule[Mod->ExportAsModule].insert(Mod->Name); 73a3b5f71eSBruno Cardoso Lopes } 74a3b5f71eSBruno Cardoso Lopes 75040e1266SRichard Smith Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) { 76040e1266SRichard Smith switch ((int)Role) { 77040e1266SRichard Smith default: llvm_unreachable("unknown header role"); 78040e1266SRichard Smith case NormalHeader: 79040e1266SRichard Smith return Module::HK_Normal; 80040e1266SRichard Smith case PrivateHeader: 81040e1266SRichard Smith return Module::HK_Private; 82040e1266SRichard Smith case TextualHeader: 83040e1266SRichard Smith return Module::HK_Textual; 84040e1266SRichard Smith case PrivateHeader | TextualHeader: 85040e1266SRichard Smith return Module::HK_PrivateTextual; 86040e1266SRichard Smith } 87040e1266SRichard Smith } 88040e1266SRichard Smith 89040e1266SRichard Smith ModuleMap::ModuleHeaderRole 90040e1266SRichard Smith ModuleMap::headerKindToRole(Module::HeaderKind Kind) { 91040e1266SRichard Smith switch ((int)Kind) { 92040e1266SRichard Smith case Module::HK_Normal: 93040e1266SRichard Smith return NormalHeader; 94040e1266SRichard Smith case Module::HK_Private: 95040e1266SRichard Smith return PrivateHeader; 96040e1266SRichard Smith case Module::HK_Textual: 97040e1266SRichard Smith return TextualHeader; 98040e1266SRichard Smith case Module::HK_PrivateTextual: 99040e1266SRichard Smith return ModuleHeaderRole(PrivateHeader | TextualHeader); 100040e1266SRichard Smith case Module::HK_Excluded: 101040e1266SRichard Smith llvm_unreachable("unexpected header kind"); 102040e1266SRichard Smith } 103040e1266SRichard Smith llvm_unreachable("unknown header kind"); 104040e1266SRichard Smith } 105040e1266SRichard Smith 1062b82c2a5SDouglas Gregor Module::ExportDecl 1072b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod, 1082b82c2a5SDouglas Gregor const Module::UnresolvedExportDecl &Unresolved, 109e4412640SArgyrios Kyrtzidis bool Complain) const { 110f5eedd05SDouglas Gregor // We may have just a wildcard. 111f5eedd05SDouglas Gregor if (Unresolved.Id.empty()) { 112f5eedd05SDouglas Gregor assert(Unresolved.Wildcard && "Invalid unresolved export"); 113d2d442caSCraig Topper return Module::ExportDecl(nullptr, true); 114f5eedd05SDouglas Gregor } 115f5eedd05SDouglas Gregor 116fb912657SDouglas Gregor // Resolve the module-id. 117fb912657SDouglas Gregor Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain); 118fb912657SDouglas Gregor if (!Context) 119afd1b1c9SEugene Zelenko return {}; 120fb912657SDouglas Gregor 121fb912657SDouglas Gregor return Module::ExportDecl(Context, Unresolved.Wildcard); 122fb912657SDouglas Gregor } 123fb912657SDouglas Gregor 124fb912657SDouglas Gregor Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod, 125fb912657SDouglas Gregor bool Complain) const { 1262b82c2a5SDouglas Gregor // Find the starting module. 127fb912657SDouglas Gregor Module *Context = lookupModuleUnqualified(Id[0].first, Mod); 1282b82c2a5SDouglas Gregor if (!Context) { 1292b82c2a5SDouglas Gregor if (Complain) 1300761a8a0SDaniel Jasper Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified) 131fb912657SDouglas Gregor << Id[0].first << Mod->getFullModuleName(); 1322b82c2a5SDouglas Gregor 133d2d442caSCraig Topper return nullptr; 1342b82c2a5SDouglas Gregor } 1352b82c2a5SDouglas Gregor 1362b82c2a5SDouglas Gregor // Dig into the module path. 137fb912657SDouglas Gregor for (unsigned I = 1, N = Id.size(); I != N; ++I) { 138fb912657SDouglas Gregor Module *Sub = lookupModuleQualified(Id[I].first, Context); 1392b82c2a5SDouglas Gregor if (!Sub) { 1402b82c2a5SDouglas Gregor if (Complain) 1410761a8a0SDaniel Jasper Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified) 142fb912657SDouglas Gregor << Id[I].first << Context->getFullModuleName() 143fb912657SDouglas Gregor << SourceRange(Id[0].second, Id[I-1].second); 1442b82c2a5SDouglas Gregor 145d2d442caSCraig Topper return nullptr; 1462b82c2a5SDouglas Gregor } 1472b82c2a5SDouglas Gregor 1482b82c2a5SDouglas Gregor Context = Sub; 1492b82c2a5SDouglas Gregor } 1502b82c2a5SDouglas Gregor 151fb912657SDouglas Gregor return Context; 1522b82c2a5SDouglas Gregor } 1532b82c2a5SDouglas Gregor 1549fc8faf9SAdrian Prantl /// Append to \p Paths the set of paths needed to get to the 1551d60987fSRichard Smith /// subframework in which the given module lives. 1561d60987fSRichard Smith static void appendSubframeworkPaths(Module *Mod, 1571d60987fSRichard Smith SmallVectorImpl<char> &Path) { 1581d60987fSRichard Smith // Collect the framework names from the given module to the top-level module. 1591d60987fSRichard Smith SmallVector<StringRef, 2> Paths; 1601d60987fSRichard Smith for (; Mod; Mod = Mod->Parent) { 1611d60987fSRichard Smith if (Mod->IsFramework) 1621d60987fSRichard Smith Paths.push_back(Mod->Name); 1631d60987fSRichard Smith } 1641d60987fSRichard Smith 1651d60987fSRichard Smith if (Paths.empty()) 1661d60987fSRichard Smith return; 1671d60987fSRichard Smith 1681d60987fSRichard Smith // Add Frameworks/Name.framework for each subframework. 1691d60987fSRichard Smith for (unsigned I = Paths.size() - 1; I != 0; --I) 1701d60987fSRichard Smith llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework"); 1711d60987fSRichard Smith } 1721d60987fSRichard Smith 1739f6020bcSBruno Cardoso Lopes const FileEntry *ModuleMap::findHeader( 1749f6020bcSBruno Cardoso Lopes Module *M, const Module::UnresolvedHeaderDirective &Header, 1759f6020bcSBruno Cardoso Lopes SmallVectorImpl<char> &RelativePathName, bool &NeedsFramework) { 1769f6020bcSBruno Cardoso Lopes // Search for the header file within the module's home directory. 1779f6020bcSBruno Cardoso Lopes auto *Directory = M->Directory; 1789f6020bcSBruno Cardoso Lopes SmallString<128> FullPathName(Directory->getName()); 1799f6020bcSBruno Cardoso Lopes 180040e1266SRichard Smith auto GetFile = [&](StringRef Filename) -> const FileEntry * { 181040e1266SRichard Smith auto *File = SourceMgr.getFileManager().getFile(Filename); 182040e1266SRichard Smith if (!File || 183040e1266SRichard Smith (Header.Size && File->getSize() != *Header.Size) || 184040e1266SRichard Smith (Header.ModTime && File->getModificationTime() != *Header.ModTime)) 185040e1266SRichard Smith return nullptr; 186040e1266SRichard Smith return File; 187040e1266SRichard Smith }; 188040e1266SRichard Smith 1899f6020bcSBruno Cardoso Lopes auto GetFrameworkFile = [&]() -> const FileEntry * { 1901d60987fSRichard Smith unsigned FullPathLength = FullPathName.size(); 1911d60987fSRichard Smith appendSubframeworkPaths(M, RelativePathName); 1921d60987fSRichard Smith unsigned RelativePathLength = RelativePathName.size(); 1931d60987fSRichard Smith 1941d60987fSRichard Smith // Check whether this file is in the public headers. 1951d60987fSRichard Smith llvm::sys::path::append(RelativePathName, "Headers", Header.FileName); 1961d60987fSRichard Smith llvm::sys::path::append(FullPathName, RelativePathName); 197040e1266SRichard Smith if (auto *File = GetFile(FullPathName)) 1981d60987fSRichard Smith return File; 1991d60987fSRichard Smith 2001d60987fSRichard Smith // Check whether this file is in the private headers. 2011d60987fSRichard Smith // Ideally, private modules in the form 'FrameworkName.Private' should 2021d60987fSRichard Smith // be defined as 'module FrameworkName.Private', and not as 2031d60987fSRichard Smith // 'framework module FrameworkName.Private', since a 'Private.Framework' 2041d60987fSRichard Smith // does not usually exist. However, since both are currently widely used 2051d60987fSRichard Smith // for private modules, make sure we find the right path in both cases. 2061d60987fSRichard Smith if (M->IsFramework && M->Name == "Private") 2071d60987fSRichard Smith RelativePathName.clear(); 2081d60987fSRichard Smith else 2091d60987fSRichard Smith RelativePathName.resize(RelativePathLength); 2101d60987fSRichard Smith FullPathName.resize(FullPathLength); 2111d60987fSRichard Smith llvm::sys::path::append(RelativePathName, "PrivateHeaders", 2121d60987fSRichard Smith Header.FileName); 2131d60987fSRichard Smith llvm::sys::path::append(FullPathName, RelativePathName); 214040e1266SRichard Smith return GetFile(FullPathName); 2159f6020bcSBruno Cardoso Lopes }; 2169f6020bcSBruno Cardoso Lopes 2179f6020bcSBruno Cardoso Lopes if (llvm::sys::path::is_absolute(Header.FileName)) { 2189f6020bcSBruno Cardoso Lopes RelativePathName.clear(); 2199f6020bcSBruno Cardoso Lopes RelativePathName.append(Header.FileName.begin(), Header.FileName.end()); 2209f6020bcSBruno Cardoso Lopes return GetFile(Header.FileName); 2211d60987fSRichard Smith } 2221d60987fSRichard Smith 2239f6020bcSBruno Cardoso Lopes if (M->isPartOfFramework()) 2249f6020bcSBruno Cardoso Lopes return GetFrameworkFile(); 2259f6020bcSBruno Cardoso Lopes 2261d60987fSRichard Smith // Lookup for normal headers. 2271d60987fSRichard Smith llvm::sys::path::append(RelativePathName, Header.FileName); 2281d60987fSRichard Smith llvm::sys::path::append(FullPathName, RelativePathName); 2299f6020bcSBruno Cardoso Lopes auto *NormalHdrFile = GetFile(FullPathName); 2309f6020bcSBruno Cardoso Lopes 2319f6020bcSBruno Cardoso Lopes if (M && !NormalHdrFile && Directory->getName().endswith(".framework")) { 2329f6020bcSBruno Cardoso Lopes // The lack of 'framework' keyword in a module declaration it's a simple 2339f6020bcSBruno Cardoso Lopes // mistake we can diagnose when the header exists within the proper 2349f6020bcSBruno Cardoso Lopes // framework style path. 2359f6020bcSBruno Cardoso Lopes FullPathName.assign(Directory->getName()); 2369f6020bcSBruno Cardoso Lopes RelativePathName.clear(); 237d101b5d7SErich Keane if (GetFrameworkFile()) { 2389f6020bcSBruno Cardoso Lopes Diags.Report(Header.FileNameLoc, 2399f6020bcSBruno Cardoso Lopes diag::warn_mmap_incomplete_framework_module_declaration) 2409f6020bcSBruno Cardoso Lopes << Header.FileName << M->getFullModuleName(); 2419f6020bcSBruno Cardoso Lopes NeedsFramework = true; 2429f6020bcSBruno Cardoso Lopes } 2439f6020bcSBruno Cardoso Lopes return nullptr; 2449f6020bcSBruno Cardoso Lopes } 2459f6020bcSBruno Cardoso Lopes 2469f6020bcSBruno Cardoso Lopes return NormalHdrFile; 2471d60987fSRichard Smith } 2481d60987fSRichard Smith 249040e1266SRichard Smith void ModuleMap::resolveHeader(Module *Mod, 2509f6020bcSBruno Cardoso Lopes const Module::UnresolvedHeaderDirective &Header, 2519f6020bcSBruno Cardoso Lopes bool &NeedsFramework) { 252040e1266SRichard Smith SmallString<128> RelativePathName; 2539f6020bcSBruno Cardoso Lopes if (const FileEntry *File = 2549f6020bcSBruno Cardoso Lopes findHeader(Mod, Header, RelativePathName, NeedsFramework)) { 255040e1266SRichard Smith if (Header.IsUmbrella) { 256040e1266SRichard Smith const DirectoryEntry *UmbrellaDir = File->getDir(); 257040e1266SRichard Smith if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir]) 258040e1266SRichard Smith Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) 259040e1266SRichard Smith << UmbrellaMod->getFullModuleName(); 260040e1266SRichard Smith else 261040e1266SRichard Smith // Record this umbrella header. 262040e1266SRichard Smith setUmbrellaHeader(Mod, File, RelativePathName.str()); 263040e1266SRichard Smith } else { 264040e1266SRichard Smith Module::Header H = {RelativePathName.str(), File}; 265040e1266SRichard Smith if (Header.Kind == Module::HK_Excluded) 266040e1266SRichard Smith excludeHeader(Mod, H); 267040e1266SRichard Smith else 268040e1266SRichard Smith addHeader(Mod, H, headerKindToRole(Header.Kind)); 269040e1266SRichard Smith } 270040e1266SRichard Smith } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) { 271040e1266SRichard Smith // There's a builtin header but no corresponding on-disk header. Assume 272040e1266SRichard Smith // this was supposed to modularize the builtin header alone. 273040e1266SRichard Smith } else if (Header.Kind == Module::HK_Excluded) { 274040e1266SRichard Smith // Ignore missing excluded header files. They're optional anyway. 275040e1266SRichard Smith } else { 276040e1266SRichard Smith // If we find a module that has a missing header, we mark this module as 277040e1266SRichard Smith // unavailable and store the header directive for displaying diagnostics. 278040e1266SRichard Smith Mod->MissingHeaders.push_back(Header); 279040e1266SRichard Smith // A missing header with stat information doesn't make the module 280040e1266SRichard Smith // unavailable; this keeps our behavior consistent as headers are lazily 281040e1266SRichard Smith // resolved. (Such a module still can't be built though, except from 282040e1266SRichard Smith // preprocessed source.) 283040e1266SRichard Smith if (!Header.Size && !Header.ModTime) 284040e1266SRichard Smith Mod->markUnavailable(); 285040e1266SRichard Smith } 286040e1266SRichard Smith } 287040e1266SRichard Smith 288040e1266SRichard Smith bool ModuleMap::resolveAsBuiltinHeader( 289040e1266SRichard Smith Module *Mod, const Module::UnresolvedHeaderDirective &Header) { 290040e1266SRichard Smith if (Header.Kind == Module::HK_Excluded || 291040e1266SRichard Smith llvm::sys::path::is_absolute(Header.FileName) || 292040e1266SRichard Smith Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella || 293040e1266SRichard Smith !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory || 294040e1266SRichard Smith !isBuiltinHeader(Header.FileName)) 295040e1266SRichard Smith return false; 2961d60987fSRichard Smith 2971d60987fSRichard Smith // This is a system module with a top-level header. This header 2981d60987fSRichard Smith // may have a counterpart (or replacement) in the set of headers 2991d60987fSRichard Smith // supplied by Clang. Find that builtin header. 300040e1266SRichard Smith SmallString<128> Path; 301040e1266SRichard Smith llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName); 302040e1266SRichard Smith auto *File = SourceMgr.getFileManager().getFile(Path); 303040e1266SRichard Smith if (!File) 304040e1266SRichard Smith return false; 305040e1266SRichard Smith 306040e1266SRichard Smith auto Role = headerKindToRole(Header.Kind); 307040e1266SRichard Smith Module::Header H = {Path.str(), File}; 308040e1266SRichard Smith addHeader(Mod, H, Role); 309040e1266SRichard Smith return true; 3101d60987fSRichard Smith } 3111d60987fSRichard Smith 3120761a8a0SDaniel Jasper ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags, 313b146baabSArgyrios Kyrtzidis const LangOptions &LangOpts, const TargetInfo *Target, 314b146baabSArgyrios Kyrtzidis HeaderSearch &HeaderInfo) 3150761a8a0SDaniel Jasper : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target), 316056bf77fSRichard Smith HeaderInfo(HeaderInfo) { 3170414b857SRichard Smith MMapLangOpts.LineComment = true; 3180414b857SRichard Smith } 319718292f2SDouglas Gregor 320718292f2SDouglas Gregor ModuleMap::~ModuleMap() { 32121668754SDavide Italiano for (auto &M : Modules) 32221668754SDavide Italiano delete M.getValue(); 3238587dfd9SBruno Cardoso Lopes for (auto *M : ShadowModules) 3248587dfd9SBruno Cardoso Lopes delete M; 325718292f2SDouglas Gregor } 326718292f2SDouglas Gregor 32789929282SDouglas Gregor void ModuleMap::setTarget(const TargetInfo &Target) { 32889929282SDouglas Gregor assert((!this->Target || this->Target == &Target) && 32989929282SDouglas Gregor "Improper target override"); 33089929282SDouglas Gregor this->Target = &Target; 33189929282SDouglas Gregor } 33289929282SDouglas Gregor 3339fc8faf9SAdrian Prantl /// "Sanitize" a filename so that it can be used as an identifier. 334056396aeSDouglas Gregor static StringRef sanitizeFilenameAsIdentifier(StringRef Name, 335056396aeSDouglas Gregor SmallVectorImpl<char> &Buffer) { 336056396aeSDouglas Gregor if (Name.empty()) 337056396aeSDouglas Gregor return Name; 338056396aeSDouglas Gregor 339a7d03840SJordan Rose if (!isValidIdentifier(Name)) { 340056396aeSDouglas Gregor // If we don't already have something with the form of an identifier, 341056396aeSDouglas Gregor // create a buffer with the sanitized name. 342056396aeSDouglas Gregor Buffer.clear(); 343a7d03840SJordan Rose if (isDigit(Name[0])) 344056396aeSDouglas Gregor Buffer.push_back('_'); 345056396aeSDouglas Gregor Buffer.reserve(Buffer.size() + Name.size()); 346056396aeSDouglas Gregor for (unsigned I = 0, N = Name.size(); I != N; ++I) { 347a7d03840SJordan Rose if (isIdentifierBody(Name[I])) 348056396aeSDouglas Gregor Buffer.push_back(Name[I]); 349056396aeSDouglas Gregor else 350056396aeSDouglas Gregor Buffer.push_back('_'); 351056396aeSDouglas Gregor } 352056396aeSDouglas Gregor 353056396aeSDouglas Gregor Name = StringRef(Buffer.data(), Buffer.size()); 354056396aeSDouglas Gregor } 355056396aeSDouglas Gregor 356056396aeSDouglas Gregor while (llvm::StringSwitch<bool>(Name) 357056396aeSDouglas Gregor #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true) 358056396aeSDouglas Gregor #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true) 359056396aeSDouglas Gregor #include "clang/Basic/TokenKinds.def" 360056396aeSDouglas Gregor .Default(false)) { 361056396aeSDouglas Gregor if (Name.data() != Buffer.data()) 362056396aeSDouglas Gregor Buffer.append(Name.begin(), Name.end()); 363056396aeSDouglas Gregor Buffer.push_back('_'); 364056396aeSDouglas Gregor Name = StringRef(Buffer.data(), Buffer.size()); 365056396aeSDouglas Gregor } 366056396aeSDouglas Gregor 367056396aeSDouglas Gregor return Name; 368056396aeSDouglas Gregor } 369056396aeSDouglas Gregor 3709fc8faf9SAdrian Prantl /// Determine whether the given file name is the name of a builtin 37134d52749SDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system 37234d52749SDouglas Gregor /// headers. 373ba1b5c98SBruno Cardoso Lopes bool ModuleMap::isBuiltinHeader(StringRef FileName) { 37434d52749SDouglas Gregor return llvm::StringSwitch<bool>(FileName) 37534d52749SDouglas Gregor .Case("float.h", true) 37634d52749SDouglas Gregor .Case("iso646.h", true) 37734d52749SDouglas Gregor .Case("limits.h", true) 37834d52749SDouglas Gregor .Case("stdalign.h", true) 37934d52749SDouglas Gregor .Case("stdarg.h", true) 3803c4b1290SBen Langmuir .Case("stdatomic.h", true) 38134d52749SDouglas Gregor .Case("stdbool.h", true) 38234d52749SDouglas Gregor .Case("stddef.h", true) 38334d52749SDouglas Gregor .Case("stdint.h", true) 38434d52749SDouglas Gregor .Case("tgmath.h", true) 38534d52749SDouglas Gregor .Case("unwind.h", true) 38634d52749SDouglas Gregor .Default(false); 38734d52749SDouglas Gregor } 38834d52749SDouglas Gregor 38992669ee4SDaniel Jasper ModuleMap::HeadersMap::iterator 39092669ee4SDaniel Jasper ModuleMap::findKnownHeader(const FileEntry *File) { 391040e1266SRichard Smith resolveHeaderDirectives(File); 39259527666SDouglas Gregor HeadersMap::iterator Known = Headers.find(File); 39347972afdSRichard Smith if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && 39447972afdSRichard Smith Known == Headers.end() && File->getDir() == BuiltinIncludeDir && 395ba1b5c98SBruno Cardoso Lopes ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()))) { 3964eaf0a6cSDaniel Jasper HeaderInfo.loadTopLevelSystemModules(); 39792669ee4SDaniel Jasper return Headers.find(File); 3984eaf0a6cSDaniel Jasper } 39992669ee4SDaniel Jasper return Known; 40092669ee4SDaniel Jasper } 40192669ee4SDaniel Jasper 4024469138eSBen Langmuir ModuleMap::KnownHeader 4034469138eSBen Langmuir ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File, 4044469138eSBen Langmuir SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) { 40547972afdSRichard Smith if (UmbrellaDirs.empty()) 406afd1b1c9SEugene Zelenko return {}; 40747972afdSRichard Smith 4084469138eSBen Langmuir const DirectoryEntry *Dir = File->getDir(); 4094469138eSBen Langmuir assert(Dir && "file in no directory"); 4104469138eSBen Langmuir 4114469138eSBen Langmuir // Note: as an egregious but useful hack we use the real path here, because 4124469138eSBen Langmuir // frameworks moving from top-level frameworks to embedded frameworks tend 4134469138eSBen Langmuir // to be symlinked from the top-level location to the embedded location, 4144469138eSBen Langmuir // and we need to resolve lookups as if we had found the embedded location. 4154469138eSBen Langmuir StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir); 4164469138eSBen Langmuir 4174469138eSBen Langmuir // Keep walking up the directory hierarchy, looking for a directory with 4184469138eSBen Langmuir // an umbrella header. 4194469138eSBen Langmuir do { 4204469138eSBen Langmuir auto KnownDir = UmbrellaDirs.find(Dir); 4214469138eSBen Langmuir if (KnownDir != UmbrellaDirs.end()) 4224469138eSBen Langmuir return KnownHeader(KnownDir->second, NormalHeader); 4234469138eSBen Langmuir 4244469138eSBen Langmuir IntermediateDirs.push_back(Dir); 4254469138eSBen Langmuir 4264469138eSBen Langmuir // Retrieve our parent path. 4274469138eSBen Langmuir DirName = llvm::sys::path::parent_path(DirName); 4284469138eSBen Langmuir if (DirName.empty()) 4294469138eSBen Langmuir break; 4304469138eSBen Langmuir 4314469138eSBen Langmuir // Resolve the parent path to a directory entry. 4324469138eSBen Langmuir Dir = SourceMgr.getFileManager().getDirectory(DirName); 4334469138eSBen Langmuir } while (Dir); 434afd1b1c9SEugene Zelenko return {}; 4354469138eSBen Langmuir } 4364469138eSBen Langmuir 43792669ee4SDaniel Jasper static bool violatesPrivateInclude(Module *RequestingModule, 43892669ee4SDaniel Jasper const FileEntry *IncFileEnt, 4394eb8393cSRichard Smith ModuleMap::KnownHeader Header) { 44092669ee4SDaniel Jasper #ifndef NDEBUG 4414eb8393cSRichard Smith if (Header.getRole() & ModuleMap::PrivateHeader) { 44292669ee4SDaniel Jasper // Check for consistency between the module header role 44392669ee4SDaniel Jasper // as obtained from the lookup and as obtained from the module. 44492669ee4SDaniel Jasper // This check is not cheap, so enable it only for debugging. 4452708e520SRichard Smith bool IsPrivate = false; 4462708e520SRichard Smith SmallVectorImpl<Module::Header> *HeaderList[] = { 4474eb8393cSRichard Smith &Header.getModule()->Headers[Module::HK_Private], 4484eb8393cSRichard Smith &Header.getModule()->Headers[Module::HK_PrivateTextual]}; 4492708e520SRichard Smith for (auto *Hs : HeaderList) 4502708e520SRichard Smith IsPrivate |= 4512708e520SRichard Smith std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) { 4523c1a41adSRichard Smith return H.Entry == IncFileEnt; 4532708e520SRichard Smith }) != Hs->end(); 4544eb8393cSRichard Smith assert(IsPrivate && "inconsistent headers and roles"); 45500bc95ecSRichard Smith } 45692669ee4SDaniel Jasper #endif 4574eb8393cSRichard Smith return !Header.isAccessibleFrom(RequestingModule); 45892669ee4SDaniel Jasper } 45992669ee4SDaniel Jasper 46071e1a64fSBen Langmuir static Module *getTopLevelOrNull(Module *M) { 46171e1a64fSBen Langmuir return M ? M->getTopLevelModule() : nullptr; 46271e1a64fSBen Langmuir } 46371e1a64fSBen Langmuir 46492669ee4SDaniel Jasper void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, 4658d4e90b3SRichard Smith bool RequestingModuleIsModuleInterface, 46692669ee4SDaniel Jasper SourceLocation FilenameLoc, 46792669ee4SDaniel Jasper StringRef Filename, 46892669ee4SDaniel Jasper const FileEntry *File) { 46992669ee4SDaniel Jasper // No errors for indirect modules. This may be a bit of a problem for modules 47092669ee4SDaniel Jasper // with no source files. 47171e1a64fSBen Langmuir if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule)) 47292669ee4SDaniel Jasper return; 47392669ee4SDaniel Jasper 474040e1266SRichard Smith if (RequestingModule) { 47592669ee4SDaniel Jasper resolveUses(RequestingModule, /*Complain=*/false); 476040e1266SRichard Smith resolveHeaderDirectives(RequestingModule); 477040e1266SRichard Smith } 47892669ee4SDaniel Jasper 47971e1a64fSBen Langmuir bool Excluded = false; 480d2d442caSCraig Topper Module *Private = nullptr; 481d2d442caSCraig Topper Module *NotUsed = nullptr; 48271e1a64fSBen Langmuir 48371e1a64fSBen Langmuir HeadersMap::iterator Known = findKnownHeader(File); 48471e1a64fSBen Langmuir if (Known != Headers.end()) { 48571e1a64fSBen Langmuir for (const KnownHeader &Header : Known->second) { 48692669ee4SDaniel Jasper // Remember private headers for later printing of a diagnostic. 4874eb8393cSRichard Smith if (violatesPrivateInclude(RequestingModule, File, Header)) { 48871e1a64fSBen Langmuir Private = Header.getModule(); 48992669ee4SDaniel Jasper continue; 49092669ee4SDaniel Jasper } 49192669ee4SDaniel Jasper 49292669ee4SDaniel Jasper // If uses need to be specified explicitly, we are only allowed to return 49392669ee4SDaniel Jasper // modules that are explicitly used by the requesting module. 49492669ee4SDaniel Jasper if (RequestingModule && LangOpts.ModulesDeclUse && 4958f4d3ff1SRichard Smith !RequestingModule->directlyUses(Header.getModule())) { 49671e1a64fSBen Langmuir NotUsed = Header.getModule(); 49792669ee4SDaniel Jasper continue; 49892669ee4SDaniel Jasper } 49992669ee4SDaniel Jasper 50092669ee4SDaniel Jasper // We have found a module that we can happily use. 50192669ee4SDaniel Jasper return; 50292669ee4SDaniel Jasper } 503feb54b6dSRichard Smith 504feb54b6dSRichard Smith Excluded = true; 50571e1a64fSBen Langmuir } 50692669ee4SDaniel Jasper 50792669ee4SDaniel Jasper // We have found a header, but it is private. 508d2d442caSCraig Topper if (Private) { 50911152dd5SRichard Smith Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module) 51092669ee4SDaniel Jasper << Filename; 51192669ee4SDaniel Jasper return; 51292669ee4SDaniel Jasper } 51392669ee4SDaniel Jasper 51492669ee4SDaniel Jasper // We have found a module, but we don't use it. 515d2d442caSCraig Topper if (NotUsed) { 51611152dd5SRichard Smith Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) 5174ea330c8SDaniel Jasper << RequestingModule->getTopLevelModule()->Name << Filename; 51892669ee4SDaniel Jasper return; 51992669ee4SDaniel Jasper } 52092669ee4SDaniel Jasper 52171e1a64fSBen Langmuir if (Excluded || isHeaderInUmbrellaDirs(File)) 52271e1a64fSBen Langmuir return; 52371e1a64fSBen Langmuir 52471e1a64fSBen Langmuir // At this point, only non-modular includes remain. 52571e1a64fSBen Langmuir 52671e1a64fSBen Langmuir if (LangOpts.ModulesStrictDeclUse) { 52711152dd5SRichard Smith Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) 5284ea330c8SDaniel Jasper << RequestingModule->getTopLevelModule()->Name << Filename; 529a67e4d32SManman Ren } else if (RequestingModule && RequestingModuleIsModuleInterface && 530a67e4d32SManman Ren LangOpts.isCompilingModule()) { 531a67e4d32SManman Ren // Do not diagnose when we are not compiling a module. 53271e1a64fSBen Langmuir diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ? 53371e1a64fSBen Langmuir diag::warn_non_modular_include_in_framework_module : 53471e1a64fSBen Langmuir diag::warn_non_modular_include_in_module; 53570a7738fSManman Ren Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName() 53670a7738fSManman Ren << File->getName(); 53771e1a64fSBen Langmuir } 53892669ee4SDaniel Jasper } 53992669ee4SDaniel Jasper 540ec87a50aSRichard Smith static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New, 541ec87a50aSRichard Smith const ModuleMap::KnownHeader &Old) { 5428b7c0398SSean Silva // Prefer available modules. 5438b7c0398SSean Silva if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable()) 5448b7c0398SSean Silva return true; 5458b7c0398SSean Silva 546ec87a50aSRichard Smith // Prefer a public header over a private header. 547ec87a50aSRichard Smith if ((New.getRole() & ModuleMap::PrivateHeader) != 548ec87a50aSRichard Smith (Old.getRole() & ModuleMap::PrivateHeader)) 549ec87a50aSRichard Smith return !(New.getRole() & ModuleMap::PrivateHeader); 550ec87a50aSRichard Smith 551ec87a50aSRichard Smith // Prefer a non-textual header over a textual header. 552ec87a50aSRichard Smith if ((New.getRole() & ModuleMap::TextualHeader) != 553ec87a50aSRichard Smith (Old.getRole() & ModuleMap::TextualHeader)) 554ec87a50aSRichard Smith return !(New.getRole() & ModuleMap::TextualHeader); 555ec87a50aSRichard Smith 556ec87a50aSRichard Smith // Don't have a reason to choose between these. Just keep the first one. 557ec87a50aSRichard Smith return false; 558ec87a50aSRichard Smith } 559ec87a50aSRichard Smith 560ed84df00SBruno Cardoso Lopes ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File, 561ed84df00SBruno Cardoso Lopes bool AllowTextual) { 562306d8920SRichard Smith auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader { 563ed84df00SBruno Cardoso Lopes if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader) 564afd1b1c9SEugene Zelenko return {}; 565306d8920SRichard Smith return R; 566306d8920SRichard Smith }; 567306d8920SRichard Smith 5684881e8b2SSean Silva HeadersMap::iterator Known = findKnownHeader(File); 5691fb5c3a6SDouglas Gregor if (Known != Headers.end()) { 570202210b3SRichard Smith ModuleMap::KnownHeader Result; 57197da9178SDaniel Jasper // Iterate over all modules that 'File' is part of to find the best fit. 5724881e8b2SSean Silva for (KnownHeader &H : Known->second) { 5737e82e019SRichard Smith // Prefer a header from the source module over all others. 5747e82e019SRichard Smith if (H.getModule()->getTopLevelModule() == SourceModule) 5752f633e7cSRichard Smith return MakeResult(H); 5764881e8b2SSean Silva if (!Result || isBetterKnownHeader(H, Result)) 5774881e8b2SSean Silva Result = H; 57897da9178SDaniel Jasper } 579306d8920SRichard Smith return MakeResult(Result); 5801fb5c3a6SDouglas Gregor } 581ab0c8a84SDouglas Gregor 582386bb073SRichard Smith return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File)); 583386bb073SRichard Smith } 584386bb073SRichard Smith 585386bb073SRichard Smith ModuleMap::KnownHeader 586386bb073SRichard Smith ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) { 587386bb073SRichard Smith assert(!Headers.count(File) && "already have a module for this header"); 588386bb073SRichard Smith 589f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs; 5904469138eSBen Langmuir KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs); 5914469138eSBen Langmuir if (H) { 5924469138eSBen Langmuir Module *Result = H.getModule(); 593930a85ccSDouglas Gregor 594930a85ccSDouglas Gregor // Search up the module stack until we find a module with an umbrella 59573141fa9SDouglas Gregor // directory. 596930a85ccSDouglas Gregor Module *UmbrellaModule = Result; 59773141fa9SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 598930a85ccSDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 599930a85ccSDouglas Gregor 600930a85ccSDouglas Gregor if (UmbrellaModule->InferSubmodules) { 6019d6448b1SBen Langmuir const FileEntry *UmbrellaModuleMap = 6029d6448b1SBen Langmuir getModuleMapFileForUniquing(UmbrellaModule); 6039d6448b1SBen Langmuir 604a89c5ac4SDouglas Gregor // Infer submodules for each of the directories we found between 605a89c5ac4SDouglas Gregor // the directory of the umbrella header and the directory where 606a89c5ac4SDouglas Gregor // the actual header is located. 6079458f82dSDouglas Gregor bool Explicit = UmbrellaModule->InferExplicitSubmodules; 6089458f82dSDouglas Gregor 6097033127bSDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 610a89c5ac4SDouglas Gregor // Find or create the module that corresponds to this directory name. 611056396aeSDouglas Gregor SmallString<32> NameBuf; 612056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 6134469138eSBen Langmuir llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf); 6149d6448b1SBen Langmuir Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 6159d6448b1SBen Langmuir Explicit).first; 6169d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = UmbrellaModuleMap; 617ffbafa2aSBen Langmuir Result->IsInferred = true; 618a89c5ac4SDouglas Gregor 619a89c5ac4SDouglas Gregor // Associate the module and the directory. 620a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I-1]] = Result; 621a89c5ac4SDouglas Gregor 622a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 623a89c5ac4SDouglas Gregor // wildcard to the set of exports. 624930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 625d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 626a89c5ac4SDouglas Gregor } 627a89c5ac4SDouglas Gregor 628a89c5ac4SDouglas Gregor // Infer a submodule with the same name as this header file. 629056396aeSDouglas Gregor SmallString<32> NameBuf; 630056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 631056396aeSDouglas Gregor llvm::sys::path::stem(File->getName()), NameBuf); 6329d6448b1SBen Langmuir Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 6339d6448b1SBen Langmuir Explicit).first; 6349d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = UmbrellaModuleMap; 635ffbafa2aSBen Langmuir Result->IsInferred = true; 6363c5305c1SArgyrios Kyrtzidis Result->addTopHeader(File); 637a89c5ac4SDouglas Gregor 638a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 639a89c5ac4SDouglas Gregor // wildcard to the set of exports. 640930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 641d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 642a89c5ac4SDouglas Gregor } else { 643a89c5ac4SDouglas Gregor // Record each of the directories we stepped through as being part of 644a89c5ac4SDouglas Gregor // the module we found, since the umbrella header covers them all. 645a89c5ac4SDouglas Gregor for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I) 646a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I]] = Result; 647a89c5ac4SDouglas Gregor } 648a89c5ac4SDouglas Gregor 649386bb073SRichard Smith KnownHeader Header(Result, NormalHeader); 650386bb073SRichard Smith Headers[File].push_back(Header); 651386bb073SRichard Smith return Header; 652a89c5ac4SDouglas Gregor } 653a89c5ac4SDouglas Gregor 654afd1b1c9SEugene Zelenko return {}; 655ab0c8a84SDouglas Gregor } 656ab0c8a84SDouglas Gregor 657386bb073SRichard Smith ArrayRef<ModuleMap::KnownHeader> 658386bb073SRichard Smith ModuleMap::findAllModulesForHeader(const FileEntry *File) const { 659040e1266SRichard Smith resolveHeaderDirectives(File); 660386bb073SRichard Smith auto It = Headers.find(File); 661386bb073SRichard Smith if (It == Headers.end()) 662386bb073SRichard Smith return None; 663386bb073SRichard Smith return It->second; 664386bb073SRichard Smith } 665386bb073SRichard Smith 666e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const { 667d2d442caSCraig Topper return isHeaderUnavailableInModule(Header, nullptr); 66850996ce1SRichard Smith } 66950996ce1SRichard Smith 67062bcd925SDmitri Gribenko bool 67162bcd925SDmitri Gribenko ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, 67262bcd925SDmitri Gribenko const Module *RequestingModule) const { 673040e1266SRichard Smith resolveHeaderDirectives(Header); 674e4412640SArgyrios Kyrtzidis HeadersMap::const_iterator Known = Headers.find(Header); 67597da9178SDaniel Jasper if (Known != Headers.end()) { 67697da9178SDaniel Jasper for (SmallVectorImpl<KnownHeader>::const_iterator 67797da9178SDaniel Jasper I = Known->second.begin(), 67897da9178SDaniel Jasper E = Known->second.end(); 67997da9178SDaniel Jasper I != E; ++I) { 680052d95a6SBruno Cardoso Lopes 681052d95a6SBruno Cardoso Lopes if (I->isAvailable() && 682052d95a6SBruno Cardoso Lopes (!RequestingModule || 683052d95a6SBruno Cardoso Lopes I->getModule()->isSubModuleOf(RequestingModule))) { 684052d95a6SBruno Cardoso Lopes // When no requesting module is available, the caller is looking if a 685052d95a6SBruno Cardoso Lopes // header is part a module by only looking into the module map. This is 686052d95a6SBruno Cardoso Lopes // done by warn_uncovered_module_header checks; don't consider textual 687052d95a6SBruno Cardoso Lopes // headers part of it in this mode, otherwise we get misleading warnings 688052d95a6SBruno Cardoso Lopes // that a umbrella header is not including a textual header. 689052d95a6SBruno Cardoso Lopes if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader) 690052d95a6SBruno Cardoso Lopes continue; 69197da9178SDaniel Jasper return false; 69297da9178SDaniel Jasper } 693052d95a6SBruno Cardoso Lopes } 69497da9178SDaniel Jasper return true; 69597da9178SDaniel Jasper } 6961fb5c3a6SDouglas Gregor 6971fb5c3a6SDouglas Gregor const DirectoryEntry *Dir = Header->getDir(); 698f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs; 6991fb5c3a6SDouglas Gregor StringRef DirName = Dir->getName(); 7001fb5c3a6SDouglas Gregor 70150996ce1SRichard Smith auto IsUnavailable = [&](const Module *M) { 70250996ce1SRichard Smith return !M->isAvailable() && (!RequestingModule || 70350996ce1SRichard Smith M->isSubModuleOf(RequestingModule)); 70450996ce1SRichard Smith }; 70550996ce1SRichard Smith 7061fb5c3a6SDouglas Gregor // Keep walking up the directory hierarchy, looking for a directory with 7071fb5c3a6SDouglas Gregor // an umbrella header. 7081fb5c3a6SDouglas Gregor do { 709e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir 7101fb5c3a6SDouglas Gregor = UmbrellaDirs.find(Dir); 7111fb5c3a6SDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 7121fb5c3a6SDouglas Gregor Module *Found = KnownDir->second; 71350996ce1SRichard Smith if (IsUnavailable(Found)) 7141fb5c3a6SDouglas Gregor return true; 7151fb5c3a6SDouglas Gregor 7161fb5c3a6SDouglas Gregor // Search up the module stack until we find a module with an umbrella 7171fb5c3a6SDouglas Gregor // directory. 7181fb5c3a6SDouglas Gregor Module *UmbrellaModule = Found; 7191fb5c3a6SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 7201fb5c3a6SDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 7211fb5c3a6SDouglas Gregor 7221fb5c3a6SDouglas Gregor if (UmbrellaModule->InferSubmodules) { 7231fb5c3a6SDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 7241fb5c3a6SDouglas Gregor // Find or create the module that corresponds to this directory name. 725056396aeSDouglas Gregor SmallString<32> NameBuf; 726056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 727056396aeSDouglas Gregor llvm::sys::path::stem(SkippedDirs[I-1]->getName()), 728056396aeSDouglas Gregor NameBuf); 7291fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 7301fb5c3a6SDouglas Gregor if (!Found) 7311fb5c3a6SDouglas Gregor return false; 73250996ce1SRichard Smith if (IsUnavailable(Found)) 7331fb5c3a6SDouglas Gregor return true; 7341fb5c3a6SDouglas Gregor } 7351fb5c3a6SDouglas Gregor 7361fb5c3a6SDouglas Gregor // Infer a submodule with the same name as this header file. 737056396aeSDouglas Gregor SmallString<32> NameBuf; 738056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 739056396aeSDouglas Gregor llvm::sys::path::stem(Header->getName()), 740056396aeSDouglas Gregor NameBuf); 7411fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 7421fb5c3a6SDouglas Gregor if (!Found) 7431fb5c3a6SDouglas Gregor return false; 7441fb5c3a6SDouglas Gregor } 7451fb5c3a6SDouglas Gregor 74650996ce1SRichard Smith return IsUnavailable(Found); 7471fb5c3a6SDouglas Gregor } 7481fb5c3a6SDouglas Gregor 7491fb5c3a6SDouglas Gregor SkippedDirs.push_back(Dir); 7501fb5c3a6SDouglas Gregor 7511fb5c3a6SDouglas Gregor // Retrieve our parent path. 7521fb5c3a6SDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 7531fb5c3a6SDouglas Gregor if (DirName.empty()) 7541fb5c3a6SDouglas Gregor break; 7551fb5c3a6SDouglas Gregor 7561fb5c3a6SDouglas Gregor // Resolve the parent path to a directory entry. 7571f76c4e8SManuel Klimek Dir = SourceMgr.getFileManager().getDirectory(DirName); 7581fb5c3a6SDouglas Gregor } while (Dir); 7591fb5c3a6SDouglas Gregor 7601fb5c3a6SDouglas Gregor return false; 7611fb5c3a6SDouglas Gregor } 7621fb5c3a6SDouglas Gregor 763e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const { 764e4412640SArgyrios Kyrtzidis llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name); 76588bdfb0eSDouglas Gregor if (Known != Modules.end()) 76688bdfb0eSDouglas Gregor return Known->getValue(); 76788bdfb0eSDouglas Gregor 768d2d442caSCraig Topper return nullptr; 76988bdfb0eSDouglas Gregor } 77088bdfb0eSDouglas Gregor 771e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name, 772e4412640SArgyrios Kyrtzidis Module *Context) const { 7732b82c2a5SDouglas Gregor for(; Context; Context = Context->Parent) { 7742b82c2a5SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Context)) 7752b82c2a5SDouglas Gregor return Sub; 7762b82c2a5SDouglas Gregor } 7772b82c2a5SDouglas Gregor 7782b82c2a5SDouglas Gregor return findModule(Name); 7792b82c2a5SDouglas Gregor } 7802b82c2a5SDouglas Gregor 781e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{ 7822b82c2a5SDouglas Gregor if (!Context) 7832b82c2a5SDouglas Gregor return findModule(Name); 7842b82c2a5SDouglas Gregor 785eb90e830SDouglas Gregor return Context->findSubmodule(Name); 7862b82c2a5SDouglas Gregor } 7872b82c2a5SDouglas Gregor 788c192d194SBruno Cardoso Lopes std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name, 789c192d194SBruno Cardoso Lopes Module *Parent, 790c192d194SBruno Cardoso Lopes bool IsFramework, 791c192d194SBruno Cardoso Lopes bool IsExplicit) { 79269021974SDouglas Gregor // Try to find an existing module with this name. 793eb90e830SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Parent)) 794eb90e830SDouglas Gregor return std::make_pair(Sub, false); 79569021974SDouglas Gregor 79669021974SDouglas Gregor // Create a new module with this name. 7979ffe5a35SDavid Blaikie Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, 7989ffe5a35SDavid Blaikie IsExplicit, NumCreatedModules++); 7996f722b4eSArgyrios Kyrtzidis if (!Parent) { 8007e82e019SRichard Smith if (LangOpts.CurrentModule == Name) 8017e82e019SRichard Smith SourceModule = Result; 80269021974SDouglas Gregor Modules[Name] = Result; 803c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID; 8046f722b4eSArgyrios Kyrtzidis } 80569021974SDouglas Gregor return std::make_pair(Result, true); 80669021974SDouglas Gregor } 80769021974SDouglas Gregor 808dd8b5337SRichard Smith Module *ModuleMap::createGlobalModuleForInterfaceUnit(SourceLocation Loc) { 809056bf77fSRichard Smith assert(!PendingGlobalModule && "created multiple global modules"); 810056bf77fSRichard Smith PendingGlobalModule.reset( 811056bf77fSRichard Smith new Module("<global>", Loc, nullptr, /*IsFramework*/ false, 812056bf77fSRichard Smith /*IsExplicit*/ true, NumCreatedModules++)); 813056bf77fSRichard Smith PendingGlobalModule->Kind = Module::GlobalModuleFragment; 814056bf77fSRichard Smith return PendingGlobalModule.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. 830056bf77fSRichard Smith assert(GlobalModule == PendingGlobalModule.get() && 831056bf77fSRichard Smith "unexpected global module"); 832dd8b5337SRichard Smith GlobalModule->setParent(Result); 833056bf77fSRichard Smith PendingGlobalModule.release(); // now owned by parent 834dd8b5337SRichard Smith 835bbcc9f04SRichard Smith // Mark the main source file as being within the newly-created module so that 836bbcc9f04SRichard Smith // declarations and macros are properly visibility-restricted to it. 837bbcc9f04SRichard Smith auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()); 838bbcc9f04SRichard Smith assert(MainFile && "no input file for module interface"); 839bbcc9f04SRichard Smith Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader)); 840bbcc9f04SRichard Smith 841bbcc9f04SRichard Smith return Result; 842bbcc9f04SRichard Smith } 843bbcc9f04SRichard Smith 8449fc8faf9SAdrian Prantl /// For a framework module, infer the framework against which we 84511dfe6feSDouglas Gregor /// should link. 84611dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir, 84711dfe6feSDouglas Gregor FileManager &FileMgr) { 84811dfe6feSDouglas Gregor assert(Mod->IsFramework && "Can only infer linking for framework modules"); 84911dfe6feSDouglas Gregor assert(!Mod->isSubFramework() && 85011dfe6feSDouglas Gregor "Can only infer linking for top-level frameworks"); 85111dfe6feSDouglas Gregor 85211dfe6feSDouglas Gregor SmallString<128> LibName; 85311dfe6feSDouglas Gregor LibName += FrameworkDir->getName(); 85411dfe6feSDouglas Gregor llvm::sys::path::append(LibName, Mod->Name); 8558aaae5a9SJuergen Ributzka 8568aaae5a9SJuergen Ributzka // The library name of a framework has more than one possible extension since 8578aaae5a9SJuergen Ributzka // the introduction of the text-based dynamic library format. We need to check 8588aaae5a9SJuergen Ributzka // for both before we give up. 8598013e81dSBenjamin Kramer for (const char *extension : {"", ".tbd"}) { 8608aaae5a9SJuergen Ributzka llvm::sys::path::replace_extension(LibName, extension); 86111dfe6feSDouglas Gregor if (FileMgr.getFile(LibName)) { 86211dfe6feSDouglas Gregor Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name, 86311dfe6feSDouglas Gregor /*IsFramework=*/true)); 8648aaae5a9SJuergen Ributzka return; 8658aaae5a9SJuergen Ributzka } 86611dfe6feSDouglas Gregor } 86711dfe6feSDouglas Gregor } 86811dfe6feSDouglas Gregor 869a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 870a525400dSBen Langmuir bool IsSystem, Module *Parent) { 871c1d88ea5SBen Langmuir Attributes Attrs; 872c1d88ea5SBen Langmuir Attrs.IsSystem = IsSystem; 873a525400dSBen Langmuir return inferFrameworkModule(FrameworkDir, Attrs, Parent); 874c1d88ea5SBen Langmuir } 875c1d88ea5SBen Langmuir 876a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 877c1d88ea5SBen Langmuir Attributes Attrs, Module *Parent) { 878a525400dSBen Langmuir // Note: as an egregious but useful hack we use the real path here, because 879a525400dSBen Langmuir // we might be looking at an embedded framework that symlinks out to a 880a525400dSBen Langmuir // top-level framework, and we need to infer as if we were naming the 881a525400dSBen Langmuir // top-level framework. 882a525400dSBen Langmuir StringRef FrameworkDirName = 883a525400dSBen Langmuir SourceMgr.getFileManager().getCanonicalName(FrameworkDir); 884a525400dSBen Langmuir 885a525400dSBen Langmuir // In case this is a case-insensitive filesystem, use the canonical 886a525400dSBen Langmuir // directory name as the ModuleName, since modules are case-sensitive. 887a525400dSBen Langmuir // FIXME: we should be able to give a fix-it hint for the correct spelling. 888a525400dSBen Langmuir SmallString<32> ModuleNameStorage; 889a525400dSBen Langmuir StringRef ModuleName = sanitizeFilenameAsIdentifier( 890a525400dSBen Langmuir llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage); 891c1d88ea5SBen Langmuir 89256c64013SDouglas Gregor // Check whether we've already found this module. 893e89dbc1dSDouglas Gregor if (Module *Mod = lookupModuleQualified(ModuleName, Parent)) 894e89dbc1dSDouglas Gregor return Mod; 895e89dbc1dSDouglas Gregor 8961f76c4e8SManuel Klimek FileManager &FileMgr = SourceMgr.getFileManager(); 89756c64013SDouglas Gregor 8989194a91dSDouglas Gregor // If the framework has a parent path from which we're allowed to infer 8999194a91dSDouglas Gregor // a framework module, do so. 900beee15e7SBen Langmuir const FileEntry *ModuleMapFile = nullptr; 9019194a91dSDouglas Gregor if (!Parent) { 9024ddf2221SDouglas Gregor // Determine whether we're allowed to infer a module map. 9039194a91dSDouglas Gregor bool canInfer = false; 9044ddf2221SDouglas Gregor if (llvm::sys::path::has_parent_path(FrameworkDirName)) { 9059194a91dSDouglas Gregor // Figure out the parent path. 9064ddf2221SDouglas Gregor StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName); 9079194a91dSDouglas Gregor if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) { 9089194a91dSDouglas Gregor // Check whether we have already looked into the parent directory 9099194a91dSDouglas Gregor // for a module map. 910e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator 9119194a91dSDouglas Gregor inferred = InferredDirectories.find(ParentDir); 9129194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) { 9139194a91dSDouglas Gregor // We haven't looked here before. Load a module map, if there is 9149194a91dSDouglas Gregor // one. 915984e1df7SBen Langmuir bool IsFrameworkDir = Parent.endswith(".framework"); 916984e1df7SBen Langmuir if (const FileEntry *ModMapFile = 917984e1df7SBen Langmuir HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) { 918c1d88ea5SBen Langmuir parseModuleMapFile(ModMapFile, Attrs.IsSystem, ParentDir); 9199194a91dSDouglas Gregor inferred = InferredDirectories.find(ParentDir); 9209194a91dSDouglas Gregor } 9219194a91dSDouglas Gregor 9229194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) 9239194a91dSDouglas Gregor inferred = InferredDirectories.insert( 9249194a91dSDouglas Gregor std::make_pair(ParentDir, InferredDirectory())).first; 9259194a91dSDouglas Gregor } 9269194a91dSDouglas Gregor 9279194a91dSDouglas Gregor if (inferred->second.InferModules) { 9289194a91dSDouglas Gregor // We're allowed to infer for this directory, but make sure it's okay 9299194a91dSDouglas Gregor // to infer this particular module. 9304ddf2221SDouglas Gregor StringRef Name = llvm::sys::path::stem(FrameworkDirName); 9319194a91dSDouglas Gregor canInfer = std::find(inferred->second.ExcludedModules.begin(), 9329194a91dSDouglas Gregor inferred->second.ExcludedModules.end(), 9339194a91dSDouglas Gregor Name) == inferred->second.ExcludedModules.end(); 9349194a91dSDouglas Gregor 935c1d88ea5SBen Langmuir Attrs.IsSystem |= inferred->second.Attrs.IsSystem; 936c1d88ea5SBen Langmuir Attrs.IsExternC |= inferred->second.Attrs.IsExternC; 937c1d88ea5SBen Langmuir Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive; 938ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes |= 939ed84df00SBruno Cardoso Lopes inferred->second.Attrs.NoUndeclaredIncludes; 940beee15e7SBen Langmuir ModuleMapFile = inferred->second.ModuleMapFile; 9419194a91dSDouglas Gregor } 9429194a91dSDouglas Gregor } 9439194a91dSDouglas Gregor } 9449194a91dSDouglas Gregor 9459194a91dSDouglas Gregor // If we're not allowed to infer a framework module, don't. 9469194a91dSDouglas Gregor if (!canInfer) 947d2d442caSCraig Topper return nullptr; 948beee15e7SBen Langmuir } else 9499d6448b1SBen Langmuir ModuleMapFile = getModuleMapFileForUniquing(Parent); 9509194a91dSDouglas Gregor 9519194a91dSDouglas Gregor 95256c64013SDouglas Gregor // Look for an umbrella header. 9532c1dd271SDylan Noblesmith SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 95417381a06SBenjamin Kramer llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h"); 955e89dbc1dSDouglas Gregor const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName); 95656c64013SDouglas Gregor 95756c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the 95856c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good 95956c64013SDouglas Gregor // idea. 96056c64013SDouglas Gregor if (!UmbrellaHeader) 961d2d442caSCraig Topper return nullptr; 96256c64013SDouglas Gregor 9639d6448b1SBen Langmuir Module *Result = new Module(ModuleName, SourceLocation(), Parent, 964a7e2cc68SRichard Smith /*IsFramework=*/true, /*IsExplicit=*/false, 965a7e2cc68SRichard Smith NumCreatedModules++); 9669d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = ModuleMapFile; 9679d6448b1SBen Langmuir Result->IsInferred = true; 9687e82e019SRichard Smith if (!Parent) { 9697e82e019SRichard Smith if (LangOpts.CurrentModule == ModuleName) 970ba7f2f71SDaniel Jasper SourceModule = Result; 9717e82e019SRichard Smith Modules[ModuleName] = Result; 972c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID; 973ba7f2f71SDaniel Jasper } 974c1d88ea5SBen Langmuir 975c1d88ea5SBen Langmuir Result->IsSystem |= Attrs.IsSystem; 976c1d88ea5SBen Langmuir Result->IsExternC |= Attrs.IsExternC; 977c1d88ea5SBen Langmuir Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive; 978ed84df00SBruno Cardoso Lopes Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes; 9792b63d15fSRichard Smith Result->Directory = FrameworkDir; 980a686e1b0SDouglas Gregor 981322f633cSDouglas Gregor // umbrella header "umbrella-header-name" 9822b63d15fSRichard Smith // 9832b63d15fSRichard Smith // The "Headers/" component of the name is implied because this is 9842b63d15fSRichard Smith // a framework module. 9852b63d15fSRichard Smith setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h"); 986d8bd7537SDouglas Gregor 987d8bd7537SDouglas Gregor // export * 988d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 989d8bd7537SDouglas Gregor 990a89c5ac4SDouglas Gregor // module * { export * } 991a89c5ac4SDouglas Gregor Result->InferSubmodules = true; 992a89c5ac4SDouglas Gregor Result->InferExportWildcard = true; 993a89c5ac4SDouglas Gregor 994e89dbc1dSDouglas Gregor // Look for subframeworks. 995c080917eSRafael Espindola std::error_code EC; 9962c1dd271SDylan Noblesmith SmallString<128> SubframeworksDirName 997ddaa69cbSDouglas Gregor = StringRef(FrameworkDir->getName()); 998e89dbc1dSDouglas Gregor llvm::sys::path::append(SubframeworksDirName, "Frameworks"); 9992d4d8cb3SBenjamin Kramer llvm::sys::path::native(SubframeworksDirName); 1000b171a59bSBruno Cardoso Lopes vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); 1001b171a59bSBruno Cardoso Lopes for (vfs::directory_iterator Dir = FS.dir_begin(SubframeworksDirName, EC), 1002b171a59bSBruno Cardoso Lopes DirEnd; 1003e89dbc1dSDouglas Gregor Dir != DirEnd && !EC; Dir.increment(EC)) { 1004*0ae00567SSam McCall if (!StringRef(Dir->path()).endswith(".framework")) 1005e89dbc1dSDouglas Gregor continue; 1006f2161a70SDouglas Gregor 1007b171a59bSBruno Cardoso Lopes if (const DirectoryEntry *SubframeworkDir = 1008*0ae00567SSam McCall FileMgr.getDirectory(Dir->path())) { 100907c22b78SDouglas Gregor // Note: as an egregious but useful hack, we use the real path here and 101007c22b78SDouglas Gregor // check whether it is actually a subdirectory of the parent directory. 101107c22b78SDouglas Gregor // This will not be the case if the 'subframework' is actually a symlink 101207c22b78SDouglas Gregor // out to a top-level framework. 1013e00c8b20SDouglas Gregor StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir); 101407c22b78SDouglas Gregor bool FoundParent = false; 101507c22b78SDouglas Gregor do { 101607c22b78SDouglas Gregor // Get the parent directory name. 101707c22b78SDouglas Gregor SubframeworkDirName 101807c22b78SDouglas Gregor = llvm::sys::path::parent_path(SubframeworkDirName); 101907c22b78SDouglas Gregor if (SubframeworkDirName.empty()) 102007c22b78SDouglas Gregor break; 102107c22b78SDouglas Gregor 102207c22b78SDouglas Gregor if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) { 102307c22b78SDouglas Gregor FoundParent = true; 102407c22b78SDouglas Gregor break; 102507c22b78SDouglas Gregor } 102607c22b78SDouglas Gregor } while (true); 102707c22b78SDouglas Gregor 102807c22b78SDouglas Gregor if (!FoundParent) 102907c22b78SDouglas Gregor continue; 103007c22b78SDouglas Gregor 1031e89dbc1dSDouglas Gregor // FIXME: Do we want to warn about subframeworks without umbrella headers? 1032a525400dSBen Langmuir inferFrameworkModule(SubframeworkDir, Attrs, Result); 1033e89dbc1dSDouglas Gregor } 1034e89dbc1dSDouglas Gregor } 1035e89dbc1dSDouglas Gregor 103611dfe6feSDouglas Gregor // If the module is a top-level framework, automatically link against the 103711dfe6feSDouglas Gregor // framework. 103811dfe6feSDouglas Gregor if (!Result->isSubFramework()) { 103911dfe6feSDouglas Gregor inferFrameworkLink(Result, FrameworkDir, FileMgr); 104011dfe6feSDouglas Gregor } 104111dfe6feSDouglas Gregor 104256c64013SDouglas Gregor return Result; 104356c64013SDouglas Gregor } 104456c64013SDouglas Gregor 10458587dfd9SBruno Cardoso Lopes Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework, 10468587dfd9SBruno Cardoso Lopes Module *ShadowingModule) { 10478587dfd9SBruno Cardoso Lopes 10488587dfd9SBruno Cardoso Lopes // Create a new module with this name. 10498587dfd9SBruno Cardoso Lopes Module *Result = 10508587dfd9SBruno Cardoso Lopes new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework, 10518587dfd9SBruno Cardoso Lopes /*IsExplicit=*/false, NumCreatedModules++); 10528587dfd9SBruno Cardoso Lopes Result->ShadowingModule = ShadowingModule; 10538587dfd9SBruno Cardoso Lopes Result->IsAvailable = false; 1054c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID; 10558587dfd9SBruno Cardoso Lopes ShadowModules.push_back(Result); 10568587dfd9SBruno Cardoso Lopes 10578587dfd9SBruno Cardoso Lopes return Result; 10588587dfd9SBruno Cardoso Lopes } 10598587dfd9SBruno Cardoso Lopes 10602b63d15fSRichard Smith void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader, 10612b63d15fSRichard Smith Twine NameAsWritten) { 106297da9178SDaniel Jasper Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader)); 106373141fa9SDouglas Gregor Mod->Umbrella = UmbrellaHeader; 10642b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 10657033127bSDouglas Gregor UmbrellaDirs[UmbrellaHeader->getDir()] = Mod; 1066b3a0fa48SBruno Cardoso Lopes 1067b3a0fa48SBruno Cardoso Lopes // Notify callbacks that we just added a new header. 1068b3a0fa48SBruno Cardoso Lopes for (const auto &Cb : Callbacks) 1069b3a0fa48SBruno Cardoso Lopes Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader); 1070a89c5ac4SDouglas Gregor } 1071a89c5ac4SDouglas Gregor 10722b63d15fSRichard Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, 10732b63d15fSRichard Smith Twine NameAsWritten) { 1074524e33e1SDouglas Gregor Mod->Umbrella = UmbrellaDir; 10752b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 1076524e33e1SDouglas Gregor UmbrellaDirs[UmbrellaDir] = Mod; 1077524e33e1SDouglas Gregor } 1078524e33e1SDouglas Gregor 1079040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod, 10809f6020bcSBruno Cardoso Lopes Module::UnresolvedHeaderDirective Header, 10819f6020bcSBruno Cardoso Lopes bool &NeedsFramework) { 1082040e1266SRichard Smith // If there is a builtin counterpart to this file, add it now so it can 1083040e1266SRichard Smith // wrap the system header. 1084040e1266SRichard Smith if (resolveAsBuiltinHeader(Mod, Header)) { 1085040e1266SRichard Smith // If we have both a builtin and system version of the file, the 1086040e1266SRichard Smith // builtin version may want to inject macros into the system header, so 1087040e1266SRichard Smith // force the system header to be treated as a textual header in this 1088040e1266SRichard Smith // case. 1089040e1266SRichard Smith Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole( 1090040e1266SRichard Smith headerKindToRole(Header.Kind) | ModuleMap::TextualHeader)); 1091040e1266SRichard Smith Header.HasBuiltinHeader = true; 10923c1a41adSRichard Smith } 1093040e1266SRichard Smith 1094040e1266SRichard Smith // If possible, don't stat the header until we need to. This requires the 1095040e1266SRichard Smith // user to have provided us with some stat information about the file. 1096040e1266SRichard Smith // FIXME: Add support for lazily stat'ing umbrella headers and excluded 1097040e1266SRichard Smith // headers. 1098040e1266SRichard Smith if ((Header.Size || Header.ModTime) && !Header.IsUmbrella && 1099040e1266SRichard Smith Header.Kind != Module::HK_Excluded) { 1100040e1266SRichard Smith // We expect more variation in mtime than size, so if we're given both, 1101040e1266SRichard Smith // use the mtime as the key. 1102040e1266SRichard Smith if (Header.ModTime) 1103040e1266SRichard Smith LazyHeadersByModTime[*Header.ModTime].push_back(Mod); 1104040e1266SRichard Smith else 1105040e1266SRichard Smith LazyHeadersBySize[*Header.Size].push_back(Mod); 1106040e1266SRichard Smith Mod->UnresolvedHeaders.push_back(Header); 1107040e1266SRichard Smith return; 1108040e1266SRichard Smith } 1109040e1266SRichard Smith 1110040e1266SRichard Smith // We don't have stat information or can't defer looking this file up. 1111040e1266SRichard Smith // Perform the lookup now. 11129f6020bcSBruno Cardoso Lopes resolveHeader(Mod, Header, NeedsFramework); 1113040e1266SRichard Smith } 1114040e1266SRichard Smith 1115040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const { 1116040e1266SRichard Smith auto BySize = LazyHeadersBySize.find(File->getSize()); 1117040e1266SRichard Smith if (BySize != LazyHeadersBySize.end()) { 1118040e1266SRichard Smith for (auto *M : BySize->second) 1119040e1266SRichard Smith resolveHeaderDirectives(M); 1120040e1266SRichard Smith LazyHeadersBySize.erase(BySize); 1121040e1266SRichard Smith } 1122040e1266SRichard Smith 1123040e1266SRichard Smith auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime()); 1124040e1266SRichard Smith if (ByModTime != LazyHeadersByModTime.end()) { 1125040e1266SRichard Smith for (auto *M : ByModTime->second) 1126040e1266SRichard Smith resolveHeaderDirectives(M); 1127040e1266SRichard Smith LazyHeadersByModTime.erase(ByModTime); 1128040e1266SRichard Smith } 1129040e1266SRichard Smith } 1130040e1266SRichard Smith 1131040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(Module *Mod) const { 11329f6020bcSBruno Cardoso Lopes bool NeedsFramework = false; 1133040e1266SRichard Smith for (auto &Header : Mod->UnresolvedHeaders) 1134040e1266SRichard Smith // This operation is logically const; we're just changing how we represent 1135040e1266SRichard Smith // the header information for this file. 11369f6020bcSBruno Cardoso Lopes const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework); 1137040e1266SRichard Smith Mod->UnresolvedHeaders.clear(); 11380e98d938SNAKAMURA Takumi } 1139202210b3SRichard Smith 11403c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header, 1141d8879c85SRichard Smith ModuleHeaderRole Role, bool Imported) { 1142386bb073SRichard Smith KnownHeader KH(Mod, Role); 11433c1a41adSRichard Smith 1144386bb073SRichard Smith // Only add each header to the headers list once. 1145386bb073SRichard Smith // FIXME: Should we diagnose if a header is listed twice in the 1146386bb073SRichard Smith // same module definition? 1147386bb073SRichard Smith auto &HeaderList = Headers[Header.Entry]; 1148386bb073SRichard Smith for (auto H : HeaderList) 1149386bb073SRichard Smith if (H == KH) 1150386bb073SRichard Smith return; 1151386bb073SRichard Smith 1152386bb073SRichard Smith HeaderList.push_back(KH); 11531ec383c7SPiotr Padlewski Mod->Headers[headerRoleToKind(Role)].push_back(Header); 1154386bb073SRichard Smith 11557e82e019SRichard Smith bool isCompilingModuleHeader = 1156bbcc9f04SRichard Smith LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule; 1157d8879c85SRichard Smith if (!Imported || isCompilingModuleHeader) { 1158d8879c85SRichard Smith // When we import HeaderFileInfo, the external source is expected to 1159d8879c85SRichard Smith // set the isModuleHeader flag itself. 1160d8879c85SRichard Smith HeaderInfo.MarkFileModuleHeader(Header.Entry, Role, 1161d8879c85SRichard Smith isCompilingModuleHeader); 1162d8879c85SRichard Smith } 1163e62cfd7cSBruno Cardoso Lopes 1164e62cfd7cSBruno Cardoso Lopes // Notify callbacks that we just added a new header. 1165e62cfd7cSBruno Cardoso Lopes for (const auto &Cb : Callbacks) 1166f0841790SBruno Cardoso Lopes Cb->moduleMapAddHeader(Header.Entry->getName()); 1167a89c5ac4SDouglas Gregor } 1168a89c5ac4SDouglas Gregor 11693c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) { 1170feb54b6dSRichard Smith // Add this as a known header so we won't implicitly add it to any 1171feb54b6dSRichard Smith // umbrella directory module. 1172feb54b6dSRichard Smith // FIXME: Should we only exclude it from umbrella modules within the 1173feb54b6dSRichard Smith // specified module? 11743c1a41adSRichard Smith (void) Headers[Header.Entry]; 11753c1a41adSRichard Smith 11763c1a41adSRichard Smith Mod->Headers[Module::HK_Excluded].push_back(std::move(Header)); 1177feb54b6dSRichard Smith } 1178feb54b6dSRichard Smith 1179514b636aSDouglas Gregor const FileEntry * 11804b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const { 11811f76c4e8SManuel Klimek if (Module->DefinitionLoc.isInvalid()) 1182d2d442caSCraig Topper return nullptr; 1183514b636aSDouglas Gregor 11841f76c4e8SManuel Klimek return SourceMgr.getFileEntryForID( 11851f76c4e8SManuel Klimek SourceMgr.getFileID(Module->DefinitionLoc)); 1186514b636aSDouglas Gregor } 1187514b636aSDouglas Gregor 11884b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const { 11899d6448b1SBen Langmuir if (M->IsInferred) { 11909d6448b1SBen Langmuir assert(InferredModuleAllowedBy.count(M) && "missing inferred module map"); 11919d6448b1SBen Langmuir return InferredModuleAllowedBy.find(M)->second; 11929d6448b1SBen Langmuir } 11939d6448b1SBen Langmuir return getContainingModuleMapFile(M); 11949d6448b1SBen Langmuir } 11959d6448b1SBen Langmuir 11969d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) { 11979d6448b1SBen Langmuir assert(M->IsInferred && "module not inferred"); 11989d6448b1SBen Langmuir InferredModuleAllowedBy[M] = ModMap; 11999d6448b1SBen Langmuir } 12009d6448b1SBen Langmuir 1201cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() { 1202718292f2SDouglas Gregor llvm::errs() << "Modules:"; 1203718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 1204718292f2SDouglas Gregor MEnd = Modules.end(); 1205718292f2SDouglas Gregor M != MEnd; ++M) 1206d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 1207718292f2SDouglas Gregor 1208718292f2SDouglas Gregor llvm::errs() << "Headers:"; 120959527666SDouglas Gregor for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end(); 1210718292f2SDouglas Gregor H != HEnd; ++H) { 121197da9178SDaniel Jasper llvm::errs() << " \"" << H->first->getName() << "\" -> "; 121297da9178SDaniel Jasper for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(), 121397da9178SDaniel Jasper E = H->second.end(); 121497da9178SDaniel Jasper I != E; ++I) { 121597da9178SDaniel Jasper if (I != H->second.begin()) 121697da9178SDaniel Jasper llvm::errs() << ","; 121797da9178SDaniel Jasper llvm::errs() << I->getModule()->getFullModuleName(); 121897da9178SDaniel Jasper } 121997da9178SDaniel Jasper llvm::errs() << "\n"; 1220718292f2SDouglas Gregor } 1221718292f2SDouglas Gregor } 1222718292f2SDouglas Gregor 12232b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) { 122442413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedExports); 122542413141SRichard Smith Mod->UnresolvedExports.clear(); 122642413141SRichard Smith for (auto &UE : Unresolved) { 122742413141SRichard Smith Module::ExportDecl Export = resolveExport(Mod, UE, Complain); 1228f5eedd05SDouglas Gregor if (Export.getPointer() || Export.getInt()) 12292b82c2a5SDouglas Gregor Mod->Exports.push_back(Export); 12302b82c2a5SDouglas Gregor else 123142413141SRichard Smith Mod->UnresolvedExports.push_back(UE); 12322b82c2a5SDouglas Gregor } 123342413141SRichard Smith return !Mod->UnresolvedExports.empty(); 12342b82c2a5SDouglas Gregor } 12352b82c2a5SDouglas Gregor 1236ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) { 123742413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedDirectUses); 123842413141SRichard Smith Mod->UnresolvedDirectUses.clear(); 123942413141SRichard Smith for (auto &UDU : Unresolved) { 124042413141SRichard Smith Module *DirectUse = resolveModuleId(UDU, Mod, Complain); 1241ba7f2f71SDaniel Jasper if (DirectUse) 1242ba7f2f71SDaniel Jasper Mod->DirectUses.push_back(DirectUse); 1243ba7f2f71SDaniel Jasper else 124442413141SRichard Smith Mod->UnresolvedDirectUses.push_back(UDU); 1245ba7f2f71SDaniel Jasper } 124642413141SRichard Smith return !Mod->UnresolvedDirectUses.empty(); 1247ba7f2f71SDaniel Jasper } 1248ba7f2f71SDaniel Jasper 1249fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) { 125042413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedConflicts); 125142413141SRichard Smith Mod->UnresolvedConflicts.clear(); 125242413141SRichard Smith for (auto &UC : Unresolved) { 125342413141SRichard Smith if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) { 1254fb912657SDouglas Gregor Module::Conflict Conflict; 1255fb912657SDouglas Gregor Conflict.Other = OtherMod; 125642413141SRichard Smith Conflict.Message = UC.Message; 1257fb912657SDouglas Gregor Mod->Conflicts.push_back(Conflict); 125842413141SRichard Smith } else 125942413141SRichard Smith Mod->UnresolvedConflicts.push_back(UC); 1260fb912657SDouglas Gregor } 126142413141SRichard Smith return !Mod->UnresolvedConflicts.empty(); 1262fb912657SDouglas Gregor } 1263fb912657SDouglas Gregor 1264718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1265718292f2SDouglas Gregor // Module map file parser 1266718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1267718292f2SDouglas Gregor 1268718292f2SDouglas Gregor namespace clang { 1269afd1b1c9SEugene Zelenko 12709fc8faf9SAdrian Prantl /// A token in a module map file. 1271718292f2SDouglas Gregor struct MMToken { 1272718292f2SDouglas Gregor enum TokenKind { 12731fb5c3a6SDouglas Gregor Comma, 127435b13eceSDouglas Gregor ConfigMacros, 1275fb912657SDouglas Gregor Conflict, 1276718292f2SDouglas Gregor EndOfFile, 1277718292f2SDouglas Gregor HeaderKeyword, 1278718292f2SDouglas Gregor Identifier, 1279a3feee2aSRichard Smith Exclaim, 128059527666SDouglas Gregor ExcludeKeyword, 1281718292f2SDouglas Gregor ExplicitKeyword, 12822b82c2a5SDouglas Gregor ExportKeyword, 1283f0b11de2SDouglas Gregor ExportAsKeyword, 128497292843SDaniel Jasper ExternKeyword, 1285755b2055SDouglas Gregor FrameworkKeyword, 12866ddfca91SDouglas Gregor LinkKeyword, 1287718292f2SDouglas Gregor ModuleKeyword, 12882b82c2a5SDouglas Gregor Period, 1289b53e5483SLawrence Crowl PrivateKeyword, 1290718292f2SDouglas Gregor UmbrellaKeyword, 1291ba7f2f71SDaniel Jasper UseKeyword, 12921fb5c3a6SDouglas Gregor RequiresKeyword, 12932b82c2a5SDouglas Gregor Star, 1294718292f2SDouglas Gregor StringLiteral, 1295040e1266SRichard Smith IntegerLiteral, 1296306d8920SRichard Smith TextualKeyword, 1297718292f2SDouglas Gregor LBrace, 1298a686e1b0SDouglas Gregor RBrace, 1299a686e1b0SDouglas Gregor LSquare, 1300a686e1b0SDouglas Gregor RSquare 1301718292f2SDouglas Gregor } Kind; 1302718292f2SDouglas Gregor 1303718292f2SDouglas Gregor unsigned Location; 1304718292f2SDouglas Gregor unsigned StringLength; 1305040e1266SRichard Smith union { 1306040e1266SRichard Smith // If Kind != IntegerLiteral. 1307718292f2SDouglas Gregor const char *StringData; 1308afd1b1c9SEugene Zelenko 1309040e1266SRichard Smith // If Kind == IntegerLiteral. 1310040e1266SRichard Smith uint64_t IntegerValue; 1311040e1266SRichard Smith }; 1312718292f2SDouglas Gregor 1313718292f2SDouglas Gregor void clear() { 1314718292f2SDouglas Gregor Kind = EndOfFile; 1315718292f2SDouglas Gregor Location = 0; 1316718292f2SDouglas Gregor StringLength = 0; 1317d2d442caSCraig Topper StringData = nullptr; 1318718292f2SDouglas Gregor } 1319718292f2SDouglas Gregor 1320718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 1321718292f2SDouglas Gregor 1322718292f2SDouglas Gregor SourceLocation getLocation() const { 1323718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 1324718292f2SDouglas Gregor } 1325718292f2SDouglas Gregor 1326040e1266SRichard Smith uint64_t getInteger() const { 1327040e1266SRichard Smith return Kind == IntegerLiteral ? IntegerValue : 0; 1328040e1266SRichard Smith } 1329040e1266SRichard Smith 1330718292f2SDouglas Gregor StringRef getString() const { 1331040e1266SRichard Smith return Kind == IntegerLiteral ? StringRef() 1332040e1266SRichard Smith : StringRef(StringData, StringLength); 1333718292f2SDouglas Gregor } 1334718292f2SDouglas Gregor }; 1335718292f2SDouglas Gregor 1336718292f2SDouglas Gregor class ModuleMapParser { 1337718292f2SDouglas Gregor Lexer &L; 1338718292f2SDouglas Gregor SourceManager &SourceMgr; 1339bc10b9fbSDouglas Gregor 13409fc8faf9SAdrian Prantl /// Default target information, used only for string literal 1341bc10b9fbSDouglas Gregor /// parsing. 1342bc10b9fbSDouglas Gregor const TargetInfo *Target; 1343bc10b9fbSDouglas Gregor 1344718292f2SDouglas Gregor DiagnosticsEngine &Diags; 1345718292f2SDouglas Gregor ModuleMap ⤅ 1346718292f2SDouglas Gregor 13479fc8faf9SAdrian Prantl /// The current module map file. 1348beee15e7SBen Langmuir const FileEntry *ModuleMapFile; 1349beee15e7SBen Langmuir 13509f6020bcSBruno Cardoso Lopes /// Source location of most recent parsed module declaration 13519f6020bcSBruno Cardoso Lopes SourceLocation CurrModuleDeclLoc; 13529f6020bcSBruno Cardoso Lopes 13539fc8faf9SAdrian Prantl /// The directory that file names in this module map file should 13549acb99e3SRichard Smith /// be resolved relative to. 13555257fc63SDouglas Gregor const DirectoryEntry *Directory; 13565257fc63SDouglas Gregor 13579fc8faf9SAdrian Prantl /// Whether this module map is in a system header directory. 1358963c5535SDouglas Gregor bool IsSystem; 1359963c5535SDouglas Gregor 13609fc8faf9SAdrian Prantl /// Whether an error occurred. 1361afd1b1c9SEugene Zelenko bool HadError = false; 1362718292f2SDouglas Gregor 13639fc8faf9SAdrian Prantl /// Stores string data for the various string literals referenced 1364718292f2SDouglas Gregor /// during parsing. 1365718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 1366718292f2SDouglas Gregor 13679fc8faf9SAdrian Prantl /// The current token. 1368718292f2SDouglas Gregor MMToken Tok; 1369718292f2SDouglas Gregor 13709fc8faf9SAdrian Prantl /// The active module. 1371afd1b1c9SEugene Zelenko Module *ActiveModule = nullptr; 1372718292f2SDouglas Gregor 13739fc8faf9SAdrian Prantl /// Whether a module uses the 'requires excluded' hack to mark its 13747ff29148SBen Langmuir /// contents as 'textual'. 13757ff29148SBen Langmuir /// 13767ff29148SBen Langmuir /// On older Darwin SDK versions, 'requires excluded' is used to mark the 13777ff29148SBen Langmuir /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as 13787ff29148SBen Langmuir /// non-modular headers. For backwards compatibility, we continue to 13797ff29148SBen Langmuir /// support this idiom for just these modules, and map the headers to 13807ff29148SBen Langmuir /// 'textual' to match the original intent. 13817ff29148SBen Langmuir llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack; 13827ff29148SBen Langmuir 13839fc8faf9SAdrian Prantl /// Consume the current token and return its location. 1384718292f2SDouglas Gregor SourceLocation consumeToken(); 1385718292f2SDouglas Gregor 13869fc8faf9SAdrian Prantl /// Skip tokens until we reach the a token with the given kind 1387718292f2SDouglas Gregor /// (or the end of the file). 1388718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 1389718292f2SDouglas Gregor 1390afd1b1c9SEugene Zelenko using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>; 1391afd1b1c9SEugene Zelenko 1392e7ab3669SDouglas Gregor bool parseModuleId(ModuleId &Id); 1393718292f2SDouglas Gregor void parseModuleDecl(); 139497292843SDaniel Jasper void parseExternModuleDecl(); 13951fb5c3a6SDouglas Gregor void parseRequiresDecl(); 1396afd1b1c9SEugene Zelenko void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc); 1397524e33e1SDouglas Gregor void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc); 13982b82c2a5SDouglas Gregor void parseExportDecl(); 1399f0b11de2SDouglas Gregor void parseExportAsDecl(); 1400ba7f2f71SDaniel Jasper void parseUseDecl(); 14016ddfca91SDouglas Gregor void parseLinkDecl(); 140235b13eceSDouglas Gregor void parseConfigMacros(); 1403fb912657SDouglas Gregor void parseConflict(); 14049194a91dSDouglas Gregor void parseInferredModuleDecl(bool Framework, bool Explicit); 1405c1d88ea5SBen Langmuir 14065f11e128SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra 14075f11e128SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH 14085f11e128SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written 14095f11e128SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits. 14105f11e128SBruno Cardoso Lopes void diagnosePrivateModules(SourceLocation ExplicitLoc, 14115f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc); 14125f11e128SBruno Cardoso Lopes 1413afd1b1c9SEugene Zelenko using Attributes = ModuleMap::Attributes; 1414afd1b1c9SEugene Zelenko 14154442605fSBill Wendling bool parseOptionalAttributes(Attributes &Attrs); 1416718292f2SDouglas Gregor 1417718292f2SDouglas Gregor public: 1418718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 14198587dfd9SBruno Cardoso Lopes const TargetInfo *Target, DiagnosticsEngine &Diags, 14208587dfd9SBruno Cardoso Lopes ModuleMap &Map, const FileEntry *ModuleMapFile, 1421c192d194SBruno Cardoso Lopes const DirectoryEntry *Directory, bool IsSystem) 1422bc10b9fbSDouglas Gregor : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map), 1423beee15e7SBen Langmuir ModuleMapFile(ModuleMapFile), Directory(Directory), 1424c192d194SBruno Cardoso Lopes IsSystem(IsSystem) { 1425718292f2SDouglas Gregor Tok.clear(); 1426718292f2SDouglas Gregor consumeToken(); 1427718292f2SDouglas Gregor } 1428718292f2SDouglas Gregor 1429718292f2SDouglas Gregor bool parseModuleMapFile(); 14308128f332SRichard Smith 14318128f332SRichard Smith bool terminatedByDirective() { return false; } 14328128f332SRichard Smith SourceLocation getLocation() { return Tok.getLocation(); } 1433718292f2SDouglas Gregor }; 1434afd1b1c9SEugene Zelenko 1435afd1b1c9SEugene Zelenko } // namespace clang 1436718292f2SDouglas Gregor 1437718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 1438718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 1439718292f2SDouglas Gregor 14408128f332SRichard Smith retry: 14418128f332SRichard Smith Tok.clear(); 1442718292f2SDouglas Gregor Token LToken; 1443718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 1444718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 1445718292f2SDouglas Gregor switch (LToken.getKind()) { 14462d57cea2SAlp Toker case tok::raw_identifier: { 14472d57cea2SAlp Toker StringRef RI = LToken.getRawIdentifier(); 14482d57cea2SAlp Toker Tok.StringData = RI.data(); 14492d57cea2SAlp Toker Tok.StringLength = RI.size(); 14502d57cea2SAlp Toker Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI) 145135b13eceSDouglas Gregor .Case("config_macros", MMToken::ConfigMacros) 1452fb912657SDouglas Gregor .Case("conflict", MMToken::Conflict) 145359527666SDouglas Gregor .Case("exclude", MMToken::ExcludeKeyword) 1454718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 14552b82c2a5SDouglas Gregor .Case("export", MMToken::ExportKeyword) 1456f0b11de2SDouglas Gregor .Case("export_as", MMToken::ExportAsKeyword) 145797292843SDaniel Jasper .Case("extern", MMToken::ExternKeyword) 1458755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 145935b13eceSDouglas Gregor .Case("header", MMToken::HeaderKeyword) 14606ddfca91SDouglas Gregor .Case("link", MMToken::LinkKeyword) 1461718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 1462b53e5483SLawrence Crowl .Case("private", MMToken::PrivateKeyword) 14631fb5c3a6SDouglas Gregor .Case("requires", MMToken::RequiresKeyword) 1464306d8920SRichard Smith .Case("textual", MMToken::TextualKeyword) 1465718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 1466ba7f2f71SDaniel Jasper .Case("use", MMToken::UseKeyword) 1467718292f2SDouglas Gregor .Default(MMToken::Identifier); 1468718292f2SDouglas Gregor break; 14692d57cea2SAlp Toker } 1470718292f2SDouglas Gregor 14711fb5c3a6SDouglas Gregor case tok::comma: 14721fb5c3a6SDouglas Gregor Tok.Kind = MMToken::Comma; 14731fb5c3a6SDouglas Gregor break; 14741fb5c3a6SDouglas Gregor 1475718292f2SDouglas Gregor case tok::eof: 1476718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 1477718292f2SDouglas Gregor break; 1478718292f2SDouglas Gregor 1479718292f2SDouglas Gregor case tok::l_brace: 1480718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 1481718292f2SDouglas Gregor break; 1482718292f2SDouglas Gregor 1483a686e1b0SDouglas Gregor case tok::l_square: 1484a686e1b0SDouglas Gregor Tok.Kind = MMToken::LSquare; 1485a686e1b0SDouglas Gregor break; 1486a686e1b0SDouglas Gregor 14872b82c2a5SDouglas Gregor case tok::period: 14882b82c2a5SDouglas Gregor Tok.Kind = MMToken::Period; 14892b82c2a5SDouglas Gregor break; 14902b82c2a5SDouglas Gregor 1491718292f2SDouglas Gregor case tok::r_brace: 1492718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 1493718292f2SDouglas Gregor break; 1494718292f2SDouglas Gregor 1495a686e1b0SDouglas Gregor case tok::r_square: 1496a686e1b0SDouglas Gregor Tok.Kind = MMToken::RSquare; 1497a686e1b0SDouglas Gregor break; 1498a686e1b0SDouglas Gregor 14992b82c2a5SDouglas Gregor case tok::star: 15002b82c2a5SDouglas Gregor Tok.Kind = MMToken::Star; 15012b82c2a5SDouglas Gregor break; 15022b82c2a5SDouglas Gregor 1503a3feee2aSRichard Smith case tok::exclaim: 1504a3feee2aSRichard Smith Tok.Kind = MMToken::Exclaim; 1505a3feee2aSRichard Smith break; 1506a3feee2aSRichard Smith 1507718292f2SDouglas Gregor case tok::string_literal: { 1508d67aea28SRichard Smith if (LToken.hasUDSuffix()) { 1509d67aea28SRichard Smith Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl); 1510d67aea28SRichard Smith HadError = true; 1511d67aea28SRichard Smith goto retry; 1512d67aea28SRichard Smith } 1513d67aea28SRichard Smith 1514718292f2SDouglas Gregor // Parse the string literal. 1515718292f2SDouglas Gregor LangOptions LangOpts; 15169d5583efSCraig Topper StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target); 1517718292f2SDouglas Gregor if (StringLiteral.hadError) 1518718292f2SDouglas Gregor goto retry; 1519718292f2SDouglas Gregor 1520718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 1521718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 1522718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 1523718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 1524718292f2SDouglas Gregor Saved[Length] = 0; 1525718292f2SDouglas Gregor 1526718292f2SDouglas Gregor // Form the token. 1527718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 1528718292f2SDouglas Gregor Tok.StringData = Saved; 1529718292f2SDouglas Gregor Tok.StringLength = Length; 1530718292f2SDouglas Gregor break; 1531718292f2SDouglas Gregor } 1532718292f2SDouglas Gregor 1533040e1266SRichard Smith case tok::numeric_constant: { 1534040e1266SRichard Smith // We don't support any suffixes or other complications. 1535040e1266SRichard Smith SmallString<32> SpellingBuffer; 1536040e1266SRichard Smith SpellingBuffer.resize(LToken.getLength() + 1); 1537040e1266SRichard Smith const char *Start = SpellingBuffer.data(); 1538040e1266SRichard Smith unsigned Length = 1539040e1266SRichard Smith Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts()); 1540040e1266SRichard Smith uint64_t Value; 1541040e1266SRichard Smith if (StringRef(Start, Length).getAsInteger(0, Value)) { 1542040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1543040e1266SRichard Smith HadError = true; 1544040e1266SRichard Smith goto retry; 1545040e1266SRichard Smith } 1546040e1266SRichard Smith 1547040e1266SRichard Smith Tok.Kind = MMToken::IntegerLiteral; 1548040e1266SRichard Smith Tok.IntegerValue = Value; 1549040e1266SRichard Smith break; 1550040e1266SRichard Smith } 1551040e1266SRichard Smith 1552718292f2SDouglas Gregor case tok::comment: 1553718292f2SDouglas Gregor goto retry; 1554718292f2SDouglas Gregor 15558128f332SRichard Smith case tok::hash: 15568128f332SRichard Smith // A module map can be terminated prematurely by 15578128f332SRichard Smith // #pragma clang module contents 15588128f332SRichard Smith // When building the module, we'll treat the rest of the file as the 15598128f332SRichard Smith // contents of the module. 15608128f332SRichard Smith { 15618128f332SRichard Smith auto NextIsIdent = [&](StringRef Str) -> bool { 15628128f332SRichard Smith L.LexFromRawLexer(LToken); 15638128f332SRichard Smith return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) && 15648128f332SRichard Smith LToken.getRawIdentifier() == Str; 15658128f332SRichard Smith }; 15668128f332SRichard Smith if (NextIsIdent("pragma") && NextIsIdent("clang") && 15678128f332SRichard Smith NextIsIdent("module") && NextIsIdent("contents")) { 15688128f332SRichard Smith Tok.Kind = MMToken::EndOfFile; 15698128f332SRichard Smith break; 15708128f332SRichard Smith } 15718128f332SRichard Smith } 15728128f332SRichard Smith LLVM_FALLTHROUGH; 15738128f332SRichard Smith 1574718292f2SDouglas Gregor default: 15758128f332SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1576718292f2SDouglas Gregor HadError = true; 1577718292f2SDouglas Gregor goto retry; 1578718292f2SDouglas Gregor } 1579718292f2SDouglas Gregor 1580718292f2SDouglas Gregor return Result; 1581718292f2SDouglas Gregor } 1582718292f2SDouglas Gregor 1583718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 1584718292f2SDouglas Gregor unsigned braceDepth = 0; 1585a686e1b0SDouglas Gregor unsigned squareDepth = 0; 1586718292f2SDouglas Gregor do { 1587718292f2SDouglas Gregor switch (Tok.Kind) { 1588718292f2SDouglas Gregor case MMToken::EndOfFile: 1589718292f2SDouglas Gregor return; 1590718292f2SDouglas Gregor 1591718292f2SDouglas Gregor case MMToken::LBrace: 1592a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1593718292f2SDouglas Gregor return; 1594718292f2SDouglas Gregor 1595718292f2SDouglas Gregor ++braceDepth; 1596718292f2SDouglas Gregor break; 1597718292f2SDouglas Gregor 1598a686e1b0SDouglas Gregor case MMToken::LSquare: 1599a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1600a686e1b0SDouglas Gregor return; 1601a686e1b0SDouglas Gregor 1602a686e1b0SDouglas Gregor ++squareDepth; 1603a686e1b0SDouglas Gregor break; 1604a686e1b0SDouglas Gregor 1605718292f2SDouglas Gregor case MMToken::RBrace: 1606718292f2SDouglas Gregor if (braceDepth > 0) 1607718292f2SDouglas Gregor --braceDepth; 1608718292f2SDouglas Gregor else if (Tok.is(K)) 1609718292f2SDouglas Gregor return; 1610718292f2SDouglas Gregor break; 1611718292f2SDouglas Gregor 1612a686e1b0SDouglas Gregor case MMToken::RSquare: 1613a686e1b0SDouglas Gregor if (squareDepth > 0) 1614a686e1b0SDouglas Gregor --squareDepth; 1615a686e1b0SDouglas Gregor else if (Tok.is(K)) 1616a686e1b0SDouglas Gregor return; 1617a686e1b0SDouglas Gregor break; 1618a686e1b0SDouglas Gregor 1619718292f2SDouglas Gregor default: 1620a686e1b0SDouglas Gregor if (braceDepth == 0 && squareDepth == 0 && Tok.is(K)) 1621718292f2SDouglas Gregor return; 1622718292f2SDouglas Gregor break; 1623718292f2SDouglas Gregor } 1624718292f2SDouglas Gregor 1625718292f2SDouglas Gregor consumeToken(); 1626718292f2SDouglas Gregor } while (true); 1627718292f2SDouglas Gregor } 1628718292f2SDouglas Gregor 16299fc8faf9SAdrian Prantl /// Parse a module-id. 1630e7ab3669SDouglas Gregor /// 1631e7ab3669SDouglas Gregor /// module-id: 1632e7ab3669SDouglas Gregor /// identifier 1633e7ab3669SDouglas Gregor /// identifier '.' module-id 1634e7ab3669SDouglas Gregor /// 1635e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise. 1636e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) { 1637e7ab3669SDouglas Gregor Id.clear(); 1638e7ab3669SDouglas Gregor do { 16393cd34c76SDaniel Jasper if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) { 1640e7ab3669SDouglas Gregor Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation())); 1641e7ab3669SDouglas Gregor consumeToken(); 1642e7ab3669SDouglas Gregor } else { 1643e7ab3669SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 1644e7ab3669SDouglas Gregor return true; 1645e7ab3669SDouglas Gregor } 1646e7ab3669SDouglas Gregor 1647e7ab3669SDouglas Gregor if (!Tok.is(MMToken::Period)) 1648e7ab3669SDouglas Gregor break; 1649e7ab3669SDouglas Gregor 1650e7ab3669SDouglas Gregor consumeToken(); 1651e7ab3669SDouglas Gregor } while (true); 1652e7ab3669SDouglas Gregor 1653e7ab3669SDouglas Gregor return false; 1654e7ab3669SDouglas Gregor } 1655e7ab3669SDouglas Gregor 1656a686e1b0SDouglas Gregor namespace { 1657afd1b1c9SEugene Zelenko 16589fc8faf9SAdrian Prantl /// Enumerates the known attributes. 1659a686e1b0SDouglas Gregor enum AttributeKind { 16609fc8faf9SAdrian Prantl /// An unknown attribute. 1661a686e1b0SDouglas Gregor AT_unknown, 1662afd1b1c9SEugene Zelenko 16639fc8faf9SAdrian Prantl /// The 'system' attribute. 166435b13eceSDouglas Gregor AT_system, 1665afd1b1c9SEugene Zelenko 16669fc8faf9SAdrian Prantl /// The 'extern_c' attribute. 166777944868SRichard Smith AT_extern_c, 1668afd1b1c9SEugene Zelenko 16699fc8faf9SAdrian Prantl /// The 'exhaustive' attribute. 1670ed84df00SBruno Cardoso Lopes AT_exhaustive, 1671afd1b1c9SEugene Zelenko 16729fc8faf9SAdrian Prantl /// The 'no_undeclared_includes' attribute. 1673ed84df00SBruno Cardoso Lopes AT_no_undeclared_includes 1674a686e1b0SDouglas Gregor }; 1675afd1b1c9SEugene Zelenko 1676afd1b1c9SEugene Zelenko } // namespace 1677a686e1b0SDouglas Gregor 167829729919SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra 167929729919SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH 168029729919SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written 168129729919SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits. 16825f11e128SBruno Cardoso Lopes void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc, 16835f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc) { 168429729919SBruno Cardoso Lopes auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical, 16857d29486dSBruno Cardoso Lopes const Module *M, SourceRange ReplLoc) { 168629729919SBruno Cardoso Lopes auto D = Diags.Report(ActiveModule->DefinitionLoc, 168729729919SBruno Cardoso Lopes diag::note_mmap_rename_top_level_private_module); 168829729919SBruno Cardoso Lopes D << BadName << M->Name; 16897d29486dSBruno Cardoso Lopes D << FixItHint::CreateReplacement(ReplLoc, Canonical); 169029729919SBruno Cardoso Lopes }; 169129729919SBruno Cardoso Lopes 169229729919SBruno Cardoso Lopes for (auto E = Map.module_begin(); E != Map.module_end(); ++E) { 169329729919SBruno Cardoso Lopes auto const *M = E->getValue(); 169429729919SBruno Cardoso Lopes if (M->Directory != ActiveModule->Directory) 169529729919SBruno Cardoso Lopes continue; 169629729919SBruno Cardoso Lopes 169729729919SBruno Cardoso Lopes SmallString<128> FullName(ActiveModule->getFullModuleName()); 169829729919SBruno Cardoso Lopes if (!FullName.startswith(M->Name) && !FullName.endswith("Private")) 169929729919SBruno Cardoso Lopes continue; 17005f11e128SBruno Cardoso Lopes SmallString<128> FixedPrivModDecl; 170129729919SBruno Cardoso Lopes SmallString<128> Canonical(M->Name); 170229729919SBruno Cardoso Lopes Canonical.append("_Private"); 170329729919SBruno Cardoso Lopes 170429729919SBruno Cardoso Lopes // Foo.Private -> Foo_Private 170529729919SBruno Cardoso Lopes if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent && 170629729919SBruno Cardoso Lopes M->Name == ActiveModule->Parent->Name) { 170729729919SBruno Cardoso Lopes Diags.Report(ActiveModule->DefinitionLoc, 170829729919SBruno Cardoso Lopes diag::warn_mmap_mismatched_private_submodule) 170929729919SBruno Cardoso Lopes << FullName; 17105f11e128SBruno Cardoso Lopes 17115f11e128SBruno Cardoso Lopes SourceLocation FixItInitBegin = CurrModuleDeclLoc; 17125f11e128SBruno Cardoso Lopes if (FrameworkLoc.isValid()) 17135f11e128SBruno Cardoso Lopes FixItInitBegin = FrameworkLoc; 17145f11e128SBruno Cardoso Lopes if (ExplicitLoc.isValid()) 17155f11e128SBruno Cardoso Lopes FixItInitBegin = ExplicitLoc; 17165f11e128SBruno Cardoso Lopes 17175f11e128SBruno Cardoso Lopes if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework) 17185f11e128SBruno Cardoso Lopes FixedPrivModDecl.append("framework "); 17195f11e128SBruno Cardoso Lopes FixedPrivModDecl.append("module "); 17205f11e128SBruno Cardoso Lopes FixedPrivModDecl.append(Canonical); 17215f11e128SBruno Cardoso Lopes 17225f11e128SBruno Cardoso Lopes GenNoteAndFixIt(FullName, FixedPrivModDecl, M, 17235f11e128SBruno Cardoso Lopes SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc)); 172429729919SBruno Cardoso Lopes continue; 172529729919SBruno Cardoso Lopes } 172629729919SBruno Cardoso Lopes 172729729919SBruno Cardoso Lopes // FooPrivate and whatnots -> Foo_Private 172829729919SBruno Cardoso Lopes if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name && 172929729919SBruno Cardoso Lopes ActiveModule->Name != Canonical) { 173029729919SBruno Cardoso Lopes Diags.Report(ActiveModule->DefinitionLoc, 173129729919SBruno Cardoso Lopes diag::warn_mmap_mismatched_private_module_name) 173229729919SBruno Cardoso Lopes << ActiveModule->Name; 17337d29486dSBruno Cardoso Lopes GenNoteAndFixIt(ActiveModule->Name, Canonical, M, 17347d29486dSBruno Cardoso Lopes SourceRange(ActiveModule->DefinitionLoc)); 173529729919SBruno Cardoso Lopes } 173629729919SBruno Cardoso Lopes } 173729729919SBruno Cardoso Lopes } 173829729919SBruno Cardoso Lopes 17399fc8faf9SAdrian Prantl /// Parse a module declaration. 1740718292f2SDouglas Gregor /// 1741718292f2SDouglas Gregor /// module-declaration: 174297292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 1743a686e1b0SDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt] 1744a686e1b0SDouglas Gregor /// { module-member* } 1745a686e1b0SDouglas Gregor /// 1746718292f2SDouglas Gregor /// module-member: 17471fb5c3a6SDouglas Gregor /// requires-declaration 1748718292f2SDouglas Gregor /// header-declaration 1749e7ab3669SDouglas Gregor /// submodule-declaration 17502b82c2a5SDouglas Gregor /// export-declaration 1751f0b11de2SDouglas Gregor /// export-as-declaration 17526ddfca91SDouglas Gregor /// link-declaration 175373441091SDouglas Gregor /// 175473441091SDouglas Gregor /// submodule-declaration: 175573441091SDouglas Gregor /// module-declaration 175673441091SDouglas Gregor /// inferred-submodule-declaration 1757718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 1758755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 175997292843SDaniel Jasper Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword)); 176097292843SDaniel Jasper if (Tok.is(MMToken::ExternKeyword)) { 176197292843SDaniel Jasper parseExternModuleDecl(); 176297292843SDaniel Jasper return; 176397292843SDaniel Jasper } 176497292843SDaniel Jasper 1765f2161a70SDouglas Gregor // Parse 'explicit' or 'framework' keyword, if present. 1766e7ab3669SDouglas Gregor SourceLocation ExplicitLoc; 17675f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc; 1768718292f2SDouglas Gregor bool Explicit = false; 1769f2161a70SDouglas Gregor bool Framework = false; 1770755b2055SDouglas Gregor 1771f2161a70SDouglas Gregor // Parse 'explicit' keyword, if present. 1772f2161a70SDouglas Gregor if (Tok.is(MMToken::ExplicitKeyword)) { 1773e7ab3669SDouglas Gregor ExplicitLoc = consumeToken(); 1774f2161a70SDouglas Gregor Explicit = true; 1775f2161a70SDouglas Gregor } 1776f2161a70SDouglas Gregor 1777f2161a70SDouglas Gregor // Parse 'framework' keyword, if present. 1778755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 17795f11e128SBruno Cardoso Lopes FrameworkLoc = consumeToken(); 1780755b2055SDouglas Gregor Framework = true; 1781755b2055SDouglas Gregor } 1782718292f2SDouglas Gregor 1783718292f2SDouglas Gregor // Parse 'module' keyword. 1784718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 1785d6343c99SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 1786718292f2SDouglas Gregor consumeToken(); 1787718292f2SDouglas Gregor HadError = true; 1788718292f2SDouglas Gregor return; 1789718292f2SDouglas Gregor } 17909f6020bcSBruno Cardoso Lopes CurrModuleDeclLoc = consumeToken(); // 'module' keyword 1791718292f2SDouglas Gregor 179273441091SDouglas Gregor // If we have a wildcard for the module name, this is an inferred submodule. 179373441091SDouglas Gregor // Parse it. 179473441091SDouglas Gregor if (Tok.is(MMToken::Star)) 17959194a91dSDouglas Gregor return parseInferredModuleDecl(Framework, Explicit); 179673441091SDouglas Gregor 1797718292f2SDouglas Gregor // Parse the module name. 1798e7ab3669SDouglas Gregor ModuleId Id; 1799e7ab3669SDouglas Gregor if (parseModuleId(Id)) { 1800718292f2SDouglas Gregor HadError = true; 1801718292f2SDouglas Gregor return; 1802718292f2SDouglas Gregor } 1803e7ab3669SDouglas Gregor 1804e7ab3669SDouglas Gregor if (ActiveModule) { 1805e7ab3669SDouglas Gregor if (Id.size() > 1) { 1806e7ab3669SDouglas Gregor Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id) 1807e7ab3669SDouglas Gregor << SourceRange(Id.front().second, Id.back().second); 1808e7ab3669SDouglas Gregor 1809e7ab3669SDouglas Gregor HadError = true; 1810e7ab3669SDouglas Gregor return; 1811e7ab3669SDouglas Gregor } 1812e7ab3669SDouglas Gregor } else if (Id.size() == 1 && Explicit) { 1813e7ab3669SDouglas Gregor // Top-level modules can't be explicit. 1814e7ab3669SDouglas Gregor Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level); 1815e7ab3669SDouglas Gregor Explicit = false; 1816e7ab3669SDouglas Gregor ExplicitLoc = SourceLocation(); 1817e7ab3669SDouglas Gregor HadError = true; 1818e7ab3669SDouglas Gregor } 1819e7ab3669SDouglas Gregor 1820e7ab3669SDouglas Gregor Module *PreviousActiveModule = ActiveModule; 1821e7ab3669SDouglas Gregor if (Id.size() > 1) { 1822e7ab3669SDouglas Gregor // This module map defines a submodule. Go find the module of which it 1823e7ab3669SDouglas Gregor // is a submodule. 1824d2d442caSCraig Topper ActiveModule = nullptr; 18254b8a9e95SBen Langmuir const Module *TopLevelModule = nullptr; 1826e7ab3669SDouglas Gregor for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) { 1827e7ab3669SDouglas Gregor if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) { 18284b8a9e95SBen Langmuir if (I == 0) 18294b8a9e95SBen Langmuir TopLevelModule = Next; 1830e7ab3669SDouglas Gregor ActiveModule = Next; 1831e7ab3669SDouglas Gregor continue; 1832e7ab3669SDouglas Gregor } 1833e7ab3669SDouglas Gregor 1834e7ab3669SDouglas Gregor if (ActiveModule) { 1835e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified) 18365b5d21eaSRichard Smith << Id[I].first 18375b5d21eaSRichard Smith << ActiveModule->getTopLevelModule()->getFullModuleName(); 1838e7ab3669SDouglas Gregor } else { 1839e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_expected_module_name); 1840e7ab3669SDouglas Gregor } 1841e7ab3669SDouglas Gregor HadError = true; 1842e7ab3669SDouglas Gregor return; 1843e7ab3669SDouglas Gregor } 18444b8a9e95SBen Langmuir 18454b8a9e95SBen Langmuir if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) { 18464b8a9e95SBen Langmuir assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) && 18474b8a9e95SBen Langmuir "submodule defined in same file as 'module *' that allowed its " 18484b8a9e95SBen Langmuir "top-level module"); 18494b8a9e95SBen Langmuir Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile); 18504b8a9e95SBen Langmuir } 1851e7ab3669SDouglas Gregor } 1852e7ab3669SDouglas Gregor 1853e7ab3669SDouglas Gregor StringRef ModuleName = Id.back().first; 1854e7ab3669SDouglas Gregor SourceLocation ModuleNameLoc = Id.back().second; 1855718292f2SDouglas Gregor 1856a686e1b0SDouglas Gregor // Parse the optional attribute list. 18574442605fSBill Wendling Attributes Attrs; 18585d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 18595d29dee0SDavide Italiano return; 18605d29dee0SDavide Italiano 1861718292f2SDouglas Gregor // Parse the opening brace. 1862718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 1863718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 1864718292f2SDouglas Gregor << ModuleName; 1865718292f2SDouglas Gregor HadError = true; 1866718292f2SDouglas Gregor return; 1867718292f2SDouglas Gregor } 1868718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 1869718292f2SDouglas Gregor 1870718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 18718587dfd9SBruno Cardoso Lopes Module *ShadowingModule = nullptr; 1872eb90e830SDouglas Gregor if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { 18734a3751ffSRichard Smith // We might see a (re)definition of a module that we already have a 18744a3751ffSRichard Smith // definition for in two cases: 18754a3751ffSRichard Smith // - If we loaded one definition from an AST file and we've just found a 18764a3751ffSRichard Smith // corresponding definition in a module map file, or 18774a3751ffSRichard Smith bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid(); 18784a3751ffSRichard Smith // - If we're building a (preprocessed) module and we've just loaded the 18794a3751ffSRichard Smith // module map file from which it was created. 18804a3751ffSRichard Smith bool ParsedAsMainInput = 18814a3751ffSRichard Smith Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap && 18824a3751ffSRichard Smith Map.LangOpts.CurrentModule == ModuleName && 18834a3751ffSRichard Smith SourceMgr.getDecomposedLoc(ModuleNameLoc).first != 18844a3751ffSRichard Smith SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first; 18854a3751ffSRichard Smith if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) { 1886fcc54a3bSDouglas Gregor // Skip the module definition. 1887fcc54a3bSDouglas Gregor skipUntil(MMToken::RBrace); 1888fcc54a3bSDouglas Gregor if (Tok.is(MMToken::RBrace)) 1889fcc54a3bSDouglas Gregor consumeToken(); 1890fcc54a3bSDouglas Gregor else { 1891fcc54a3bSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 1892fcc54a3bSDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 1893fcc54a3bSDouglas Gregor HadError = true; 1894fcc54a3bSDouglas Gregor } 1895fcc54a3bSDouglas Gregor return; 1896fcc54a3bSDouglas Gregor } 1897fcc54a3bSDouglas Gregor 1898c192d194SBruno Cardoso Lopes if (!Existing->Parent && Map.mayShadowNewModule(Existing)) { 18998587dfd9SBruno Cardoso Lopes ShadowingModule = Existing; 19008587dfd9SBruno Cardoso Lopes } else { 19018587dfd9SBruno Cardoso Lopes // This is not a shawdowed module decl, it is an illegal redefinition. 1902718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 1903718292f2SDouglas Gregor << ModuleName; 1904eb90e830SDouglas Gregor Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition); 1905718292f2SDouglas Gregor 1906718292f2SDouglas Gregor // Skip the module definition. 1907718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 1908718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 1909718292f2SDouglas Gregor consumeToken(); 1910718292f2SDouglas Gregor 1911718292f2SDouglas Gregor HadError = true; 1912718292f2SDouglas Gregor return; 1913718292f2SDouglas Gregor } 19148587dfd9SBruno Cardoso Lopes } 1915718292f2SDouglas Gregor 1916718292f2SDouglas Gregor // Start defining this module. 19178587dfd9SBruno Cardoso Lopes if (ShadowingModule) { 19188587dfd9SBruno Cardoso Lopes ActiveModule = 19198587dfd9SBruno Cardoso Lopes Map.createShadowedModule(ModuleName, Framework, ShadowingModule); 19208587dfd9SBruno Cardoso Lopes } else { 1921c192d194SBruno Cardoso Lopes ActiveModule = 1922c192d194SBruno Cardoso Lopes Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit) 19238587dfd9SBruno Cardoso Lopes .first; 19248587dfd9SBruno Cardoso Lopes } 19258587dfd9SBruno Cardoso Lopes 1926eb90e830SDouglas Gregor ActiveModule->DefinitionLoc = ModuleNameLoc; 1927963c5535SDouglas Gregor if (Attrs.IsSystem || IsSystem) 1928a686e1b0SDouglas Gregor ActiveModule->IsSystem = true; 192977944868SRichard Smith if (Attrs.IsExternC) 193077944868SRichard Smith ActiveModule->IsExternC = true; 1931ed84df00SBruno Cardoso Lopes if (Attrs.NoUndeclaredIncludes || 1932ed84df00SBruno Cardoso Lopes (!ActiveModule->Parent && ModuleName == "Darwin")) 1933ed84df00SBruno Cardoso Lopes ActiveModule->NoUndeclaredIncludes = true; 19343c1a41adSRichard Smith ActiveModule->Directory = Directory; 1935718292f2SDouglas Gregor 193690b0a1fcSJordan Rose StringRef MapFileName(ModuleMapFile->getName()); 193790b0a1fcSJordan Rose if (MapFileName.endswith("module.private.modulemap") || 193890b0a1fcSJordan Rose MapFileName.endswith("module_private.map")) { 193990b0a1fcSJordan Rose ActiveModule->ModuleMapIsPrivate = true; 194090b0a1fcSJordan Rose } 194129729919SBruno Cardoso Lopes 194229729919SBruno Cardoso Lopes // Private modules named as FooPrivate, Foo.Private or similar are likely a 194329729919SBruno Cardoso Lopes // user error; provide warnings, notes and fixits to direct users to use 194429729919SBruno Cardoso Lopes // Foo_Private instead. 194529729919SBruno Cardoso Lopes SourceLocation StartLoc = 194629729919SBruno Cardoso Lopes SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()); 194729729919SBruno Cardoso Lopes if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && 194829729919SBruno Cardoso Lopes !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule, 194929729919SBruno Cardoso Lopes StartLoc) && 195029729919SBruno Cardoso Lopes !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name, 195129729919SBruno Cardoso Lopes StartLoc) && 195290b0a1fcSJordan Rose ActiveModule->ModuleMapIsPrivate) 19535f11e128SBruno Cardoso Lopes diagnosePrivateModules(ExplicitLoc, FrameworkLoc); 19544d867640SGraydon Hoare 1955718292f2SDouglas Gregor bool Done = false; 1956718292f2SDouglas Gregor do { 1957718292f2SDouglas Gregor switch (Tok.Kind) { 1958718292f2SDouglas Gregor case MMToken::EndOfFile: 1959718292f2SDouglas Gregor case MMToken::RBrace: 1960718292f2SDouglas Gregor Done = true; 1961718292f2SDouglas Gregor break; 1962718292f2SDouglas Gregor 196335b13eceSDouglas Gregor case MMToken::ConfigMacros: 196435b13eceSDouglas Gregor parseConfigMacros(); 196535b13eceSDouglas Gregor break; 196635b13eceSDouglas Gregor 1967fb912657SDouglas Gregor case MMToken::Conflict: 1968fb912657SDouglas Gregor parseConflict(); 1969fb912657SDouglas Gregor break; 1970fb912657SDouglas Gregor 1971718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 197297292843SDaniel Jasper case MMToken::ExternKeyword: 1973f2161a70SDouglas Gregor case MMToken::FrameworkKeyword: 1974718292f2SDouglas Gregor case MMToken::ModuleKeyword: 1975718292f2SDouglas Gregor parseModuleDecl(); 1976718292f2SDouglas Gregor break; 1977718292f2SDouglas Gregor 19782b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 19792b82c2a5SDouglas Gregor parseExportDecl(); 19802b82c2a5SDouglas Gregor break; 19812b82c2a5SDouglas Gregor 1982f0b11de2SDouglas Gregor case MMToken::ExportAsKeyword: 1983f0b11de2SDouglas Gregor parseExportAsDecl(); 1984f0b11de2SDouglas Gregor break; 1985f0b11de2SDouglas Gregor 1986ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 1987ba7f2f71SDaniel Jasper parseUseDecl(); 1988ba7f2f71SDaniel Jasper break; 1989ba7f2f71SDaniel Jasper 19901fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 19911fb5c3a6SDouglas Gregor parseRequiresDecl(); 19921fb5c3a6SDouglas Gregor break; 19931fb5c3a6SDouglas Gregor 1994202210b3SRichard Smith case MMToken::TextualKeyword: 1995202210b3SRichard Smith parseHeaderDecl(MMToken::TextualKeyword, consumeToken()); 1996306d8920SRichard Smith break; 1997306d8920SRichard Smith 1998524e33e1SDouglas Gregor case MMToken::UmbrellaKeyword: { 1999524e33e1SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 2000524e33e1SDouglas Gregor if (Tok.is(MMToken::HeaderKeyword)) 2001b53e5483SLawrence Crowl parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc); 2002524e33e1SDouglas Gregor else 2003524e33e1SDouglas Gregor parseUmbrellaDirDecl(UmbrellaLoc); 2004718292f2SDouglas Gregor break; 2005524e33e1SDouglas Gregor } 2006718292f2SDouglas Gregor 2007202210b3SRichard Smith case MMToken::ExcludeKeyword: 2008202210b3SRichard Smith parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken()); 200959527666SDouglas Gregor break; 201059527666SDouglas Gregor 2011202210b3SRichard Smith case MMToken::PrivateKeyword: 2012202210b3SRichard Smith parseHeaderDecl(MMToken::PrivateKeyword, consumeToken()); 2013b53e5483SLawrence Crowl break; 2014b53e5483SLawrence Crowl 2015322f633cSDouglas Gregor case MMToken::HeaderKeyword: 2016202210b3SRichard Smith parseHeaderDecl(MMToken::HeaderKeyword, consumeToken()); 2017718292f2SDouglas Gregor break; 2018718292f2SDouglas Gregor 20196ddfca91SDouglas Gregor case MMToken::LinkKeyword: 20206ddfca91SDouglas Gregor parseLinkDecl(); 20216ddfca91SDouglas Gregor break; 20226ddfca91SDouglas Gregor 2023718292f2SDouglas Gregor default: 2024718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 2025718292f2SDouglas Gregor consumeToken(); 2026718292f2SDouglas Gregor break; 2027718292f2SDouglas Gregor } 2028718292f2SDouglas Gregor } while (!Done); 2029718292f2SDouglas Gregor 2030718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 2031718292f2SDouglas Gregor consumeToken(); 2032718292f2SDouglas Gregor else { 2033718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 2034718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 2035718292f2SDouglas Gregor HadError = true; 2036718292f2SDouglas Gregor } 2037718292f2SDouglas Gregor 203811dfe6feSDouglas Gregor // If the active module is a top-level framework, and there are no link 203911dfe6feSDouglas Gregor // libraries, automatically link against the framework. 204011dfe6feSDouglas Gregor if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() && 204111dfe6feSDouglas Gregor ActiveModule->LinkLibraries.empty()) { 204211dfe6feSDouglas Gregor inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager()); 204311dfe6feSDouglas Gregor } 204411dfe6feSDouglas Gregor 2045ec8c9752SBen Langmuir // If the module meets all requirements but is still unavailable, mark the 2046ec8c9752SBen Langmuir // whole tree as unavailable to prevent it from building. 2047ec8c9752SBen Langmuir if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement && 2048ec8c9752SBen Langmuir ActiveModule->Parent) { 2049ec8c9752SBen Langmuir ActiveModule->getTopLevelModule()->markUnavailable(); 2050ec8c9752SBen Langmuir ActiveModule->getTopLevelModule()->MissingHeaders.append( 2051ec8c9752SBen Langmuir ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end()); 2052ec8c9752SBen Langmuir } 2053ec8c9752SBen Langmuir 2054e7ab3669SDouglas Gregor // We're done parsing this module. Pop back to the previous module. 2055e7ab3669SDouglas Gregor ActiveModule = PreviousActiveModule; 2056718292f2SDouglas Gregor } 2057718292f2SDouglas Gregor 20589fc8faf9SAdrian Prantl /// Parse an extern module declaration. 205997292843SDaniel Jasper /// 206097292843SDaniel Jasper /// extern module-declaration: 206197292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 206297292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() { 206397292843SDaniel Jasper assert(Tok.is(MMToken::ExternKeyword)); 2064ae6df27eSRichard Smith SourceLocation ExternLoc = consumeToken(); // 'extern' keyword 206597292843SDaniel Jasper 206697292843SDaniel Jasper // Parse 'module' keyword. 206797292843SDaniel Jasper if (!Tok.is(MMToken::ModuleKeyword)) { 206897292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 206997292843SDaniel Jasper consumeToken(); 207097292843SDaniel Jasper HadError = true; 207197292843SDaniel Jasper return; 207297292843SDaniel Jasper } 207397292843SDaniel Jasper consumeToken(); // 'module' keyword 207497292843SDaniel Jasper 207597292843SDaniel Jasper // Parse the module name. 207697292843SDaniel Jasper ModuleId Id; 207797292843SDaniel Jasper if (parseModuleId(Id)) { 207897292843SDaniel Jasper HadError = true; 207997292843SDaniel Jasper return; 208097292843SDaniel Jasper } 208197292843SDaniel Jasper 208297292843SDaniel Jasper // Parse the referenced module map file name. 208397292843SDaniel Jasper if (!Tok.is(MMToken::StringLiteral)) { 208497292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file); 208597292843SDaniel Jasper HadError = true; 208697292843SDaniel Jasper return; 208797292843SDaniel Jasper } 208897292843SDaniel Jasper std::string FileName = Tok.getString(); 208997292843SDaniel Jasper consumeToken(); // filename 209097292843SDaniel Jasper 209197292843SDaniel Jasper StringRef FileNameRef = FileName; 209297292843SDaniel Jasper SmallString<128> ModuleMapFileName; 209397292843SDaniel Jasper if (llvm::sys::path::is_relative(FileNameRef)) { 209497292843SDaniel Jasper ModuleMapFileName += Directory->getName(); 209597292843SDaniel Jasper llvm::sys::path::append(ModuleMapFileName, FileName); 209692e1b62dSYaron Keren FileNameRef = ModuleMapFileName; 209797292843SDaniel Jasper } 209897292843SDaniel Jasper if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef)) 20999acb99e3SRichard Smith Map.parseModuleMapFile( 21009acb99e3SRichard Smith File, /*IsSystem=*/false, 21019acb99e3SRichard Smith Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd 21029acb99e3SRichard Smith ? Directory 21038128f332SRichard Smith : File->getDir(), 2104c192d194SBruno Cardoso Lopes FileID(), nullptr, ExternLoc); 210597292843SDaniel Jasper } 210697292843SDaniel Jasper 21077ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M. 21087ff29148SBen Langmuir /// 21097ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system 21107ff29148SBen Langmuir /// module map files: 21117ff29148SBen Langmuir /// 21127ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which 21137ff29148SBen Langmuir /// should really be mapped to 'textual' now that we have this feature. We 21147ff29148SBen Langmuir /// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to 21157ff29148SBen Langmuir /// true. Later, this bit will be used to map all the headers inside this 21167ff29148SBen Langmuir /// module to 'textual'. 21177ff29148SBen Langmuir /// 21187ff29148SBen Langmuir /// This affects Darwin.C.excluded (for assert.h) and Tcl.Private. 21197ff29148SBen Langmuir /// 21207ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement 21217ff29148SBen Langmuir /// was never correct and causes issues now that we check it, so drop it. 21227ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature, 21237ff29148SBen Langmuir bool &IsRequiresExcludedHack) { 21248013e81dSBenjamin Kramer if (Feature == "excluded" && 21258013e81dSBenjamin Kramer (M->fullModuleNameIs({"Darwin", "C", "excluded"}) || 21268013e81dSBenjamin Kramer M->fullModuleNameIs({"Tcl", "Private"}))) { 21277ff29148SBen Langmuir IsRequiresExcludedHack = true; 21287ff29148SBen Langmuir return false; 21298013e81dSBenjamin Kramer } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) { 21307ff29148SBen Langmuir return false; 21317ff29148SBen Langmuir } 21327ff29148SBen Langmuir 21337ff29148SBen Langmuir return true; 21347ff29148SBen Langmuir } 21357ff29148SBen Langmuir 21369fc8faf9SAdrian Prantl /// Parse a requires declaration. 21371fb5c3a6SDouglas Gregor /// 21381fb5c3a6SDouglas Gregor /// requires-declaration: 21391fb5c3a6SDouglas Gregor /// 'requires' feature-list 21401fb5c3a6SDouglas Gregor /// 21411fb5c3a6SDouglas Gregor /// feature-list: 2142a3feee2aSRichard Smith /// feature ',' feature-list 2143a3feee2aSRichard Smith /// feature 2144a3feee2aSRichard Smith /// 2145a3feee2aSRichard Smith /// feature: 2146a3feee2aSRichard Smith /// '!'[opt] identifier 21471fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() { 21481fb5c3a6SDouglas Gregor assert(Tok.is(MMToken::RequiresKeyword)); 21491fb5c3a6SDouglas Gregor 21501fb5c3a6SDouglas Gregor // Parse 'requires' keyword. 21511fb5c3a6SDouglas Gregor consumeToken(); 21521fb5c3a6SDouglas Gregor 21531fb5c3a6SDouglas Gregor // Parse the feature-list. 21541fb5c3a6SDouglas Gregor do { 2155a3feee2aSRichard Smith bool RequiredState = true; 2156a3feee2aSRichard Smith if (Tok.is(MMToken::Exclaim)) { 2157a3feee2aSRichard Smith RequiredState = false; 2158a3feee2aSRichard Smith consumeToken(); 2159a3feee2aSRichard Smith } 2160a3feee2aSRichard Smith 21611fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 21621fb5c3a6SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature); 21631fb5c3a6SDouglas Gregor HadError = true; 21641fb5c3a6SDouglas Gregor return; 21651fb5c3a6SDouglas Gregor } 21661fb5c3a6SDouglas Gregor 21671fb5c3a6SDouglas Gregor // Consume the feature name. 21681fb5c3a6SDouglas Gregor std::string Feature = Tok.getString(); 21691fb5c3a6SDouglas Gregor consumeToken(); 21701fb5c3a6SDouglas Gregor 21717ff29148SBen Langmuir bool IsRequiresExcludedHack = false; 21727ff29148SBen Langmuir bool ShouldAddRequirement = 21737ff29148SBen Langmuir shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack); 21747ff29148SBen Langmuir 21757ff29148SBen Langmuir if (IsRequiresExcludedHack) 21767ff29148SBen Langmuir UsesRequiresExcludedHack.insert(ActiveModule); 21777ff29148SBen Langmuir 21787ff29148SBen Langmuir if (ShouldAddRequirement) { 21791fb5c3a6SDouglas Gregor // Add this feature. 21807ff29148SBen Langmuir ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts, 21817ff29148SBen Langmuir *Map.Target); 21827ff29148SBen Langmuir } 21831fb5c3a6SDouglas Gregor 21841fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Comma)) 21851fb5c3a6SDouglas Gregor break; 21861fb5c3a6SDouglas Gregor 21871fb5c3a6SDouglas Gregor // Consume the comma. 21881fb5c3a6SDouglas Gregor consumeToken(); 21891fb5c3a6SDouglas Gregor } while (true); 21901fb5c3a6SDouglas Gregor } 21911fb5c3a6SDouglas Gregor 21929fc8faf9SAdrian Prantl /// Parse a header declaration. 2193718292f2SDouglas Gregor /// 2194718292f2SDouglas Gregor /// header-declaration: 2195306d8920SRichard Smith /// 'textual'[opt] 'header' string-literal 2196202210b3SRichard Smith /// 'private' 'textual'[opt] 'header' string-literal 2197202210b3SRichard Smith /// 'exclude' 'header' string-literal 2198202210b3SRichard Smith /// 'umbrella' 'header' string-literal 2199306d8920SRichard Smith /// 2200306d8920SRichard Smith /// FIXME: Support 'private textual header'. 2201b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, 2202b53e5483SLawrence Crowl SourceLocation LeadingLoc) { 2203202210b3SRichard Smith // We've already consumed the first token. 2204202210b3SRichard Smith ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader; 2205202210b3SRichard Smith if (LeadingToken == MMToken::PrivateKeyword) { 2206202210b3SRichard Smith Role = ModuleMap::PrivateHeader; 2207202210b3SRichard Smith // 'private' may optionally be followed by 'textual'. 2208202210b3SRichard Smith if (Tok.is(MMToken::TextualKeyword)) { 2209202210b3SRichard Smith LeadingToken = Tok.Kind; 22101871ed3dSBenjamin Kramer consumeToken(); 2211202210b3SRichard Smith } 2212202210b3SRichard Smith } 22137ff29148SBen Langmuir 2214202210b3SRichard Smith if (LeadingToken == MMToken::TextualKeyword) 2215202210b3SRichard Smith Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 2216202210b3SRichard Smith 22177ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 22187ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 22197ff29148SBen Langmuir // Module::UsesRequiresExcludedHack). 22207ff29148SBen Langmuir Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 22217ff29148SBen Langmuir } 22227ff29148SBen Langmuir 2223202210b3SRichard Smith if (LeadingToken != MMToken::HeaderKeyword) { 2224202210b3SRichard Smith if (!Tok.is(MMToken::HeaderKeyword)) { 2225202210b3SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2226202210b3SRichard Smith << (LeadingToken == MMToken::PrivateKeyword ? "private" : 2227202210b3SRichard Smith LeadingToken == MMToken::ExcludeKeyword ? "exclude" : 2228202210b3SRichard Smith LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella"); 2229202210b3SRichard Smith return; 2230202210b3SRichard Smith } 2231202210b3SRichard Smith consumeToken(); 2232202210b3SRichard Smith } 2233718292f2SDouglas Gregor 2234718292f2SDouglas Gregor // Parse the header name. 2235718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2236718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2237718292f2SDouglas Gregor << "header"; 2238718292f2SDouglas Gregor HadError = true; 2239718292f2SDouglas Gregor return; 2240718292f2SDouglas Gregor } 22413c1a41adSRichard Smith Module::UnresolvedHeaderDirective Header; 22420761a8a0SDaniel Jasper Header.FileName = Tok.getString(); 22430761a8a0SDaniel Jasper Header.FileNameLoc = consumeToken(); 22441d60987fSRichard Smith Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword; 2245040e1266SRichard Smith Header.Kind = 2246040e1266SRichard Smith (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded 2247040e1266SRichard Smith : Map.headerRoleToKind(Role)); 2248718292f2SDouglas Gregor 2249524e33e1SDouglas Gregor // Check whether we already have an umbrella. 22501d60987fSRichard Smith if (Header.IsUmbrella && ActiveModule->Umbrella) { 22510761a8a0SDaniel Jasper Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) 2252524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2253322f633cSDouglas Gregor HadError = true; 2254322f633cSDouglas Gregor return; 2255322f633cSDouglas Gregor } 2256322f633cSDouglas Gregor 2257040e1266SRichard Smith // If we were given stat information, parse it so we can skip looking for 2258040e1266SRichard Smith // the file. 2259040e1266SRichard Smith if (Tok.is(MMToken::LBrace)) { 2260040e1266SRichard Smith SourceLocation LBraceLoc = consumeToken(); 22613ec6663bSDouglas Gregor 2262040e1266SRichard Smith while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) { 2263040e1266SRichard Smith enum Attribute { Size, ModTime, Unknown }; 2264040e1266SRichard Smith StringRef Str = Tok.getString(); 2265040e1266SRichard Smith SourceLocation Loc = consumeToken(); 2266040e1266SRichard Smith switch (llvm::StringSwitch<Attribute>(Str) 2267040e1266SRichard Smith .Case("size", Size) 2268040e1266SRichard Smith .Case("mtime", ModTime) 2269040e1266SRichard Smith .Default(Unknown)) { 2270040e1266SRichard Smith case Size: 2271040e1266SRichard Smith if (Header.Size) 2272040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2273040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2274040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2275040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2276040e1266SRichard Smith skipUntil(MMToken::RBrace); 2277040e1266SRichard Smith break; 2278040e1266SRichard Smith } 2279040e1266SRichard Smith Header.Size = Tok.getInteger(); 2280040e1266SRichard Smith consumeToken(); 2281040e1266SRichard Smith break; 2282040e1266SRichard Smith 2283040e1266SRichard Smith case ModTime: 2284040e1266SRichard Smith if (Header.ModTime) 2285040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2286040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2287040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2288040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2289040e1266SRichard Smith skipUntil(MMToken::RBrace); 2290040e1266SRichard Smith break; 2291040e1266SRichard Smith } 2292040e1266SRichard Smith Header.ModTime = Tok.getInteger(); 2293040e1266SRichard Smith consumeToken(); 2294040e1266SRichard Smith break; 2295040e1266SRichard Smith 2296040e1266SRichard Smith case Unknown: 2297040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_expected_header_attribute); 2298040e1266SRichard Smith skipUntil(MMToken::RBrace); 2299040e1266SRichard Smith break; 2300040e1266SRichard Smith } 23013ec6663bSDouglas Gregor } 23025257fc63SDouglas Gregor 2303040e1266SRichard Smith if (Tok.is(MMToken::RBrace)) 2304040e1266SRichard Smith consumeToken(); 2305040e1266SRichard Smith else { 2306040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 2307040e1266SRichard Smith Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 2308322f633cSDouglas Gregor HadError = true; 2309322f633cSDouglas Gregor } 23100101b540SHans Wennborg } 231125d50758SRichard Smith 23129f6020bcSBruno Cardoso Lopes bool NeedsFramework = false; 23139f6020bcSBruno Cardoso Lopes Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework); 23149f6020bcSBruno Cardoso Lopes 23159f6020bcSBruno Cardoso Lopes if (NeedsFramework && ActiveModule) 23169f6020bcSBruno Cardoso Lopes Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword) 23179f6020bcSBruno Cardoso Lopes << ActiveModule->getFullModuleName() 23189f6020bcSBruno Cardoso Lopes << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module"); 2319718292f2SDouglas Gregor } 2320718292f2SDouglas Gregor 232141f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A, 232241f81994SBen Langmuir const Module::Header *B) { 232341f81994SBen Langmuir return A->NameAsWritten.compare(B->NameAsWritten); 232441f81994SBen Langmuir } 232541f81994SBen Langmuir 23269fc8faf9SAdrian Prantl /// Parse an umbrella directory declaration. 2327524e33e1SDouglas Gregor /// 2328524e33e1SDouglas Gregor /// umbrella-dir-declaration: 2329524e33e1SDouglas Gregor /// umbrella string-literal 2330524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { 2331524e33e1SDouglas Gregor // Parse the directory name. 2332524e33e1SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2333524e33e1SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2334524e33e1SDouglas Gregor << "umbrella"; 2335524e33e1SDouglas Gregor HadError = true; 2336524e33e1SDouglas Gregor return; 2337524e33e1SDouglas Gregor } 2338524e33e1SDouglas Gregor 2339524e33e1SDouglas Gregor std::string DirName = Tok.getString(); 2340524e33e1SDouglas Gregor SourceLocation DirNameLoc = consumeToken(); 2341524e33e1SDouglas Gregor 2342524e33e1SDouglas Gregor // Check whether we already have an umbrella. 2343524e33e1SDouglas Gregor if (ActiveModule->Umbrella) { 2344524e33e1SDouglas Gregor Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash) 2345524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2346524e33e1SDouglas Gregor HadError = true; 2347524e33e1SDouglas Gregor return; 2348524e33e1SDouglas Gregor } 2349524e33e1SDouglas Gregor 2350524e33e1SDouglas Gregor // Look for this file. 2351d2d442caSCraig Topper const DirectoryEntry *Dir = nullptr; 2352524e33e1SDouglas Gregor if (llvm::sys::path::is_absolute(DirName)) 2353524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(DirName); 2354524e33e1SDouglas Gregor else { 23552c1dd271SDylan Noblesmith SmallString<128> PathName; 2356524e33e1SDouglas Gregor PathName = Directory->getName(); 2357524e33e1SDouglas Gregor llvm::sys::path::append(PathName, DirName); 2358524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(PathName); 2359524e33e1SDouglas Gregor } 2360524e33e1SDouglas Gregor 2361524e33e1SDouglas Gregor if (!Dir) { 2362a0320b97SVassil Vassilev Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found) 2363524e33e1SDouglas Gregor << DirName; 2364524e33e1SDouglas Gregor return; 2365524e33e1SDouglas Gregor } 2366524e33e1SDouglas Gregor 23677ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 23687ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 23697ff29148SBen Langmuir // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the 23707ff29148SBen Langmuir // directory is relatively expensive, in practice this only applies to the 23717ff29148SBen Langmuir // uncommonly used Tcl module on Darwin platforms. 23727ff29148SBen Langmuir std::error_code EC; 23737ff29148SBen Langmuir SmallVector<Module::Header, 6> Headers; 2374b171a59bSBruno Cardoso Lopes vfs::FileSystem &FS = *SourceMgr.getFileManager().getVirtualFileSystem(); 2375b171a59bSBruno Cardoso Lopes for (vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E; 23767ff29148SBen Langmuir I != E && !EC; I.increment(EC)) { 2377*0ae00567SSam McCall if (const FileEntry *FE = SourceMgr.getFileManager().getFile(I->path())) { 23787ff29148SBen Langmuir 2379*0ae00567SSam McCall Module::Header Header = {I->path(), FE}; 23807ff29148SBen Langmuir Headers.push_back(std::move(Header)); 23817ff29148SBen Langmuir } 23827ff29148SBen Langmuir } 23837ff29148SBen Langmuir 23847ff29148SBen Langmuir // Sort header paths so that the pcm doesn't depend on iteration order. 238541f81994SBen Langmuir llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders); 238641f81994SBen Langmuir 23877ff29148SBen Langmuir for (auto &Header : Headers) 23887ff29148SBen Langmuir Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader); 23897ff29148SBen Langmuir return; 23907ff29148SBen Langmuir } 23917ff29148SBen Langmuir 2392524e33e1SDouglas Gregor if (Module *OwningModule = Map.UmbrellaDirs[Dir]) { 2393524e33e1SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 2394524e33e1SDouglas Gregor << OwningModule->getFullModuleName(); 2395524e33e1SDouglas Gregor HadError = true; 2396524e33e1SDouglas Gregor return; 2397524e33e1SDouglas Gregor } 2398524e33e1SDouglas Gregor 2399524e33e1SDouglas Gregor // Record this umbrella directory. 24002b63d15fSRichard Smith Map.setUmbrellaDir(ActiveModule, Dir, DirName); 2401524e33e1SDouglas Gregor } 2402524e33e1SDouglas Gregor 24039fc8faf9SAdrian Prantl /// Parse a module export declaration. 24042b82c2a5SDouglas Gregor /// 24052b82c2a5SDouglas Gregor /// export-declaration: 24062b82c2a5SDouglas Gregor /// 'export' wildcard-module-id 24072b82c2a5SDouglas Gregor /// 24082b82c2a5SDouglas Gregor /// wildcard-module-id: 24092b82c2a5SDouglas Gregor /// identifier 24102b82c2a5SDouglas Gregor /// '*' 24112b82c2a5SDouglas Gregor /// identifier '.' wildcard-module-id 24122b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() { 24132b82c2a5SDouglas Gregor assert(Tok.is(MMToken::ExportKeyword)); 24142b82c2a5SDouglas Gregor SourceLocation ExportLoc = consumeToken(); 24152b82c2a5SDouglas Gregor 24162b82c2a5SDouglas Gregor // Parse the module-id with an optional wildcard at the end. 24172b82c2a5SDouglas Gregor ModuleId ParsedModuleId; 24182b82c2a5SDouglas Gregor bool Wildcard = false; 24192b82c2a5SDouglas Gregor do { 2420306d8920SRichard Smith // FIXME: Support string-literal module names here. 24212b82c2a5SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 24222b82c2a5SDouglas Gregor ParsedModuleId.push_back(std::make_pair(Tok.getString(), 24232b82c2a5SDouglas Gregor Tok.getLocation())); 24242b82c2a5SDouglas Gregor consumeToken(); 24252b82c2a5SDouglas Gregor 24262b82c2a5SDouglas Gregor if (Tok.is(MMToken::Period)) { 24272b82c2a5SDouglas Gregor consumeToken(); 24282b82c2a5SDouglas Gregor continue; 24292b82c2a5SDouglas Gregor } 24302b82c2a5SDouglas Gregor 24312b82c2a5SDouglas Gregor break; 24322b82c2a5SDouglas Gregor } 24332b82c2a5SDouglas Gregor 24342b82c2a5SDouglas Gregor if(Tok.is(MMToken::Star)) { 24352b82c2a5SDouglas Gregor Wildcard = true; 2436f5eedd05SDouglas Gregor consumeToken(); 24372b82c2a5SDouglas Gregor break; 24382b82c2a5SDouglas Gregor } 24392b82c2a5SDouglas Gregor 2440ba7f2f71SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_module_id); 24412b82c2a5SDouglas Gregor HadError = true; 24422b82c2a5SDouglas Gregor return; 24432b82c2a5SDouglas Gregor } while (true); 24442b82c2a5SDouglas Gregor 24452b82c2a5SDouglas Gregor Module::UnresolvedExportDecl Unresolved = { 24462b82c2a5SDouglas Gregor ExportLoc, ParsedModuleId, Wildcard 24472b82c2a5SDouglas Gregor }; 24482b82c2a5SDouglas Gregor ActiveModule->UnresolvedExports.push_back(Unresolved); 24492b82c2a5SDouglas Gregor } 24502b82c2a5SDouglas Gregor 24519fc8faf9SAdrian Prantl /// Parse a module export_as declaration. 2452f0b11de2SDouglas Gregor /// 2453f0b11de2SDouglas Gregor /// export-as-declaration: 2454f0b11de2SDouglas Gregor /// 'export_as' identifier 2455f0b11de2SDouglas Gregor void ModuleMapParser::parseExportAsDecl() { 2456f0b11de2SDouglas Gregor assert(Tok.is(MMToken::ExportAsKeyword)); 2457f0b11de2SDouglas Gregor consumeToken(); 2458f0b11de2SDouglas Gregor 2459f0b11de2SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 2460f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_module_id); 2461f0b11de2SDouglas Gregor HadError = true; 2462f0b11de2SDouglas Gregor return; 2463f0b11de2SDouglas Gregor } 2464f0b11de2SDouglas Gregor 2465f0b11de2SDouglas Gregor if (ActiveModule->Parent) { 2466f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as); 2467f0b11de2SDouglas Gregor consumeToken(); 2468f0b11de2SDouglas Gregor return; 2469f0b11de2SDouglas Gregor } 2470f0b11de2SDouglas Gregor 2471f0b11de2SDouglas Gregor if (!ActiveModule->ExportAsModule.empty()) { 2472f0b11de2SDouglas Gregor if (ActiveModule->ExportAsModule == Tok.getString()) { 2473f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as) 2474f0b11de2SDouglas Gregor << ActiveModule->Name << Tok.getString(); 2475f0b11de2SDouglas Gregor } else { 2476f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as) 2477f0b11de2SDouglas Gregor << ActiveModule->Name << ActiveModule->ExportAsModule 2478f0b11de2SDouglas Gregor << Tok.getString(); 2479f0b11de2SDouglas Gregor } 2480f0b11de2SDouglas Gregor } 2481f0b11de2SDouglas Gregor 2482f0b11de2SDouglas Gregor ActiveModule->ExportAsModule = Tok.getString(); 2483a3b5f71eSBruno Cardoso Lopes Map.addLinkAsDependency(ActiveModule); 2484a3b5f71eSBruno Cardoso Lopes 2485f0b11de2SDouglas Gregor consumeToken(); 2486f0b11de2SDouglas Gregor } 2487f0b11de2SDouglas Gregor 24889fc8faf9SAdrian Prantl /// Parse a module use declaration. 2489ba7f2f71SDaniel Jasper /// 24908f4d3ff1SRichard Smith /// use-declaration: 24918f4d3ff1SRichard Smith /// 'use' wildcard-module-id 2492ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() { 2493ba7f2f71SDaniel Jasper assert(Tok.is(MMToken::UseKeyword)); 24948f4d3ff1SRichard Smith auto KWLoc = consumeToken(); 2495ba7f2f71SDaniel Jasper // Parse the module-id. 2496ba7f2f71SDaniel Jasper ModuleId ParsedModuleId; 24973cd34c76SDaniel Jasper parseModuleId(ParsedModuleId); 2498ba7f2f71SDaniel Jasper 24998f4d3ff1SRichard Smith if (ActiveModule->Parent) 25008f4d3ff1SRichard Smith Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule); 25018f4d3ff1SRichard Smith else 2502ba7f2f71SDaniel Jasper ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId); 2503ba7f2f71SDaniel Jasper } 2504ba7f2f71SDaniel Jasper 25059fc8faf9SAdrian Prantl /// Parse a link declaration. 25066ddfca91SDouglas Gregor /// 25076ddfca91SDouglas Gregor /// module-declaration: 25086ddfca91SDouglas Gregor /// 'link' 'framework'[opt] string-literal 25096ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() { 25106ddfca91SDouglas Gregor assert(Tok.is(MMToken::LinkKeyword)); 25116ddfca91SDouglas Gregor SourceLocation LinkLoc = consumeToken(); 25126ddfca91SDouglas Gregor 25136ddfca91SDouglas Gregor // Parse the optional 'framework' keyword. 25146ddfca91SDouglas Gregor bool IsFramework = false; 25156ddfca91SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 25166ddfca91SDouglas Gregor consumeToken(); 25176ddfca91SDouglas Gregor IsFramework = true; 25186ddfca91SDouglas Gregor } 25196ddfca91SDouglas Gregor 25206ddfca91SDouglas Gregor // Parse the library name 25216ddfca91SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 25226ddfca91SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name) 25236ddfca91SDouglas Gregor << IsFramework << SourceRange(LinkLoc); 25246ddfca91SDouglas Gregor HadError = true; 25256ddfca91SDouglas Gregor return; 25266ddfca91SDouglas Gregor } 25276ddfca91SDouglas Gregor 25286ddfca91SDouglas Gregor std::string LibraryName = Tok.getString(); 25296ddfca91SDouglas Gregor consumeToken(); 25306ddfca91SDouglas Gregor ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName, 25316ddfca91SDouglas Gregor IsFramework)); 25326ddfca91SDouglas Gregor } 25336ddfca91SDouglas Gregor 25349fc8faf9SAdrian Prantl /// Parse a configuration macro declaration. 253535b13eceSDouglas Gregor /// 253635b13eceSDouglas Gregor /// module-declaration: 253735b13eceSDouglas Gregor /// 'config_macros' attributes[opt] config-macro-list? 253835b13eceSDouglas Gregor /// 253935b13eceSDouglas Gregor /// config-macro-list: 254035b13eceSDouglas Gregor /// identifier (',' identifier)? 254135b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() { 254235b13eceSDouglas Gregor assert(Tok.is(MMToken::ConfigMacros)); 254335b13eceSDouglas Gregor SourceLocation ConfigMacrosLoc = consumeToken(); 254435b13eceSDouglas Gregor 254535b13eceSDouglas Gregor // Only top-level modules can have configuration macros. 254635b13eceSDouglas Gregor if (ActiveModule->Parent) { 254735b13eceSDouglas Gregor Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule); 254835b13eceSDouglas Gregor } 254935b13eceSDouglas Gregor 255035b13eceSDouglas Gregor // Parse the optional attributes. 255135b13eceSDouglas Gregor Attributes Attrs; 25525d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 25535d29dee0SDavide Italiano return; 25545d29dee0SDavide Italiano 255535b13eceSDouglas Gregor if (Attrs.IsExhaustive && !ActiveModule->Parent) { 255635b13eceSDouglas Gregor ActiveModule->ConfigMacrosExhaustive = true; 255735b13eceSDouglas Gregor } 255835b13eceSDouglas Gregor 255935b13eceSDouglas Gregor // If we don't have an identifier, we're done. 2560306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 256135b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) 256235b13eceSDouglas Gregor return; 256335b13eceSDouglas Gregor 256435b13eceSDouglas Gregor // Consume the first identifier. 256535b13eceSDouglas Gregor if (!ActiveModule->Parent) { 256635b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 256735b13eceSDouglas Gregor } 256835b13eceSDouglas Gregor consumeToken(); 256935b13eceSDouglas Gregor 257035b13eceSDouglas Gregor do { 257135b13eceSDouglas Gregor // If there's a comma, consume it. 257235b13eceSDouglas Gregor if (!Tok.is(MMToken::Comma)) 257335b13eceSDouglas Gregor break; 257435b13eceSDouglas Gregor consumeToken(); 257535b13eceSDouglas Gregor 257635b13eceSDouglas Gregor // We expect to see a macro name here. 2577306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 257835b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 257935b13eceSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro); 258035b13eceSDouglas Gregor break; 258135b13eceSDouglas Gregor } 258235b13eceSDouglas Gregor 258335b13eceSDouglas Gregor // Consume the macro name. 258435b13eceSDouglas Gregor if (!ActiveModule->Parent) { 258535b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 258635b13eceSDouglas Gregor } 258735b13eceSDouglas Gregor consumeToken(); 258835b13eceSDouglas Gregor } while (true); 258935b13eceSDouglas Gregor } 259035b13eceSDouglas Gregor 25919fc8faf9SAdrian Prantl /// Format a module-id into a string. 2592fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) { 2593fb912657SDouglas Gregor std::string result; 2594fb912657SDouglas Gregor { 2595fb912657SDouglas Gregor llvm::raw_string_ostream OS(result); 2596fb912657SDouglas Gregor 2597fb912657SDouglas Gregor for (unsigned I = 0, N = Id.size(); I != N; ++I) { 2598fb912657SDouglas Gregor if (I) 2599fb912657SDouglas Gregor OS << "."; 2600fb912657SDouglas Gregor OS << Id[I].first; 2601fb912657SDouglas Gregor } 2602fb912657SDouglas Gregor } 2603fb912657SDouglas Gregor 2604fb912657SDouglas Gregor return result; 2605fb912657SDouglas Gregor } 2606fb912657SDouglas Gregor 26079fc8faf9SAdrian Prantl /// Parse a conflict declaration. 2608fb912657SDouglas Gregor /// 2609fb912657SDouglas Gregor /// module-declaration: 2610fb912657SDouglas Gregor /// 'conflict' module-id ',' string-literal 2611fb912657SDouglas Gregor void ModuleMapParser::parseConflict() { 2612fb912657SDouglas Gregor assert(Tok.is(MMToken::Conflict)); 2613fb912657SDouglas Gregor SourceLocation ConflictLoc = consumeToken(); 2614fb912657SDouglas Gregor Module::UnresolvedConflict Conflict; 2615fb912657SDouglas Gregor 2616fb912657SDouglas Gregor // Parse the module-id. 2617fb912657SDouglas Gregor if (parseModuleId(Conflict.Id)) 2618fb912657SDouglas Gregor return; 2619fb912657SDouglas Gregor 2620fb912657SDouglas Gregor // Parse the ','. 2621fb912657SDouglas Gregor if (!Tok.is(MMToken::Comma)) { 2622fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma) 2623fb912657SDouglas Gregor << SourceRange(ConflictLoc); 2624fb912657SDouglas Gregor return; 2625fb912657SDouglas Gregor } 2626fb912657SDouglas Gregor consumeToken(); 2627fb912657SDouglas Gregor 2628fb912657SDouglas Gregor // Parse the message. 2629fb912657SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2630fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message) 2631fb912657SDouglas Gregor << formatModuleId(Conflict.Id); 2632fb912657SDouglas Gregor return; 2633fb912657SDouglas Gregor } 2634fb912657SDouglas Gregor Conflict.Message = Tok.getString().str(); 2635fb912657SDouglas Gregor consumeToken(); 2636fb912657SDouglas Gregor 2637fb912657SDouglas Gregor // Add this unresolved conflict. 2638fb912657SDouglas Gregor ActiveModule->UnresolvedConflicts.push_back(Conflict); 2639fb912657SDouglas Gregor } 2640fb912657SDouglas Gregor 26419fc8faf9SAdrian Prantl /// Parse an inferred module declaration (wildcard modules). 26429194a91dSDouglas Gregor /// 26439194a91dSDouglas Gregor /// module-declaration: 26449194a91dSDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt] 26459194a91dSDouglas Gregor /// { inferred-module-member* } 26469194a91dSDouglas Gregor /// 26479194a91dSDouglas Gregor /// inferred-module-member: 26489194a91dSDouglas Gregor /// 'export' '*' 26499194a91dSDouglas Gregor /// 'exclude' identifier 26509194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { 265173441091SDouglas Gregor assert(Tok.is(MMToken::Star)); 265273441091SDouglas Gregor SourceLocation StarLoc = consumeToken(); 265373441091SDouglas Gregor bool Failed = false; 265473441091SDouglas Gregor 265573441091SDouglas Gregor // Inferred modules must be submodules. 26569194a91dSDouglas Gregor if (!ActiveModule && !Framework) { 265773441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule); 265873441091SDouglas Gregor Failed = true; 265973441091SDouglas Gregor } 266073441091SDouglas Gregor 26619194a91dSDouglas Gregor if (ActiveModule) { 2662524e33e1SDouglas Gregor // Inferred modules must have umbrella directories. 26634898cde4SBen Langmuir if (!Failed && ActiveModule->IsAvailable && 26644898cde4SBen Langmuir !ActiveModule->getUmbrellaDir()) { 266573441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); 266673441091SDouglas Gregor Failed = true; 266773441091SDouglas Gregor } 266873441091SDouglas Gregor 266973441091SDouglas Gregor // Check for redefinition of an inferred module. 2670dd005f69SDouglas Gregor if (!Failed && ActiveModule->InferSubmodules) { 267173441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_redef); 2672dd005f69SDouglas Gregor if (ActiveModule->InferredSubmoduleLoc.isValid()) 2673dd005f69SDouglas Gregor Diags.Report(ActiveModule->InferredSubmoduleLoc, 267473441091SDouglas Gregor diag::note_mmap_prev_definition); 267573441091SDouglas Gregor Failed = true; 267673441091SDouglas Gregor } 267773441091SDouglas Gregor 26789194a91dSDouglas Gregor // Check for the 'framework' keyword, which is not permitted here. 26799194a91dSDouglas Gregor if (Framework) { 26809194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule); 26819194a91dSDouglas Gregor Framework = false; 26829194a91dSDouglas Gregor } 26839194a91dSDouglas Gregor } else if (Explicit) { 26849194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework); 26859194a91dSDouglas Gregor Explicit = false; 26869194a91dSDouglas Gregor } 26879194a91dSDouglas Gregor 268873441091SDouglas Gregor // If there were any problems with this inferred submodule, skip its body. 268973441091SDouglas Gregor if (Failed) { 269073441091SDouglas Gregor if (Tok.is(MMToken::LBrace)) { 269173441091SDouglas Gregor consumeToken(); 269273441091SDouglas Gregor skipUntil(MMToken::RBrace); 269373441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 269473441091SDouglas Gregor consumeToken(); 269573441091SDouglas Gregor } 269673441091SDouglas Gregor HadError = true; 269773441091SDouglas Gregor return; 269873441091SDouglas Gregor } 269973441091SDouglas Gregor 27009194a91dSDouglas Gregor // Parse optional attributes. 27014442605fSBill Wendling Attributes Attrs; 27025d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 27035d29dee0SDavide Italiano return; 27049194a91dSDouglas Gregor 27059194a91dSDouglas Gregor if (ActiveModule) { 270673441091SDouglas Gregor // Note that we have an inferred submodule. 2707dd005f69SDouglas Gregor ActiveModule->InferSubmodules = true; 2708dd005f69SDouglas Gregor ActiveModule->InferredSubmoduleLoc = StarLoc; 2709dd005f69SDouglas Gregor ActiveModule->InferExplicitSubmodules = Explicit; 27109194a91dSDouglas Gregor } else { 27119194a91dSDouglas Gregor // We'll be inferring framework modules for this directory. 27129194a91dSDouglas Gregor Map.InferredDirectories[Directory].InferModules = true; 2713c1d88ea5SBen Langmuir Map.InferredDirectories[Directory].Attrs = Attrs; 2714beee15e7SBen Langmuir Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile; 2715131daca0SRichard Smith // FIXME: Handle the 'framework' keyword. 27169194a91dSDouglas Gregor } 271773441091SDouglas Gregor 271873441091SDouglas Gregor // Parse the opening brace. 271973441091SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 272073441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard); 272173441091SDouglas Gregor HadError = true; 272273441091SDouglas Gregor return; 272373441091SDouglas Gregor } 272473441091SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 272573441091SDouglas Gregor 272673441091SDouglas Gregor // Parse the body of the inferred submodule. 272773441091SDouglas Gregor bool Done = false; 272873441091SDouglas Gregor do { 272973441091SDouglas Gregor switch (Tok.Kind) { 273073441091SDouglas Gregor case MMToken::EndOfFile: 273173441091SDouglas Gregor case MMToken::RBrace: 273273441091SDouglas Gregor Done = true; 273373441091SDouglas Gregor break; 273473441091SDouglas Gregor 2735afd1b1c9SEugene Zelenko case MMToken::ExcludeKeyword: 27369194a91dSDouglas Gregor if (ActiveModule) { 27379194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2738d2d442caSCraig Topper << (ActiveModule != nullptr); 27399194a91dSDouglas Gregor consumeToken(); 27409194a91dSDouglas Gregor break; 27419194a91dSDouglas Gregor } 27429194a91dSDouglas Gregor 27439194a91dSDouglas Gregor consumeToken(); 2744306d8920SRichard Smith // FIXME: Support string-literal module names here. 27459194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 27469194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name); 27479194a91dSDouglas Gregor break; 27489194a91dSDouglas Gregor } 27499194a91dSDouglas Gregor 27509194a91dSDouglas Gregor Map.InferredDirectories[Directory].ExcludedModules 27519194a91dSDouglas Gregor .push_back(Tok.getString()); 27529194a91dSDouglas Gregor consumeToken(); 27539194a91dSDouglas Gregor break; 27549194a91dSDouglas Gregor 27559194a91dSDouglas Gregor case MMToken::ExportKeyword: 27569194a91dSDouglas Gregor if (!ActiveModule) { 27579194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2758d2d442caSCraig Topper << (ActiveModule != nullptr); 27599194a91dSDouglas Gregor consumeToken(); 27609194a91dSDouglas Gregor break; 27619194a91dSDouglas Gregor } 27629194a91dSDouglas Gregor 276373441091SDouglas Gregor consumeToken(); 276473441091SDouglas Gregor if (Tok.is(MMToken::Star)) 2765dd005f69SDouglas Gregor ActiveModule->InferExportWildcard = true; 276673441091SDouglas Gregor else 276773441091SDouglas Gregor Diags.Report(Tok.getLocation(), 276873441091SDouglas Gregor diag::err_mmap_expected_export_wildcard); 276973441091SDouglas Gregor consumeToken(); 277073441091SDouglas Gregor break; 277173441091SDouglas Gregor 277273441091SDouglas Gregor case MMToken::ExplicitKeyword: 277373441091SDouglas Gregor case MMToken::ModuleKeyword: 277473441091SDouglas Gregor case MMToken::HeaderKeyword: 2775b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 277673441091SDouglas Gregor case MMToken::UmbrellaKeyword: 277773441091SDouglas Gregor default: 27789194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2779d2d442caSCraig Topper << (ActiveModule != nullptr); 278073441091SDouglas Gregor consumeToken(); 278173441091SDouglas Gregor break; 278273441091SDouglas Gregor } 278373441091SDouglas Gregor } while (!Done); 278473441091SDouglas Gregor 278573441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 278673441091SDouglas Gregor consumeToken(); 278773441091SDouglas Gregor else { 278873441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 278973441091SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 279073441091SDouglas Gregor HadError = true; 279173441091SDouglas Gregor } 279273441091SDouglas Gregor } 279373441091SDouglas Gregor 27949fc8faf9SAdrian Prantl /// Parse optional attributes. 27959194a91dSDouglas Gregor /// 27969194a91dSDouglas Gregor /// attributes: 27979194a91dSDouglas Gregor /// attribute attributes 27989194a91dSDouglas Gregor /// attribute 27999194a91dSDouglas Gregor /// 28009194a91dSDouglas Gregor /// attribute: 28019194a91dSDouglas Gregor /// [ identifier ] 28029194a91dSDouglas Gregor /// 28039194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes. 28049194a91dSDouglas Gregor /// 28059194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise. 28064442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { 28079194a91dSDouglas Gregor bool HadError = false; 28089194a91dSDouglas Gregor 28099194a91dSDouglas Gregor while (Tok.is(MMToken::LSquare)) { 28109194a91dSDouglas Gregor // Consume the '['. 28119194a91dSDouglas Gregor SourceLocation LSquareLoc = consumeToken(); 28129194a91dSDouglas Gregor 28139194a91dSDouglas Gregor // Check whether we have an attribute name here. 28149194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 28159194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute); 28169194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 28179194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 28189194a91dSDouglas Gregor consumeToken(); 28199194a91dSDouglas Gregor HadError = true; 28209194a91dSDouglas Gregor } 28219194a91dSDouglas Gregor 28229194a91dSDouglas Gregor // Decode the attribute name. 28239194a91dSDouglas Gregor AttributeKind Attribute 28249194a91dSDouglas Gregor = llvm::StringSwitch<AttributeKind>(Tok.getString()) 282535b13eceSDouglas Gregor .Case("exhaustive", AT_exhaustive) 282677944868SRichard Smith .Case("extern_c", AT_extern_c) 2827ed84df00SBruno Cardoso Lopes .Case("no_undeclared_includes", AT_no_undeclared_includes) 28289194a91dSDouglas Gregor .Case("system", AT_system) 28299194a91dSDouglas Gregor .Default(AT_unknown); 28309194a91dSDouglas Gregor switch (Attribute) { 28319194a91dSDouglas Gregor case AT_unknown: 28329194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute) 28339194a91dSDouglas Gregor << Tok.getString(); 28349194a91dSDouglas Gregor break; 28359194a91dSDouglas Gregor 28369194a91dSDouglas Gregor case AT_system: 28379194a91dSDouglas Gregor Attrs.IsSystem = true; 28389194a91dSDouglas Gregor break; 283935b13eceSDouglas Gregor 284077944868SRichard Smith case AT_extern_c: 284177944868SRichard Smith Attrs.IsExternC = true; 284277944868SRichard Smith break; 284377944868SRichard Smith 284435b13eceSDouglas Gregor case AT_exhaustive: 284535b13eceSDouglas Gregor Attrs.IsExhaustive = true; 284635b13eceSDouglas Gregor break; 2847ed84df00SBruno Cardoso Lopes 2848ed84df00SBruno Cardoso Lopes case AT_no_undeclared_includes: 2849ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes = true; 2850ed84df00SBruno Cardoso Lopes break; 28519194a91dSDouglas Gregor } 28529194a91dSDouglas Gregor consumeToken(); 28539194a91dSDouglas Gregor 28549194a91dSDouglas Gregor // Consume the ']'. 28559194a91dSDouglas Gregor if (!Tok.is(MMToken::RSquare)) { 28569194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare); 28579194a91dSDouglas Gregor Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match); 28589194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 28599194a91dSDouglas Gregor HadError = true; 28609194a91dSDouglas Gregor } 28619194a91dSDouglas Gregor 28629194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 28639194a91dSDouglas Gregor consumeToken(); 28649194a91dSDouglas Gregor } 28659194a91dSDouglas Gregor 28669194a91dSDouglas Gregor return HadError; 28679194a91dSDouglas Gregor } 28689194a91dSDouglas Gregor 28699fc8faf9SAdrian Prantl /// Parse a module map file. 2870718292f2SDouglas Gregor /// 2871718292f2SDouglas Gregor /// module-map-file: 2872718292f2SDouglas Gregor /// module-declaration* 2873718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 2874718292f2SDouglas Gregor do { 2875718292f2SDouglas Gregor switch (Tok.Kind) { 2876718292f2SDouglas Gregor case MMToken::EndOfFile: 2877718292f2SDouglas Gregor return HadError; 2878718292f2SDouglas Gregor 2879e7ab3669SDouglas Gregor case MMToken::ExplicitKeyword: 288097292843SDaniel Jasper case MMToken::ExternKeyword: 2881718292f2SDouglas Gregor case MMToken::ModuleKeyword: 2882755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 2883718292f2SDouglas Gregor parseModuleDecl(); 2884718292f2SDouglas Gregor break; 2885718292f2SDouglas Gregor 28861fb5c3a6SDouglas Gregor case MMToken::Comma: 288735b13eceSDouglas Gregor case MMToken::ConfigMacros: 2888fb912657SDouglas Gregor case MMToken::Conflict: 2889a3feee2aSRichard Smith case MMToken::Exclaim: 289059527666SDouglas Gregor case MMToken::ExcludeKeyword: 28912b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 2892f0b11de2SDouglas Gregor case MMToken::ExportAsKeyword: 2893718292f2SDouglas Gregor case MMToken::HeaderKeyword: 2894718292f2SDouglas Gregor case MMToken::Identifier: 2895718292f2SDouglas Gregor case MMToken::LBrace: 28966ddfca91SDouglas Gregor case MMToken::LinkKeyword: 2897a686e1b0SDouglas Gregor case MMToken::LSquare: 28982b82c2a5SDouglas Gregor case MMToken::Period: 2899b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 2900718292f2SDouglas Gregor case MMToken::RBrace: 2901a686e1b0SDouglas Gregor case MMToken::RSquare: 29021fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 29032b82c2a5SDouglas Gregor case MMToken::Star: 2904718292f2SDouglas Gregor case MMToken::StringLiteral: 2905040e1266SRichard Smith case MMToken::IntegerLiteral: 2906b8afebe2SRichard Smith case MMToken::TextualKeyword: 2907718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 2908ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 2909718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 2910718292f2SDouglas Gregor HadError = true; 2911718292f2SDouglas Gregor consumeToken(); 2912718292f2SDouglas Gregor break; 2913718292f2SDouglas Gregor } 2914718292f2SDouglas Gregor } while (true); 2915718292f2SDouglas Gregor } 2916718292f2SDouglas Gregor 29179acb99e3SRichard Smith bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem, 2918c192d194SBruno Cardoso Lopes const DirectoryEntry *Dir, FileID ID, 29198128f332SRichard Smith unsigned *Offset, 2920ae6df27eSRichard Smith SourceLocation ExternModuleLoc) { 29218128f332SRichard Smith assert(Target && "Missing target information"); 29224ddf2221SDouglas Gregor llvm::DenseMap<const FileEntry *, bool>::iterator Known 29234ddf2221SDouglas Gregor = ParsedModuleMap.find(File); 29244ddf2221SDouglas Gregor if (Known != ParsedModuleMap.end()) 29254ddf2221SDouglas Gregor return Known->second; 29264ddf2221SDouglas Gregor 29278128f332SRichard Smith // If the module map file wasn't already entered, do so now. 29288128f332SRichard Smith if (ID.isInvalid()) { 2929f3f84616SRichard Smith auto FileCharacter = 2930f3f84616SRichard Smith IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap; 29318128f332SRichard Smith ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter); 29328128f332SRichard Smith } 29338128f332SRichard Smith 29348128f332SRichard Smith assert(Target && "Missing target information"); 29351f76c4e8SManuel Klimek const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID); 2936718292f2SDouglas Gregor if (!Buffer) 29374ddf2221SDouglas Gregor return ParsedModuleMap[File] = true; 29388128f332SRichard Smith assert((!Offset || *Offset <= Buffer->getBufferSize()) && 29398128f332SRichard Smith "invalid buffer offset"); 2940718292f2SDouglas Gregor 2941718292f2SDouglas Gregor // Parse this module map file. 29428128f332SRichard Smith Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts, 29438128f332SRichard Smith Buffer->getBufferStart(), 29448128f332SRichard Smith Buffer->getBufferStart() + (Offset ? *Offset : 0), 29458128f332SRichard Smith Buffer->getBufferEnd()); 29462a6edb30SRichard Smith SourceLocation Start = L.getSourceLocation(); 2947beee15e7SBen Langmuir ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir, 2948c192d194SBruno Cardoso Lopes IsSystem); 2949718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 29504ddf2221SDouglas Gregor ParsedModuleMap[File] = Result; 29512a6edb30SRichard Smith 29528128f332SRichard Smith if (Offset) { 29538128f332SRichard Smith auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation()); 29548128f332SRichard Smith assert(Loc.first == ID && "stopped in a different file?"); 29558128f332SRichard Smith *Offset = Loc.second; 29568128f332SRichard Smith } 29578128f332SRichard Smith 29582a6edb30SRichard Smith // Notify callbacks that we parsed it. 29592a6edb30SRichard Smith for (const auto &Cb : Callbacks) 29602a6edb30SRichard Smith Cb->moduleMapFileRead(Start, *File, IsSystem); 29618587dfd9SBruno Cardoso Lopes 2962718292f2SDouglas Gregor return Result; 2963718292f2SDouglas Gregor } 2964