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) { 809*d6509cf2SRichard Smith PendingSubmodules.emplace_back( 810056bf77fSRichard Smith new Module("<global>", Loc, nullptr, /*IsFramework*/ false, 811056bf77fSRichard Smith /*IsExplicit*/ true, NumCreatedModules++)); 812*d6509cf2SRichard Smith PendingSubmodules.back()->Kind = Module::GlobalModuleFragment; 813*d6509cf2SRichard Smith return PendingSubmodules.back().get(); 814dd8b5337SRichard Smith } 815dd8b5337SRichard Smith 816bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc, 817dd8b5337SRichard Smith StringRef Name, 818dd8b5337SRichard Smith Module *GlobalModule) { 819bbcc9f04SRichard Smith assert(LangOpts.CurrentModule == Name && "module name mismatch"); 820bbcc9f04SRichard Smith assert(!Modules[Name] && "redefining existing module"); 821bbcc9f04SRichard Smith 822bbcc9f04SRichard Smith auto *Result = 823bbcc9f04SRichard Smith new Module(Name, Loc, nullptr, /*IsFramework*/ false, 824bbcc9f04SRichard Smith /*IsExplicit*/ false, NumCreatedModules++); 825145e15a3SRichard Smith Result->Kind = Module::ModuleInterfaceUnit; 826bbcc9f04SRichard Smith Modules[Name] = SourceModule = Result; 827bbcc9f04SRichard Smith 828dd8b5337SRichard Smith // Reparent the current global module fragment as a submodule of this module. 829*d6509cf2SRichard Smith for (auto &Submodule : PendingSubmodules) { 830*d6509cf2SRichard Smith Submodule->setParent(Result); 831*d6509cf2SRichard Smith Submodule.release(); // now owned by parent 832*d6509cf2SRichard Smith } 833*d6509cf2SRichard Smith PendingSubmodules.clear(); 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 844*d6509cf2SRichard Smith Module *ModuleMap::createHeaderModule(StringRef Name, 845*d6509cf2SRichard Smith ArrayRef<Module::Header> Headers) { 846*d6509cf2SRichard Smith assert(LangOpts.CurrentModule == Name && "module name mismatch"); 847*d6509cf2SRichard Smith assert(!Modules[Name] && "redefining existing module"); 848*d6509cf2SRichard Smith 849*d6509cf2SRichard Smith auto *Result = 850*d6509cf2SRichard Smith new Module(Name, SourceLocation(), nullptr, /*IsFramework*/ false, 851*d6509cf2SRichard Smith /*IsExplicit*/ false, NumCreatedModules++); 852*d6509cf2SRichard Smith Result->Kind = Module::ModuleInterfaceUnit; 853*d6509cf2SRichard Smith Modules[Name] = SourceModule = Result; 854*d6509cf2SRichard Smith 855*d6509cf2SRichard Smith for (const Module::Header &H : Headers) { 856*d6509cf2SRichard Smith auto *M = new Module(H.NameAsWritten, SourceLocation(), Result, 857*d6509cf2SRichard Smith /*IsFramework*/ false, 858*d6509cf2SRichard Smith /*IsExplicit*/ true, NumCreatedModules++); 859*d6509cf2SRichard Smith // Header modules are implicitly 'export *'. 860*d6509cf2SRichard Smith M->Exports.push_back(Module::ExportDecl(nullptr, true)); 861*d6509cf2SRichard Smith addHeader(M, H, NormalHeader); 862*d6509cf2SRichard Smith } 863*d6509cf2SRichard Smith 864*d6509cf2SRichard Smith return Result; 865*d6509cf2SRichard Smith } 866*d6509cf2SRichard Smith 8679fc8faf9SAdrian Prantl /// For a framework module, infer the framework against which we 86811dfe6feSDouglas Gregor /// should link. 86911dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir, 87011dfe6feSDouglas Gregor FileManager &FileMgr) { 87111dfe6feSDouglas Gregor assert(Mod->IsFramework && "Can only infer linking for framework modules"); 87211dfe6feSDouglas Gregor assert(!Mod->isSubFramework() && 87311dfe6feSDouglas Gregor "Can only infer linking for top-level frameworks"); 87411dfe6feSDouglas Gregor 87511dfe6feSDouglas Gregor SmallString<128> LibName; 87611dfe6feSDouglas Gregor LibName += FrameworkDir->getName(); 87711dfe6feSDouglas Gregor llvm::sys::path::append(LibName, Mod->Name); 8788aaae5a9SJuergen Ributzka 8798aaae5a9SJuergen Ributzka // The library name of a framework has more than one possible extension since 8808aaae5a9SJuergen Ributzka // the introduction of the text-based dynamic library format. We need to check 8818aaae5a9SJuergen Ributzka // for both before we give up. 8828013e81dSBenjamin Kramer for (const char *extension : {"", ".tbd"}) { 8838aaae5a9SJuergen Ributzka llvm::sys::path::replace_extension(LibName, extension); 88411dfe6feSDouglas Gregor if (FileMgr.getFile(LibName)) { 88511dfe6feSDouglas Gregor Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name, 88611dfe6feSDouglas Gregor /*IsFramework=*/true)); 8878aaae5a9SJuergen Ributzka return; 8888aaae5a9SJuergen Ributzka } 88911dfe6feSDouglas Gregor } 89011dfe6feSDouglas Gregor } 89111dfe6feSDouglas Gregor 892a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 893a525400dSBen Langmuir bool IsSystem, Module *Parent) { 894c1d88ea5SBen Langmuir Attributes Attrs; 895c1d88ea5SBen Langmuir Attrs.IsSystem = IsSystem; 896a525400dSBen Langmuir return inferFrameworkModule(FrameworkDir, Attrs, Parent); 897c1d88ea5SBen Langmuir } 898c1d88ea5SBen Langmuir 899a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 900c1d88ea5SBen Langmuir Attributes Attrs, Module *Parent) { 901a525400dSBen Langmuir // Note: as an egregious but useful hack we use the real path here, because 902a525400dSBen Langmuir // we might be looking at an embedded framework that symlinks out to a 903a525400dSBen Langmuir // top-level framework, and we need to infer as if we were naming the 904a525400dSBen Langmuir // top-level framework. 905a525400dSBen Langmuir StringRef FrameworkDirName = 906a525400dSBen Langmuir SourceMgr.getFileManager().getCanonicalName(FrameworkDir); 907a525400dSBen Langmuir 908a525400dSBen Langmuir // In case this is a case-insensitive filesystem, use the canonical 909a525400dSBen Langmuir // directory name as the ModuleName, since modules are case-sensitive. 910a525400dSBen Langmuir // FIXME: we should be able to give a fix-it hint for the correct spelling. 911a525400dSBen Langmuir SmallString<32> ModuleNameStorage; 912a525400dSBen Langmuir StringRef ModuleName = sanitizeFilenameAsIdentifier( 913a525400dSBen Langmuir llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage); 914c1d88ea5SBen Langmuir 91556c64013SDouglas Gregor // Check whether we've already found this module. 916e89dbc1dSDouglas Gregor if (Module *Mod = lookupModuleQualified(ModuleName, Parent)) 917e89dbc1dSDouglas Gregor return Mod; 918e89dbc1dSDouglas Gregor 9191f76c4e8SManuel Klimek FileManager &FileMgr = SourceMgr.getFileManager(); 92056c64013SDouglas Gregor 9219194a91dSDouglas Gregor // If the framework has a parent path from which we're allowed to infer 9229194a91dSDouglas Gregor // a framework module, do so. 923beee15e7SBen Langmuir const FileEntry *ModuleMapFile = nullptr; 9249194a91dSDouglas Gregor if (!Parent) { 9254ddf2221SDouglas Gregor // Determine whether we're allowed to infer a module map. 9269194a91dSDouglas Gregor bool canInfer = false; 9274ddf2221SDouglas Gregor if (llvm::sys::path::has_parent_path(FrameworkDirName)) { 9289194a91dSDouglas Gregor // Figure out the parent path. 9294ddf2221SDouglas Gregor StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName); 9309194a91dSDouglas Gregor if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) { 9319194a91dSDouglas Gregor // Check whether we have already looked into the parent directory 9329194a91dSDouglas Gregor // for a module map. 933e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator 9349194a91dSDouglas Gregor inferred = InferredDirectories.find(ParentDir); 9359194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) { 9369194a91dSDouglas Gregor // We haven't looked here before. Load a module map, if there is 9379194a91dSDouglas Gregor // one. 938984e1df7SBen Langmuir bool IsFrameworkDir = Parent.endswith(".framework"); 939984e1df7SBen Langmuir if (const FileEntry *ModMapFile = 940984e1df7SBen Langmuir HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) { 941c1d88ea5SBen Langmuir parseModuleMapFile(ModMapFile, Attrs.IsSystem, ParentDir); 9429194a91dSDouglas Gregor inferred = InferredDirectories.find(ParentDir); 9439194a91dSDouglas Gregor } 9449194a91dSDouglas Gregor 9459194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) 9469194a91dSDouglas Gregor inferred = InferredDirectories.insert( 9479194a91dSDouglas Gregor std::make_pair(ParentDir, InferredDirectory())).first; 9489194a91dSDouglas Gregor } 9499194a91dSDouglas Gregor 9509194a91dSDouglas Gregor if (inferred->second.InferModules) { 9519194a91dSDouglas Gregor // We're allowed to infer for this directory, but make sure it's okay 9529194a91dSDouglas Gregor // to infer this particular module. 9534ddf2221SDouglas Gregor StringRef Name = llvm::sys::path::stem(FrameworkDirName); 9549194a91dSDouglas Gregor canInfer = std::find(inferred->second.ExcludedModules.begin(), 9559194a91dSDouglas Gregor inferred->second.ExcludedModules.end(), 9569194a91dSDouglas Gregor Name) == inferred->second.ExcludedModules.end(); 9579194a91dSDouglas Gregor 958c1d88ea5SBen Langmuir Attrs.IsSystem |= inferred->second.Attrs.IsSystem; 959c1d88ea5SBen Langmuir Attrs.IsExternC |= inferred->second.Attrs.IsExternC; 960c1d88ea5SBen Langmuir Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive; 961ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes |= 962ed84df00SBruno Cardoso Lopes inferred->second.Attrs.NoUndeclaredIncludes; 963beee15e7SBen Langmuir ModuleMapFile = inferred->second.ModuleMapFile; 9649194a91dSDouglas Gregor } 9659194a91dSDouglas Gregor } 9669194a91dSDouglas Gregor } 9679194a91dSDouglas Gregor 9689194a91dSDouglas Gregor // If we're not allowed to infer a framework module, don't. 9699194a91dSDouglas Gregor if (!canInfer) 970d2d442caSCraig Topper return nullptr; 971beee15e7SBen Langmuir } else 9729d6448b1SBen Langmuir ModuleMapFile = getModuleMapFileForUniquing(Parent); 9739194a91dSDouglas Gregor 9749194a91dSDouglas Gregor 97556c64013SDouglas Gregor // Look for an umbrella header. 9762c1dd271SDylan Noblesmith SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 97717381a06SBenjamin Kramer llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h"); 978e89dbc1dSDouglas Gregor const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName); 97956c64013SDouglas Gregor 98056c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the 98156c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good 98256c64013SDouglas Gregor // idea. 98356c64013SDouglas Gregor if (!UmbrellaHeader) 984d2d442caSCraig Topper return nullptr; 98556c64013SDouglas Gregor 9869d6448b1SBen Langmuir Module *Result = new Module(ModuleName, SourceLocation(), Parent, 987a7e2cc68SRichard Smith /*IsFramework=*/true, /*IsExplicit=*/false, 988a7e2cc68SRichard Smith NumCreatedModules++); 9899d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = ModuleMapFile; 9909d6448b1SBen Langmuir Result->IsInferred = true; 9917e82e019SRichard Smith if (!Parent) { 9927e82e019SRichard Smith if (LangOpts.CurrentModule == ModuleName) 993ba7f2f71SDaniel Jasper SourceModule = Result; 9947e82e019SRichard Smith Modules[ModuleName] = Result; 995c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID; 996ba7f2f71SDaniel Jasper } 997c1d88ea5SBen Langmuir 998c1d88ea5SBen Langmuir Result->IsSystem |= Attrs.IsSystem; 999c1d88ea5SBen Langmuir Result->IsExternC |= Attrs.IsExternC; 1000c1d88ea5SBen Langmuir Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive; 1001ed84df00SBruno Cardoso Lopes Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes; 10022b63d15fSRichard Smith Result->Directory = FrameworkDir; 1003a686e1b0SDouglas Gregor 1004322f633cSDouglas Gregor // umbrella header "umbrella-header-name" 10052b63d15fSRichard Smith // 10062b63d15fSRichard Smith // The "Headers/" component of the name is implied because this is 10072b63d15fSRichard Smith // a framework module. 10082b63d15fSRichard Smith setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h"); 1009d8bd7537SDouglas Gregor 1010d8bd7537SDouglas Gregor // export * 1011d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 1012d8bd7537SDouglas Gregor 1013a89c5ac4SDouglas Gregor // module * { export * } 1014a89c5ac4SDouglas Gregor Result->InferSubmodules = true; 1015a89c5ac4SDouglas Gregor Result->InferExportWildcard = true; 1016a89c5ac4SDouglas Gregor 1017e89dbc1dSDouglas Gregor // Look for subframeworks. 1018c080917eSRafael Espindola std::error_code EC; 10192c1dd271SDylan Noblesmith SmallString<128> SubframeworksDirName 1020ddaa69cbSDouglas Gregor = StringRef(FrameworkDir->getName()); 1021e89dbc1dSDouglas Gregor llvm::sys::path::append(SubframeworksDirName, "Frameworks"); 10222d4d8cb3SBenjamin Kramer llvm::sys::path::native(SubframeworksDirName); 1023b171a59bSBruno Cardoso Lopes vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); 1024b171a59bSBruno Cardoso Lopes for (vfs::directory_iterator Dir = FS.dir_begin(SubframeworksDirName, EC), 1025b171a59bSBruno Cardoso Lopes DirEnd; 1026e89dbc1dSDouglas Gregor Dir != DirEnd && !EC; Dir.increment(EC)) { 10270ae00567SSam McCall if (!StringRef(Dir->path()).endswith(".framework")) 1028e89dbc1dSDouglas Gregor continue; 1029f2161a70SDouglas Gregor 1030b171a59bSBruno Cardoso Lopes if (const DirectoryEntry *SubframeworkDir = 10310ae00567SSam McCall FileMgr.getDirectory(Dir->path())) { 103207c22b78SDouglas Gregor // Note: as an egregious but useful hack, we use the real path here and 103307c22b78SDouglas Gregor // check whether it is actually a subdirectory of the parent directory. 103407c22b78SDouglas Gregor // This will not be the case if the 'subframework' is actually a symlink 103507c22b78SDouglas Gregor // out to a top-level framework. 1036e00c8b20SDouglas Gregor StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir); 103707c22b78SDouglas Gregor bool FoundParent = false; 103807c22b78SDouglas Gregor do { 103907c22b78SDouglas Gregor // Get the parent directory name. 104007c22b78SDouglas Gregor SubframeworkDirName 104107c22b78SDouglas Gregor = llvm::sys::path::parent_path(SubframeworkDirName); 104207c22b78SDouglas Gregor if (SubframeworkDirName.empty()) 104307c22b78SDouglas Gregor break; 104407c22b78SDouglas Gregor 104507c22b78SDouglas Gregor if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) { 104607c22b78SDouglas Gregor FoundParent = true; 104707c22b78SDouglas Gregor break; 104807c22b78SDouglas Gregor } 104907c22b78SDouglas Gregor } while (true); 105007c22b78SDouglas Gregor 105107c22b78SDouglas Gregor if (!FoundParent) 105207c22b78SDouglas Gregor continue; 105307c22b78SDouglas Gregor 1054e89dbc1dSDouglas Gregor // FIXME: Do we want to warn about subframeworks without umbrella headers? 1055a525400dSBen Langmuir inferFrameworkModule(SubframeworkDir, Attrs, Result); 1056e89dbc1dSDouglas Gregor } 1057e89dbc1dSDouglas Gregor } 1058e89dbc1dSDouglas Gregor 105911dfe6feSDouglas Gregor // If the module is a top-level framework, automatically link against the 106011dfe6feSDouglas Gregor // framework. 106111dfe6feSDouglas Gregor if (!Result->isSubFramework()) { 106211dfe6feSDouglas Gregor inferFrameworkLink(Result, FrameworkDir, FileMgr); 106311dfe6feSDouglas Gregor } 106411dfe6feSDouglas Gregor 106556c64013SDouglas Gregor return Result; 106656c64013SDouglas Gregor } 106756c64013SDouglas Gregor 10688587dfd9SBruno Cardoso Lopes Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework, 10698587dfd9SBruno Cardoso Lopes Module *ShadowingModule) { 10708587dfd9SBruno Cardoso Lopes 10718587dfd9SBruno Cardoso Lopes // Create a new module with this name. 10728587dfd9SBruno Cardoso Lopes Module *Result = 10738587dfd9SBruno Cardoso Lopes new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework, 10748587dfd9SBruno Cardoso Lopes /*IsExplicit=*/false, NumCreatedModules++); 10758587dfd9SBruno Cardoso Lopes Result->ShadowingModule = ShadowingModule; 10768587dfd9SBruno Cardoso Lopes Result->IsAvailable = false; 1077c192d194SBruno Cardoso Lopes ModuleScopeIDs[Result] = CurrentModuleScopeID; 10788587dfd9SBruno Cardoso Lopes ShadowModules.push_back(Result); 10798587dfd9SBruno Cardoso Lopes 10808587dfd9SBruno Cardoso Lopes return Result; 10818587dfd9SBruno Cardoso Lopes } 10828587dfd9SBruno Cardoso Lopes 10832b63d15fSRichard Smith void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader, 10842b63d15fSRichard Smith Twine NameAsWritten) { 108597da9178SDaniel Jasper Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader)); 108673141fa9SDouglas Gregor Mod->Umbrella = UmbrellaHeader; 10872b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 10887033127bSDouglas Gregor UmbrellaDirs[UmbrellaHeader->getDir()] = Mod; 1089b3a0fa48SBruno Cardoso Lopes 1090b3a0fa48SBruno Cardoso Lopes // Notify callbacks that we just added a new header. 1091b3a0fa48SBruno Cardoso Lopes for (const auto &Cb : Callbacks) 1092b3a0fa48SBruno Cardoso Lopes Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader); 1093a89c5ac4SDouglas Gregor } 1094a89c5ac4SDouglas Gregor 10952b63d15fSRichard Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, 10962b63d15fSRichard Smith Twine NameAsWritten) { 1097524e33e1SDouglas Gregor Mod->Umbrella = UmbrellaDir; 10982b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 1099524e33e1SDouglas Gregor UmbrellaDirs[UmbrellaDir] = Mod; 1100524e33e1SDouglas Gregor } 1101524e33e1SDouglas Gregor 1102040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod, 11039f6020bcSBruno Cardoso Lopes Module::UnresolvedHeaderDirective Header, 11049f6020bcSBruno Cardoso Lopes bool &NeedsFramework) { 1105040e1266SRichard Smith // If there is a builtin counterpart to this file, add it now so it can 1106040e1266SRichard Smith // wrap the system header. 1107040e1266SRichard Smith if (resolveAsBuiltinHeader(Mod, Header)) { 1108040e1266SRichard Smith // If we have both a builtin and system version of the file, the 1109040e1266SRichard Smith // builtin version may want to inject macros into the system header, so 1110040e1266SRichard Smith // force the system header to be treated as a textual header in this 1111040e1266SRichard Smith // case. 1112040e1266SRichard Smith Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole( 1113040e1266SRichard Smith headerKindToRole(Header.Kind) | ModuleMap::TextualHeader)); 1114040e1266SRichard Smith Header.HasBuiltinHeader = true; 11153c1a41adSRichard Smith } 1116040e1266SRichard Smith 1117040e1266SRichard Smith // If possible, don't stat the header until we need to. This requires the 1118040e1266SRichard Smith // user to have provided us with some stat information about the file. 1119040e1266SRichard Smith // FIXME: Add support for lazily stat'ing umbrella headers and excluded 1120040e1266SRichard Smith // headers. 1121040e1266SRichard Smith if ((Header.Size || Header.ModTime) && !Header.IsUmbrella && 1122040e1266SRichard Smith Header.Kind != Module::HK_Excluded) { 1123040e1266SRichard Smith // We expect more variation in mtime than size, so if we're given both, 1124040e1266SRichard Smith // use the mtime as the key. 1125040e1266SRichard Smith if (Header.ModTime) 1126040e1266SRichard Smith LazyHeadersByModTime[*Header.ModTime].push_back(Mod); 1127040e1266SRichard Smith else 1128040e1266SRichard Smith LazyHeadersBySize[*Header.Size].push_back(Mod); 1129040e1266SRichard Smith Mod->UnresolvedHeaders.push_back(Header); 1130040e1266SRichard Smith return; 1131040e1266SRichard Smith } 1132040e1266SRichard Smith 1133040e1266SRichard Smith // We don't have stat information or can't defer looking this file up. 1134040e1266SRichard Smith // Perform the lookup now. 11359f6020bcSBruno Cardoso Lopes resolveHeader(Mod, Header, NeedsFramework); 1136040e1266SRichard Smith } 1137040e1266SRichard Smith 1138040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const { 1139040e1266SRichard Smith auto BySize = LazyHeadersBySize.find(File->getSize()); 1140040e1266SRichard Smith if (BySize != LazyHeadersBySize.end()) { 1141040e1266SRichard Smith for (auto *M : BySize->second) 1142040e1266SRichard Smith resolveHeaderDirectives(M); 1143040e1266SRichard Smith LazyHeadersBySize.erase(BySize); 1144040e1266SRichard Smith } 1145040e1266SRichard Smith 1146040e1266SRichard Smith auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime()); 1147040e1266SRichard Smith if (ByModTime != LazyHeadersByModTime.end()) { 1148040e1266SRichard Smith for (auto *M : ByModTime->second) 1149040e1266SRichard Smith resolveHeaderDirectives(M); 1150040e1266SRichard Smith LazyHeadersByModTime.erase(ByModTime); 1151040e1266SRichard Smith } 1152040e1266SRichard Smith } 1153040e1266SRichard Smith 1154040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(Module *Mod) const { 11559f6020bcSBruno Cardoso Lopes bool NeedsFramework = false; 1156040e1266SRichard Smith for (auto &Header : Mod->UnresolvedHeaders) 1157040e1266SRichard Smith // This operation is logically const; we're just changing how we represent 1158040e1266SRichard Smith // the header information for this file. 11599f6020bcSBruno Cardoso Lopes const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header, NeedsFramework); 1160040e1266SRichard Smith Mod->UnresolvedHeaders.clear(); 11610e98d938SNAKAMURA Takumi } 1162202210b3SRichard Smith 11633c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header, 1164d8879c85SRichard Smith ModuleHeaderRole Role, bool Imported) { 1165386bb073SRichard Smith KnownHeader KH(Mod, Role); 11663c1a41adSRichard Smith 1167386bb073SRichard Smith // Only add each header to the headers list once. 1168386bb073SRichard Smith // FIXME: Should we diagnose if a header is listed twice in the 1169386bb073SRichard Smith // same module definition? 1170386bb073SRichard Smith auto &HeaderList = Headers[Header.Entry]; 1171386bb073SRichard Smith for (auto H : HeaderList) 1172386bb073SRichard Smith if (H == KH) 1173386bb073SRichard Smith return; 1174386bb073SRichard Smith 1175386bb073SRichard Smith HeaderList.push_back(KH); 11761ec383c7SPiotr Padlewski Mod->Headers[headerRoleToKind(Role)].push_back(Header); 1177386bb073SRichard Smith 11787e82e019SRichard Smith bool isCompilingModuleHeader = 1179bbcc9f04SRichard Smith LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule; 1180d8879c85SRichard Smith if (!Imported || isCompilingModuleHeader) { 1181d8879c85SRichard Smith // When we import HeaderFileInfo, the external source is expected to 1182d8879c85SRichard Smith // set the isModuleHeader flag itself. 1183d8879c85SRichard Smith HeaderInfo.MarkFileModuleHeader(Header.Entry, Role, 1184d8879c85SRichard Smith isCompilingModuleHeader); 1185d8879c85SRichard Smith } 1186e62cfd7cSBruno Cardoso Lopes 1187e62cfd7cSBruno Cardoso Lopes // Notify callbacks that we just added a new header. 1188e62cfd7cSBruno Cardoso Lopes for (const auto &Cb : Callbacks) 1189f0841790SBruno Cardoso Lopes Cb->moduleMapAddHeader(Header.Entry->getName()); 1190a89c5ac4SDouglas Gregor } 1191a89c5ac4SDouglas Gregor 11923c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) { 1193feb54b6dSRichard Smith // Add this as a known header so we won't implicitly add it to any 1194feb54b6dSRichard Smith // umbrella directory module. 1195feb54b6dSRichard Smith // FIXME: Should we only exclude it from umbrella modules within the 1196feb54b6dSRichard Smith // specified module? 11973c1a41adSRichard Smith (void) Headers[Header.Entry]; 11983c1a41adSRichard Smith 11993c1a41adSRichard Smith Mod->Headers[Module::HK_Excluded].push_back(std::move(Header)); 1200feb54b6dSRichard Smith } 1201feb54b6dSRichard Smith 1202514b636aSDouglas Gregor const FileEntry * 12034b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const { 12041f76c4e8SManuel Klimek if (Module->DefinitionLoc.isInvalid()) 1205d2d442caSCraig Topper return nullptr; 1206514b636aSDouglas Gregor 12071f76c4e8SManuel Klimek return SourceMgr.getFileEntryForID( 12081f76c4e8SManuel Klimek SourceMgr.getFileID(Module->DefinitionLoc)); 1209514b636aSDouglas Gregor } 1210514b636aSDouglas Gregor 12114b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const { 12129d6448b1SBen Langmuir if (M->IsInferred) { 12139d6448b1SBen Langmuir assert(InferredModuleAllowedBy.count(M) && "missing inferred module map"); 12149d6448b1SBen Langmuir return InferredModuleAllowedBy.find(M)->second; 12159d6448b1SBen Langmuir } 12169d6448b1SBen Langmuir return getContainingModuleMapFile(M); 12179d6448b1SBen Langmuir } 12189d6448b1SBen Langmuir 12199d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) { 12209d6448b1SBen Langmuir assert(M->IsInferred && "module not inferred"); 12219d6448b1SBen Langmuir InferredModuleAllowedBy[M] = ModMap; 12229d6448b1SBen Langmuir } 12239d6448b1SBen Langmuir 1224cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() { 1225718292f2SDouglas Gregor llvm::errs() << "Modules:"; 1226718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 1227718292f2SDouglas Gregor MEnd = Modules.end(); 1228718292f2SDouglas Gregor M != MEnd; ++M) 1229d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 1230718292f2SDouglas Gregor 1231718292f2SDouglas Gregor llvm::errs() << "Headers:"; 123259527666SDouglas Gregor for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end(); 1233718292f2SDouglas Gregor H != HEnd; ++H) { 123497da9178SDaniel Jasper llvm::errs() << " \"" << H->first->getName() << "\" -> "; 123597da9178SDaniel Jasper for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(), 123697da9178SDaniel Jasper E = H->second.end(); 123797da9178SDaniel Jasper I != E; ++I) { 123897da9178SDaniel Jasper if (I != H->second.begin()) 123997da9178SDaniel Jasper llvm::errs() << ","; 124097da9178SDaniel Jasper llvm::errs() << I->getModule()->getFullModuleName(); 124197da9178SDaniel Jasper } 124297da9178SDaniel Jasper llvm::errs() << "\n"; 1243718292f2SDouglas Gregor } 1244718292f2SDouglas Gregor } 1245718292f2SDouglas Gregor 12462b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) { 124742413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedExports); 124842413141SRichard Smith Mod->UnresolvedExports.clear(); 124942413141SRichard Smith for (auto &UE : Unresolved) { 125042413141SRichard Smith Module::ExportDecl Export = resolveExport(Mod, UE, Complain); 1251f5eedd05SDouglas Gregor if (Export.getPointer() || Export.getInt()) 12522b82c2a5SDouglas Gregor Mod->Exports.push_back(Export); 12532b82c2a5SDouglas Gregor else 125442413141SRichard Smith Mod->UnresolvedExports.push_back(UE); 12552b82c2a5SDouglas Gregor } 125642413141SRichard Smith return !Mod->UnresolvedExports.empty(); 12572b82c2a5SDouglas Gregor } 12582b82c2a5SDouglas Gregor 1259ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) { 126042413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedDirectUses); 126142413141SRichard Smith Mod->UnresolvedDirectUses.clear(); 126242413141SRichard Smith for (auto &UDU : Unresolved) { 126342413141SRichard Smith Module *DirectUse = resolveModuleId(UDU, Mod, Complain); 1264ba7f2f71SDaniel Jasper if (DirectUse) 1265ba7f2f71SDaniel Jasper Mod->DirectUses.push_back(DirectUse); 1266ba7f2f71SDaniel Jasper else 126742413141SRichard Smith Mod->UnresolvedDirectUses.push_back(UDU); 1268ba7f2f71SDaniel Jasper } 126942413141SRichard Smith return !Mod->UnresolvedDirectUses.empty(); 1270ba7f2f71SDaniel Jasper } 1271ba7f2f71SDaniel Jasper 1272fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) { 127342413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedConflicts); 127442413141SRichard Smith Mod->UnresolvedConflicts.clear(); 127542413141SRichard Smith for (auto &UC : Unresolved) { 127642413141SRichard Smith if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) { 1277fb912657SDouglas Gregor Module::Conflict Conflict; 1278fb912657SDouglas Gregor Conflict.Other = OtherMod; 127942413141SRichard Smith Conflict.Message = UC.Message; 1280fb912657SDouglas Gregor Mod->Conflicts.push_back(Conflict); 128142413141SRichard Smith } else 128242413141SRichard Smith Mod->UnresolvedConflicts.push_back(UC); 1283fb912657SDouglas Gregor } 128442413141SRichard Smith return !Mod->UnresolvedConflicts.empty(); 1285fb912657SDouglas Gregor } 1286fb912657SDouglas Gregor 1287718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1288718292f2SDouglas Gregor // Module map file parser 1289718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1290718292f2SDouglas Gregor 1291718292f2SDouglas Gregor namespace clang { 1292afd1b1c9SEugene Zelenko 12939fc8faf9SAdrian Prantl /// A token in a module map file. 1294718292f2SDouglas Gregor struct MMToken { 1295718292f2SDouglas Gregor enum TokenKind { 12961fb5c3a6SDouglas Gregor Comma, 129735b13eceSDouglas Gregor ConfigMacros, 1298fb912657SDouglas Gregor Conflict, 1299718292f2SDouglas Gregor EndOfFile, 1300718292f2SDouglas Gregor HeaderKeyword, 1301718292f2SDouglas Gregor Identifier, 1302a3feee2aSRichard Smith Exclaim, 130359527666SDouglas Gregor ExcludeKeyword, 1304718292f2SDouglas Gregor ExplicitKeyword, 13052b82c2a5SDouglas Gregor ExportKeyword, 1306f0b11de2SDouglas Gregor ExportAsKeyword, 130797292843SDaniel Jasper ExternKeyword, 1308755b2055SDouglas Gregor FrameworkKeyword, 13096ddfca91SDouglas Gregor LinkKeyword, 1310718292f2SDouglas Gregor ModuleKeyword, 13112b82c2a5SDouglas Gregor Period, 1312b53e5483SLawrence Crowl PrivateKeyword, 1313718292f2SDouglas Gregor UmbrellaKeyword, 1314ba7f2f71SDaniel Jasper UseKeyword, 13151fb5c3a6SDouglas Gregor RequiresKeyword, 13162b82c2a5SDouglas Gregor Star, 1317718292f2SDouglas Gregor StringLiteral, 1318040e1266SRichard Smith IntegerLiteral, 1319306d8920SRichard Smith TextualKeyword, 1320718292f2SDouglas Gregor LBrace, 1321a686e1b0SDouglas Gregor RBrace, 1322a686e1b0SDouglas Gregor LSquare, 1323a686e1b0SDouglas Gregor RSquare 1324718292f2SDouglas Gregor } Kind; 1325718292f2SDouglas Gregor 1326718292f2SDouglas Gregor unsigned Location; 1327718292f2SDouglas Gregor unsigned StringLength; 1328040e1266SRichard Smith union { 1329040e1266SRichard Smith // If Kind != IntegerLiteral. 1330718292f2SDouglas Gregor const char *StringData; 1331afd1b1c9SEugene Zelenko 1332040e1266SRichard Smith // If Kind == IntegerLiteral. 1333040e1266SRichard Smith uint64_t IntegerValue; 1334040e1266SRichard Smith }; 1335718292f2SDouglas Gregor 1336718292f2SDouglas Gregor void clear() { 1337718292f2SDouglas Gregor Kind = EndOfFile; 1338718292f2SDouglas Gregor Location = 0; 1339718292f2SDouglas Gregor StringLength = 0; 1340d2d442caSCraig Topper StringData = nullptr; 1341718292f2SDouglas Gregor } 1342718292f2SDouglas Gregor 1343718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 1344718292f2SDouglas Gregor 1345718292f2SDouglas Gregor SourceLocation getLocation() const { 1346718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 1347718292f2SDouglas Gregor } 1348718292f2SDouglas Gregor 1349040e1266SRichard Smith uint64_t getInteger() const { 1350040e1266SRichard Smith return Kind == IntegerLiteral ? IntegerValue : 0; 1351040e1266SRichard Smith } 1352040e1266SRichard Smith 1353718292f2SDouglas Gregor StringRef getString() const { 1354040e1266SRichard Smith return Kind == IntegerLiteral ? StringRef() 1355040e1266SRichard Smith : StringRef(StringData, StringLength); 1356718292f2SDouglas Gregor } 1357718292f2SDouglas Gregor }; 1358718292f2SDouglas Gregor 1359718292f2SDouglas Gregor class ModuleMapParser { 1360718292f2SDouglas Gregor Lexer &L; 1361718292f2SDouglas Gregor SourceManager &SourceMgr; 1362bc10b9fbSDouglas Gregor 13639fc8faf9SAdrian Prantl /// Default target information, used only for string literal 1364bc10b9fbSDouglas Gregor /// parsing. 1365bc10b9fbSDouglas Gregor const TargetInfo *Target; 1366bc10b9fbSDouglas Gregor 1367718292f2SDouglas Gregor DiagnosticsEngine &Diags; 1368718292f2SDouglas Gregor ModuleMap ⤅ 1369718292f2SDouglas Gregor 13709fc8faf9SAdrian Prantl /// The current module map file. 1371beee15e7SBen Langmuir const FileEntry *ModuleMapFile; 1372beee15e7SBen Langmuir 13739f6020bcSBruno Cardoso Lopes /// Source location of most recent parsed module declaration 13749f6020bcSBruno Cardoso Lopes SourceLocation CurrModuleDeclLoc; 13759f6020bcSBruno Cardoso Lopes 13769fc8faf9SAdrian Prantl /// The directory that file names in this module map file should 13779acb99e3SRichard Smith /// be resolved relative to. 13785257fc63SDouglas Gregor const DirectoryEntry *Directory; 13795257fc63SDouglas Gregor 13809fc8faf9SAdrian Prantl /// Whether this module map is in a system header directory. 1381963c5535SDouglas Gregor bool IsSystem; 1382963c5535SDouglas Gregor 13839fc8faf9SAdrian Prantl /// Whether an error occurred. 1384afd1b1c9SEugene Zelenko bool HadError = false; 1385718292f2SDouglas Gregor 13869fc8faf9SAdrian Prantl /// Stores string data for the various string literals referenced 1387718292f2SDouglas Gregor /// during parsing. 1388718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 1389718292f2SDouglas Gregor 13909fc8faf9SAdrian Prantl /// The current token. 1391718292f2SDouglas Gregor MMToken Tok; 1392718292f2SDouglas Gregor 13939fc8faf9SAdrian Prantl /// The active module. 1394afd1b1c9SEugene Zelenko Module *ActiveModule = nullptr; 1395718292f2SDouglas Gregor 13969fc8faf9SAdrian Prantl /// Whether a module uses the 'requires excluded' hack to mark its 13977ff29148SBen Langmuir /// contents as 'textual'. 13987ff29148SBen Langmuir /// 13997ff29148SBen Langmuir /// On older Darwin SDK versions, 'requires excluded' is used to mark the 14007ff29148SBen Langmuir /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as 14017ff29148SBen Langmuir /// non-modular headers. For backwards compatibility, we continue to 14027ff29148SBen Langmuir /// support this idiom for just these modules, and map the headers to 14037ff29148SBen Langmuir /// 'textual' to match the original intent. 14047ff29148SBen Langmuir llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack; 14057ff29148SBen Langmuir 14069fc8faf9SAdrian Prantl /// Consume the current token and return its location. 1407718292f2SDouglas Gregor SourceLocation consumeToken(); 1408718292f2SDouglas Gregor 14099fc8faf9SAdrian Prantl /// Skip tokens until we reach the a token with the given kind 1410718292f2SDouglas Gregor /// (or the end of the file). 1411718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 1412718292f2SDouglas Gregor 1413afd1b1c9SEugene Zelenko using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>; 1414afd1b1c9SEugene Zelenko 1415e7ab3669SDouglas Gregor bool parseModuleId(ModuleId &Id); 1416718292f2SDouglas Gregor void parseModuleDecl(); 141797292843SDaniel Jasper void parseExternModuleDecl(); 14181fb5c3a6SDouglas Gregor void parseRequiresDecl(); 1419afd1b1c9SEugene Zelenko void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc); 1420524e33e1SDouglas Gregor void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc); 14212b82c2a5SDouglas Gregor void parseExportDecl(); 1422f0b11de2SDouglas Gregor void parseExportAsDecl(); 1423ba7f2f71SDaniel Jasper void parseUseDecl(); 14246ddfca91SDouglas Gregor void parseLinkDecl(); 142535b13eceSDouglas Gregor void parseConfigMacros(); 1426fb912657SDouglas Gregor void parseConflict(); 14279194a91dSDouglas Gregor void parseInferredModuleDecl(bool Framework, bool Explicit); 1428c1d88ea5SBen Langmuir 14295f11e128SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra 14305f11e128SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH 14315f11e128SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written 14325f11e128SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits. 14335f11e128SBruno Cardoso Lopes void diagnosePrivateModules(SourceLocation ExplicitLoc, 14345f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc); 14355f11e128SBruno Cardoso Lopes 1436afd1b1c9SEugene Zelenko using Attributes = ModuleMap::Attributes; 1437afd1b1c9SEugene Zelenko 14384442605fSBill Wendling bool parseOptionalAttributes(Attributes &Attrs); 1439718292f2SDouglas Gregor 1440718292f2SDouglas Gregor public: 1441718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 14428587dfd9SBruno Cardoso Lopes const TargetInfo *Target, DiagnosticsEngine &Diags, 14438587dfd9SBruno Cardoso Lopes ModuleMap &Map, const FileEntry *ModuleMapFile, 1444c192d194SBruno Cardoso Lopes const DirectoryEntry *Directory, bool IsSystem) 1445bc10b9fbSDouglas Gregor : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map), 1446beee15e7SBen Langmuir ModuleMapFile(ModuleMapFile), Directory(Directory), 1447c192d194SBruno Cardoso Lopes IsSystem(IsSystem) { 1448718292f2SDouglas Gregor Tok.clear(); 1449718292f2SDouglas Gregor consumeToken(); 1450718292f2SDouglas Gregor } 1451718292f2SDouglas Gregor 1452718292f2SDouglas Gregor bool parseModuleMapFile(); 14538128f332SRichard Smith 14548128f332SRichard Smith bool terminatedByDirective() { return false; } 14558128f332SRichard Smith SourceLocation getLocation() { return Tok.getLocation(); } 1456718292f2SDouglas Gregor }; 1457afd1b1c9SEugene Zelenko 1458afd1b1c9SEugene Zelenko } // namespace clang 1459718292f2SDouglas Gregor 1460718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 1461718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 1462718292f2SDouglas Gregor 14638128f332SRichard Smith retry: 14648128f332SRichard Smith Tok.clear(); 1465718292f2SDouglas Gregor Token LToken; 1466718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 1467718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 1468718292f2SDouglas Gregor switch (LToken.getKind()) { 14692d57cea2SAlp Toker case tok::raw_identifier: { 14702d57cea2SAlp Toker StringRef RI = LToken.getRawIdentifier(); 14712d57cea2SAlp Toker Tok.StringData = RI.data(); 14722d57cea2SAlp Toker Tok.StringLength = RI.size(); 14732d57cea2SAlp Toker Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI) 147435b13eceSDouglas Gregor .Case("config_macros", MMToken::ConfigMacros) 1475fb912657SDouglas Gregor .Case("conflict", MMToken::Conflict) 147659527666SDouglas Gregor .Case("exclude", MMToken::ExcludeKeyword) 1477718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 14782b82c2a5SDouglas Gregor .Case("export", MMToken::ExportKeyword) 1479f0b11de2SDouglas Gregor .Case("export_as", MMToken::ExportAsKeyword) 148097292843SDaniel Jasper .Case("extern", MMToken::ExternKeyword) 1481755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 148235b13eceSDouglas Gregor .Case("header", MMToken::HeaderKeyword) 14836ddfca91SDouglas Gregor .Case("link", MMToken::LinkKeyword) 1484718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 1485b53e5483SLawrence Crowl .Case("private", MMToken::PrivateKeyword) 14861fb5c3a6SDouglas Gregor .Case("requires", MMToken::RequiresKeyword) 1487306d8920SRichard Smith .Case("textual", MMToken::TextualKeyword) 1488718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 1489ba7f2f71SDaniel Jasper .Case("use", MMToken::UseKeyword) 1490718292f2SDouglas Gregor .Default(MMToken::Identifier); 1491718292f2SDouglas Gregor break; 14922d57cea2SAlp Toker } 1493718292f2SDouglas Gregor 14941fb5c3a6SDouglas Gregor case tok::comma: 14951fb5c3a6SDouglas Gregor Tok.Kind = MMToken::Comma; 14961fb5c3a6SDouglas Gregor break; 14971fb5c3a6SDouglas Gregor 1498718292f2SDouglas Gregor case tok::eof: 1499718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 1500718292f2SDouglas Gregor break; 1501718292f2SDouglas Gregor 1502718292f2SDouglas Gregor case tok::l_brace: 1503718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 1504718292f2SDouglas Gregor break; 1505718292f2SDouglas Gregor 1506a686e1b0SDouglas Gregor case tok::l_square: 1507a686e1b0SDouglas Gregor Tok.Kind = MMToken::LSquare; 1508a686e1b0SDouglas Gregor break; 1509a686e1b0SDouglas Gregor 15102b82c2a5SDouglas Gregor case tok::period: 15112b82c2a5SDouglas Gregor Tok.Kind = MMToken::Period; 15122b82c2a5SDouglas Gregor break; 15132b82c2a5SDouglas Gregor 1514718292f2SDouglas Gregor case tok::r_brace: 1515718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 1516718292f2SDouglas Gregor break; 1517718292f2SDouglas Gregor 1518a686e1b0SDouglas Gregor case tok::r_square: 1519a686e1b0SDouglas Gregor Tok.Kind = MMToken::RSquare; 1520a686e1b0SDouglas Gregor break; 1521a686e1b0SDouglas Gregor 15222b82c2a5SDouglas Gregor case tok::star: 15232b82c2a5SDouglas Gregor Tok.Kind = MMToken::Star; 15242b82c2a5SDouglas Gregor break; 15252b82c2a5SDouglas Gregor 1526a3feee2aSRichard Smith case tok::exclaim: 1527a3feee2aSRichard Smith Tok.Kind = MMToken::Exclaim; 1528a3feee2aSRichard Smith break; 1529a3feee2aSRichard Smith 1530718292f2SDouglas Gregor case tok::string_literal: { 1531d67aea28SRichard Smith if (LToken.hasUDSuffix()) { 1532d67aea28SRichard Smith Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl); 1533d67aea28SRichard Smith HadError = true; 1534d67aea28SRichard Smith goto retry; 1535d67aea28SRichard Smith } 1536d67aea28SRichard Smith 1537718292f2SDouglas Gregor // Parse the string literal. 1538718292f2SDouglas Gregor LangOptions LangOpts; 15399d5583efSCraig Topper StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target); 1540718292f2SDouglas Gregor if (StringLiteral.hadError) 1541718292f2SDouglas Gregor goto retry; 1542718292f2SDouglas Gregor 1543718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 1544718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 1545718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 1546718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 1547718292f2SDouglas Gregor Saved[Length] = 0; 1548718292f2SDouglas Gregor 1549718292f2SDouglas Gregor // Form the token. 1550718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 1551718292f2SDouglas Gregor Tok.StringData = Saved; 1552718292f2SDouglas Gregor Tok.StringLength = Length; 1553718292f2SDouglas Gregor break; 1554718292f2SDouglas Gregor } 1555718292f2SDouglas Gregor 1556040e1266SRichard Smith case tok::numeric_constant: { 1557040e1266SRichard Smith // We don't support any suffixes or other complications. 1558040e1266SRichard Smith SmallString<32> SpellingBuffer; 1559040e1266SRichard Smith SpellingBuffer.resize(LToken.getLength() + 1); 1560040e1266SRichard Smith const char *Start = SpellingBuffer.data(); 1561040e1266SRichard Smith unsigned Length = 1562040e1266SRichard Smith Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts()); 1563040e1266SRichard Smith uint64_t Value; 1564040e1266SRichard Smith if (StringRef(Start, Length).getAsInteger(0, Value)) { 1565040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1566040e1266SRichard Smith HadError = true; 1567040e1266SRichard Smith goto retry; 1568040e1266SRichard Smith } 1569040e1266SRichard Smith 1570040e1266SRichard Smith Tok.Kind = MMToken::IntegerLiteral; 1571040e1266SRichard Smith Tok.IntegerValue = Value; 1572040e1266SRichard Smith break; 1573040e1266SRichard Smith } 1574040e1266SRichard Smith 1575718292f2SDouglas Gregor case tok::comment: 1576718292f2SDouglas Gregor goto retry; 1577718292f2SDouglas Gregor 15788128f332SRichard Smith case tok::hash: 15798128f332SRichard Smith // A module map can be terminated prematurely by 15808128f332SRichard Smith // #pragma clang module contents 15818128f332SRichard Smith // When building the module, we'll treat the rest of the file as the 15828128f332SRichard Smith // contents of the module. 15838128f332SRichard Smith { 15848128f332SRichard Smith auto NextIsIdent = [&](StringRef Str) -> bool { 15858128f332SRichard Smith L.LexFromRawLexer(LToken); 15868128f332SRichard Smith return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) && 15878128f332SRichard Smith LToken.getRawIdentifier() == Str; 15888128f332SRichard Smith }; 15898128f332SRichard Smith if (NextIsIdent("pragma") && NextIsIdent("clang") && 15908128f332SRichard Smith NextIsIdent("module") && NextIsIdent("contents")) { 15918128f332SRichard Smith Tok.Kind = MMToken::EndOfFile; 15928128f332SRichard Smith break; 15938128f332SRichard Smith } 15948128f332SRichard Smith } 15958128f332SRichard Smith LLVM_FALLTHROUGH; 15968128f332SRichard Smith 1597718292f2SDouglas Gregor default: 15988128f332SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1599718292f2SDouglas Gregor HadError = true; 1600718292f2SDouglas Gregor goto retry; 1601718292f2SDouglas Gregor } 1602718292f2SDouglas Gregor 1603718292f2SDouglas Gregor return Result; 1604718292f2SDouglas Gregor } 1605718292f2SDouglas Gregor 1606718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 1607718292f2SDouglas Gregor unsigned braceDepth = 0; 1608a686e1b0SDouglas Gregor unsigned squareDepth = 0; 1609718292f2SDouglas Gregor do { 1610718292f2SDouglas Gregor switch (Tok.Kind) { 1611718292f2SDouglas Gregor case MMToken::EndOfFile: 1612718292f2SDouglas Gregor return; 1613718292f2SDouglas Gregor 1614718292f2SDouglas Gregor case MMToken::LBrace: 1615a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1616718292f2SDouglas Gregor return; 1617718292f2SDouglas Gregor 1618718292f2SDouglas Gregor ++braceDepth; 1619718292f2SDouglas Gregor break; 1620718292f2SDouglas Gregor 1621a686e1b0SDouglas Gregor case MMToken::LSquare: 1622a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1623a686e1b0SDouglas Gregor return; 1624a686e1b0SDouglas Gregor 1625a686e1b0SDouglas Gregor ++squareDepth; 1626a686e1b0SDouglas Gregor break; 1627a686e1b0SDouglas Gregor 1628718292f2SDouglas Gregor case MMToken::RBrace: 1629718292f2SDouglas Gregor if (braceDepth > 0) 1630718292f2SDouglas Gregor --braceDepth; 1631718292f2SDouglas Gregor else if (Tok.is(K)) 1632718292f2SDouglas Gregor return; 1633718292f2SDouglas Gregor break; 1634718292f2SDouglas Gregor 1635a686e1b0SDouglas Gregor case MMToken::RSquare: 1636a686e1b0SDouglas Gregor if (squareDepth > 0) 1637a686e1b0SDouglas Gregor --squareDepth; 1638a686e1b0SDouglas Gregor else if (Tok.is(K)) 1639a686e1b0SDouglas Gregor return; 1640a686e1b0SDouglas Gregor break; 1641a686e1b0SDouglas Gregor 1642718292f2SDouglas Gregor default: 1643a686e1b0SDouglas Gregor if (braceDepth == 0 && squareDepth == 0 && Tok.is(K)) 1644718292f2SDouglas Gregor return; 1645718292f2SDouglas Gregor break; 1646718292f2SDouglas Gregor } 1647718292f2SDouglas Gregor 1648718292f2SDouglas Gregor consumeToken(); 1649718292f2SDouglas Gregor } while (true); 1650718292f2SDouglas Gregor } 1651718292f2SDouglas Gregor 16529fc8faf9SAdrian Prantl /// Parse a module-id. 1653e7ab3669SDouglas Gregor /// 1654e7ab3669SDouglas Gregor /// module-id: 1655e7ab3669SDouglas Gregor /// identifier 1656e7ab3669SDouglas Gregor /// identifier '.' module-id 1657e7ab3669SDouglas Gregor /// 1658e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise. 1659e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) { 1660e7ab3669SDouglas Gregor Id.clear(); 1661e7ab3669SDouglas Gregor do { 16623cd34c76SDaniel Jasper if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) { 1663e7ab3669SDouglas Gregor Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation())); 1664e7ab3669SDouglas Gregor consumeToken(); 1665e7ab3669SDouglas Gregor } else { 1666e7ab3669SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 1667e7ab3669SDouglas Gregor return true; 1668e7ab3669SDouglas Gregor } 1669e7ab3669SDouglas Gregor 1670e7ab3669SDouglas Gregor if (!Tok.is(MMToken::Period)) 1671e7ab3669SDouglas Gregor break; 1672e7ab3669SDouglas Gregor 1673e7ab3669SDouglas Gregor consumeToken(); 1674e7ab3669SDouglas Gregor } while (true); 1675e7ab3669SDouglas Gregor 1676e7ab3669SDouglas Gregor return false; 1677e7ab3669SDouglas Gregor } 1678e7ab3669SDouglas Gregor 1679a686e1b0SDouglas Gregor namespace { 1680afd1b1c9SEugene Zelenko 16819fc8faf9SAdrian Prantl /// Enumerates the known attributes. 1682a686e1b0SDouglas Gregor enum AttributeKind { 16839fc8faf9SAdrian Prantl /// An unknown attribute. 1684a686e1b0SDouglas Gregor AT_unknown, 1685afd1b1c9SEugene Zelenko 16869fc8faf9SAdrian Prantl /// The 'system' attribute. 168735b13eceSDouglas Gregor AT_system, 1688afd1b1c9SEugene Zelenko 16899fc8faf9SAdrian Prantl /// The 'extern_c' attribute. 169077944868SRichard Smith AT_extern_c, 1691afd1b1c9SEugene Zelenko 16929fc8faf9SAdrian Prantl /// The 'exhaustive' attribute. 1693ed84df00SBruno Cardoso Lopes AT_exhaustive, 1694afd1b1c9SEugene Zelenko 16959fc8faf9SAdrian Prantl /// The 'no_undeclared_includes' attribute. 1696ed84df00SBruno Cardoso Lopes AT_no_undeclared_includes 1697a686e1b0SDouglas Gregor }; 1698afd1b1c9SEugene Zelenko 1699afd1b1c9SEugene Zelenko } // namespace 1700a686e1b0SDouglas Gregor 170129729919SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra 170229729919SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH 170329729919SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written 170429729919SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits. 17055f11e128SBruno Cardoso Lopes void ModuleMapParser::diagnosePrivateModules(SourceLocation ExplicitLoc, 17065f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc) { 170729729919SBruno Cardoso Lopes auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical, 17087d29486dSBruno Cardoso Lopes const Module *M, SourceRange ReplLoc) { 170929729919SBruno Cardoso Lopes auto D = Diags.Report(ActiveModule->DefinitionLoc, 171029729919SBruno Cardoso Lopes diag::note_mmap_rename_top_level_private_module); 171129729919SBruno Cardoso Lopes D << BadName << M->Name; 17127d29486dSBruno Cardoso Lopes D << FixItHint::CreateReplacement(ReplLoc, Canonical); 171329729919SBruno Cardoso Lopes }; 171429729919SBruno Cardoso Lopes 171529729919SBruno Cardoso Lopes for (auto E = Map.module_begin(); E != Map.module_end(); ++E) { 171629729919SBruno Cardoso Lopes auto const *M = E->getValue(); 171729729919SBruno Cardoso Lopes if (M->Directory != ActiveModule->Directory) 171829729919SBruno Cardoso Lopes continue; 171929729919SBruno Cardoso Lopes 172029729919SBruno Cardoso Lopes SmallString<128> FullName(ActiveModule->getFullModuleName()); 172129729919SBruno Cardoso Lopes if (!FullName.startswith(M->Name) && !FullName.endswith("Private")) 172229729919SBruno Cardoso Lopes continue; 17235f11e128SBruno Cardoso Lopes SmallString<128> FixedPrivModDecl; 172429729919SBruno Cardoso Lopes SmallString<128> Canonical(M->Name); 172529729919SBruno Cardoso Lopes Canonical.append("_Private"); 172629729919SBruno Cardoso Lopes 172729729919SBruno Cardoso Lopes // Foo.Private -> Foo_Private 172829729919SBruno Cardoso Lopes if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent && 172929729919SBruno Cardoso Lopes M->Name == ActiveModule->Parent->Name) { 173029729919SBruno Cardoso Lopes Diags.Report(ActiveModule->DefinitionLoc, 173129729919SBruno Cardoso Lopes diag::warn_mmap_mismatched_private_submodule) 173229729919SBruno Cardoso Lopes << FullName; 17335f11e128SBruno Cardoso Lopes 17345f11e128SBruno Cardoso Lopes SourceLocation FixItInitBegin = CurrModuleDeclLoc; 17355f11e128SBruno Cardoso Lopes if (FrameworkLoc.isValid()) 17365f11e128SBruno Cardoso Lopes FixItInitBegin = FrameworkLoc; 17375f11e128SBruno Cardoso Lopes if (ExplicitLoc.isValid()) 17385f11e128SBruno Cardoso Lopes FixItInitBegin = ExplicitLoc; 17395f11e128SBruno Cardoso Lopes 17405f11e128SBruno Cardoso Lopes if (FrameworkLoc.isValid() || ActiveModule->Parent->IsFramework) 17415f11e128SBruno Cardoso Lopes FixedPrivModDecl.append("framework "); 17425f11e128SBruno Cardoso Lopes FixedPrivModDecl.append("module "); 17435f11e128SBruno Cardoso Lopes FixedPrivModDecl.append(Canonical); 17445f11e128SBruno Cardoso Lopes 17455f11e128SBruno Cardoso Lopes GenNoteAndFixIt(FullName, FixedPrivModDecl, M, 17465f11e128SBruno Cardoso Lopes SourceRange(FixItInitBegin, ActiveModule->DefinitionLoc)); 174729729919SBruno Cardoso Lopes continue; 174829729919SBruno Cardoso Lopes } 174929729919SBruno Cardoso Lopes 175029729919SBruno Cardoso Lopes // FooPrivate and whatnots -> Foo_Private 175129729919SBruno Cardoso Lopes if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name && 175229729919SBruno Cardoso Lopes ActiveModule->Name != Canonical) { 175329729919SBruno Cardoso Lopes Diags.Report(ActiveModule->DefinitionLoc, 175429729919SBruno Cardoso Lopes diag::warn_mmap_mismatched_private_module_name) 175529729919SBruno Cardoso Lopes << ActiveModule->Name; 17567d29486dSBruno Cardoso Lopes GenNoteAndFixIt(ActiveModule->Name, Canonical, M, 17577d29486dSBruno Cardoso Lopes SourceRange(ActiveModule->DefinitionLoc)); 175829729919SBruno Cardoso Lopes } 175929729919SBruno Cardoso Lopes } 176029729919SBruno Cardoso Lopes } 176129729919SBruno Cardoso Lopes 17629fc8faf9SAdrian Prantl /// Parse a module declaration. 1763718292f2SDouglas Gregor /// 1764718292f2SDouglas Gregor /// module-declaration: 176597292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 1766a686e1b0SDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt] 1767a686e1b0SDouglas Gregor /// { module-member* } 1768a686e1b0SDouglas Gregor /// 1769718292f2SDouglas Gregor /// module-member: 17701fb5c3a6SDouglas Gregor /// requires-declaration 1771718292f2SDouglas Gregor /// header-declaration 1772e7ab3669SDouglas Gregor /// submodule-declaration 17732b82c2a5SDouglas Gregor /// export-declaration 1774f0b11de2SDouglas Gregor /// export-as-declaration 17756ddfca91SDouglas Gregor /// link-declaration 177673441091SDouglas Gregor /// 177773441091SDouglas Gregor /// submodule-declaration: 177873441091SDouglas Gregor /// module-declaration 177973441091SDouglas Gregor /// inferred-submodule-declaration 1780718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 1781755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 178297292843SDaniel Jasper Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword)); 178397292843SDaniel Jasper if (Tok.is(MMToken::ExternKeyword)) { 178497292843SDaniel Jasper parseExternModuleDecl(); 178597292843SDaniel Jasper return; 178697292843SDaniel Jasper } 178797292843SDaniel Jasper 1788f2161a70SDouglas Gregor // Parse 'explicit' or 'framework' keyword, if present. 1789e7ab3669SDouglas Gregor SourceLocation ExplicitLoc; 17905f11e128SBruno Cardoso Lopes SourceLocation FrameworkLoc; 1791718292f2SDouglas Gregor bool Explicit = false; 1792f2161a70SDouglas Gregor bool Framework = false; 1793755b2055SDouglas Gregor 1794f2161a70SDouglas Gregor // Parse 'explicit' keyword, if present. 1795f2161a70SDouglas Gregor if (Tok.is(MMToken::ExplicitKeyword)) { 1796e7ab3669SDouglas Gregor ExplicitLoc = consumeToken(); 1797f2161a70SDouglas Gregor Explicit = true; 1798f2161a70SDouglas Gregor } 1799f2161a70SDouglas Gregor 1800f2161a70SDouglas Gregor // Parse 'framework' keyword, if present. 1801755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 18025f11e128SBruno Cardoso Lopes FrameworkLoc = consumeToken(); 1803755b2055SDouglas Gregor Framework = true; 1804755b2055SDouglas Gregor } 1805718292f2SDouglas Gregor 1806718292f2SDouglas Gregor // Parse 'module' keyword. 1807718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 1808d6343c99SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 1809718292f2SDouglas Gregor consumeToken(); 1810718292f2SDouglas Gregor HadError = true; 1811718292f2SDouglas Gregor return; 1812718292f2SDouglas Gregor } 18139f6020bcSBruno Cardoso Lopes CurrModuleDeclLoc = consumeToken(); // 'module' keyword 1814718292f2SDouglas Gregor 181573441091SDouglas Gregor // If we have a wildcard for the module name, this is an inferred submodule. 181673441091SDouglas Gregor // Parse it. 181773441091SDouglas Gregor if (Tok.is(MMToken::Star)) 18189194a91dSDouglas Gregor return parseInferredModuleDecl(Framework, Explicit); 181973441091SDouglas Gregor 1820718292f2SDouglas Gregor // Parse the module name. 1821e7ab3669SDouglas Gregor ModuleId Id; 1822e7ab3669SDouglas Gregor if (parseModuleId(Id)) { 1823718292f2SDouglas Gregor HadError = true; 1824718292f2SDouglas Gregor return; 1825718292f2SDouglas Gregor } 1826e7ab3669SDouglas Gregor 1827e7ab3669SDouglas Gregor if (ActiveModule) { 1828e7ab3669SDouglas Gregor if (Id.size() > 1) { 1829e7ab3669SDouglas Gregor Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id) 1830e7ab3669SDouglas Gregor << SourceRange(Id.front().second, Id.back().second); 1831e7ab3669SDouglas Gregor 1832e7ab3669SDouglas Gregor HadError = true; 1833e7ab3669SDouglas Gregor return; 1834e7ab3669SDouglas Gregor } 1835e7ab3669SDouglas Gregor } else if (Id.size() == 1 && Explicit) { 1836e7ab3669SDouglas Gregor // Top-level modules can't be explicit. 1837e7ab3669SDouglas Gregor Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level); 1838e7ab3669SDouglas Gregor Explicit = false; 1839e7ab3669SDouglas Gregor ExplicitLoc = SourceLocation(); 1840e7ab3669SDouglas Gregor HadError = true; 1841e7ab3669SDouglas Gregor } 1842e7ab3669SDouglas Gregor 1843e7ab3669SDouglas Gregor Module *PreviousActiveModule = ActiveModule; 1844e7ab3669SDouglas Gregor if (Id.size() > 1) { 1845e7ab3669SDouglas Gregor // This module map defines a submodule. Go find the module of which it 1846e7ab3669SDouglas Gregor // is a submodule. 1847d2d442caSCraig Topper ActiveModule = nullptr; 18484b8a9e95SBen Langmuir const Module *TopLevelModule = nullptr; 1849e7ab3669SDouglas Gregor for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) { 1850e7ab3669SDouglas Gregor if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) { 18514b8a9e95SBen Langmuir if (I == 0) 18524b8a9e95SBen Langmuir TopLevelModule = Next; 1853e7ab3669SDouglas Gregor ActiveModule = Next; 1854e7ab3669SDouglas Gregor continue; 1855e7ab3669SDouglas Gregor } 1856e7ab3669SDouglas Gregor 1857e7ab3669SDouglas Gregor if (ActiveModule) { 1858e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified) 18595b5d21eaSRichard Smith << Id[I].first 18605b5d21eaSRichard Smith << ActiveModule->getTopLevelModule()->getFullModuleName(); 1861e7ab3669SDouglas Gregor } else { 1862e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_expected_module_name); 1863e7ab3669SDouglas Gregor } 1864e7ab3669SDouglas Gregor HadError = true; 1865e7ab3669SDouglas Gregor return; 1866e7ab3669SDouglas Gregor } 18674b8a9e95SBen Langmuir 18684b8a9e95SBen Langmuir if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) { 18694b8a9e95SBen Langmuir assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) && 18704b8a9e95SBen Langmuir "submodule defined in same file as 'module *' that allowed its " 18714b8a9e95SBen Langmuir "top-level module"); 18724b8a9e95SBen Langmuir Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile); 18734b8a9e95SBen Langmuir } 1874e7ab3669SDouglas Gregor } 1875e7ab3669SDouglas Gregor 1876e7ab3669SDouglas Gregor StringRef ModuleName = Id.back().first; 1877e7ab3669SDouglas Gregor SourceLocation ModuleNameLoc = Id.back().second; 1878718292f2SDouglas Gregor 1879a686e1b0SDouglas Gregor // Parse the optional attribute list. 18804442605fSBill Wendling Attributes Attrs; 18815d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 18825d29dee0SDavide Italiano return; 18835d29dee0SDavide Italiano 1884718292f2SDouglas Gregor // Parse the opening brace. 1885718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 1886718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 1887718292f2SDouglas Gregor << ModuleName; 1888718292f2SDouglas Gregor HadError = true; 1889718292f2SDouglas Gregor return; 1890718292f2SDouglas Gregor } 1891718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 1892718292f2SDouglas Gregor 1893718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 18948587dfd9SBruno Cardoso Lopes Module *ShadowingModule = nullptr; 1895eb90e830SDouglas Gregor if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { 18964a3751ffSRichard Smith // We might see a (re)definition of a module that we already have a 18974a3751ffSRichard Smith // definition for in two cases: 18984a3751ffSRichard Smith // - If we loaded one definition from an AST file and we've just found a 18994a3751ffSRichard Smith // corresponding definition in a module map file, or 19004a3751ffSRichard Smith bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid(); 19014a3751ffSRichard Smith // - If we're building a (preprocessed) module and we've just loaded the 19024a3751ffSRichard Smith // module map file from which it was created. 19034a3751ffSRichard Smith bool ParsedAsMainInput = 19044a3751ffSRichard Smith Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap && 19054a3751ffSRichard Smith Map.LangOpts.CurrentModule == ModuleName && 19064a3751ffSRichard Smith SourceMgr.getDecomposedLoc(ModuleNameLoc).first != 19074a3751ffSRichard Smith SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first; 19084a3751ffSRichard Smith if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) { 1909fcc54a3bSDouglas Gregor // Skip the module definition. 1910fcc54a3bSDouglas Gregor skipUntil(MMToken::RBrace); 1911fcc54a3bSDouglas Gregor if (Tok.is(MMToken::RBrace)) 1912fcc54a3bSDouglas Gregor consumeToken(); 1913fcc54a3bSDouglas Gregor else { 1914fcc54a3bSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 1915fcc54a3bSDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 1916fcc54a3bSDouglas Gregor HadError = true; 1917fcc54a3bSDouglas Gregor } 1918fcc54a3bSDouglas Gregor return; 1919fcc54a3bSDouglas Gregor } 1920fcc54a3bSDouglas Gregor 1921c192d194SBruno Cardoso Lopes if (!Existing->Parent && Map.mayShadowNewModule(Existing)) { 19228587dfd9SBruno Cardoso Lopes ShadowingModule = Existing; 19238587dfd9SBruno Cardoso Lopes } else { 19248587dfd9SBruno Cardoso Lopes // This is not a shawdowed module decl, it is an illegal redefinition. 1925718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 1926718292f2SDouglas Gregor << ModuleName; 1927eb90e830SDouglas Gregor Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition); 1928718292f2SDouglas Gregor 1929718292f2SDouglas Gregor // Skip the module definition. 1930718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 1931718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 1932718292f2SDouglas Gregor consumeToken(); 1933718292f2SDouglas Gregor 1934718292f2SDouglas Gregor HadError = true; 1935718292f2SDouglas Gregor return; 1936718292f2SDouglas Gregor } 19378587dfd9SBruno Cardoso Lopes } 1938718292f2SDouglas Gregor 1939718292f2SDouglas Gregor // Start defining this module. 19408587dfd9SBruno Cardoso Lopes if (ShadowingModule) { 19418587dfd9SBruno Cardoso Lopes ActiveModule = 19428587dfd9SBruno Cardoso Lopes Map.createShadowedModule(ModuleName, Framework, ShadowingModule); 19438587dfd9SBruno Cardoso Lopes } else { 1944c192d194SBruno Cardoso Lopes ActiveModule = 1945c192d194SBruno Cardoso Lopes Map.findOrCreateModule(ModuleName, ActiveModule, Framework, Explicit) 19468587dfd9SBruno Cardoso Lopes .first; 19478587dfd9SBruno Cardoso Lopes } 19488587dfd9SBruno Cardoso Lopes 1949eb90e830SDouglas Gregor ActiveModule->DefinitionLoc = ModuleNameLoc; 1950963c5535SDouglas Gregor if (Attrs.IsSystem || IsSystem) 1951a686e1b0SDouglas Gregor ActiveModule->IsSystem = true; 195277944868SRichard Smith if (Attrs.IsExternC) 195377944868SRichard Smith ActiveModule->IsExternC = true; 1954ed84df00SBruno Cardoso Lopes if (Attrs.NoUndeclaredIncludes || 1955ed84df00SBruno Cardoso Lopes (!ActiveModule->Parent && ModuleName == "Darwin")) 1956ed84df00SBruno Cardoso Lopes ActiveModule->NoUndeclaredIncludes = true; 19573c1a41adSRichard Smith ActiveModule->Directory = Directory; 1958718292f2SDouglas Gregor 195990b0a1fcSJordan Rose StringRef MapFileName(ModuleMapFile->getName()); 196090b0a1fcSJordan Rose if (MapFileName.endswith("module.private.modulemap") || 196190b0a1fcSJordan Rose MapFileName.endswith("module_private.map")) { 196290b0a1fcSJordan Rose ActiveModule->ModuleMapIsPrivate = true; 196390b0a1fcSJordan Rose } 196429729919SBruno Cardoso Lopes 196529729919SBruno Cardoso Lopes // Private modules named as FooPrivate, Foo.Private or similar are likely a 196629729919SBruno Cardoso Lopes // user error; provide warnings, notes and fixits to direct users to use 196729729919SBruno Cardoso Lopes // Foo_Private instead. 196829729919SBruno Cardoso Lopes SourceLocation StartLoc = 196929729919SBruno Cardoso Lopes SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()); 197029729919SBruno Cardoso Lopes if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && 197129729919SBruno Cardoso Lopes !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule, 197229729919SBruno Cardoso Lopes StartLoc) && 197329729919SBruno Cardoso Lopes !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name, 197429729919SBruno Cardoso Lopes StartLoc) && 197590b0a1fcSJordan Rose ActiveModule->ModuleMapIsPrivate) 19765f11e128SBruno Cardoso Lopes diagnosePrivateModules(ExplicitLoc, FrameworkLoc); 19774d867640SGraydon Hoare 1978718292f2SDouglas Gregor bool Done = false; 1979718292f2SDouglas Gregor do { 1980718292f2SDouglas Gregor switch (Tok.Kind) { 1981718292f2SDouglas Gregor case MMToken::EndOfFile: 1982718292f2SDouglas Gregor case MMToken::RBrace: 1983718292f2SDouglas Gregor Done = true; 1984718292f2SDouglas Gregor break; 1985718292f2SDouglas Gregor 198635b13eceSDouglas Gregor case MMToken::ConfigMacros: 198735b13eceSDouglas Gregor parseConfigMacros(); 198835b13eceSDouglas Gregor break; 198935b13eceSDouglas Gregor 1990fb912657SDouglas Gregor case MMToken::Conflict: 1991fb912657SDouglas Gregor parseConflict(); 1992fb912657SDouglas Gregor break; 1993fb912657SDouglas Gregor 1994718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 199597292843SDaniel Jasper case MMToken::ExternKeyword: 1996f2161a70SDouglas Gregor case MMToken::FrameworkKeyword: 1997718292f2SDouglas Gregor case MMToken::ModuleKeyword: 1998718292f2SDouglas Gregor parseModuleDecl(); 1999718292f2SDouglas Gregor break; 2000718292f2SDouglas Gregor 20012b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 20022b82c2a5SDouglas Gregor parseExportDecl(); 20032b82c2a5SDouglas Gregor break; 20042b82c2a5SDouglas Gregor 2005f0b11de2SDouglas Gregor case MMToken::ExportAsKeyword: 2006f0b11de2SDouglas Gregor parseExportAsDecl(); 2007f0b11de2SDouglas Gregor break; 2008f0b11de2SDouglas Gregor 2009ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 2010ba7f2f71SDaniel Jasper parseUseDecl(); 2011ba7f2f71SDaniel Jasper break; 2012ba7f2f71SDaniel Jasper 20131fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 20141fb5c3a6SDouglas Gregor parseRequiresDecl(); 20151fb5c3a6SDouglas Gregor break; 20161fb5c3a6SDouglas Gregor 2017202210b3SRichard Smith case MMToken::TextualKeyword: 2018202210b3SRichard Smith parseHeaderDecl(MMToken::TextualKeyword, consumeToken()); 2019306d8920SRichard Smith break; 2020306d8920SRichard Smith 2021524e33e1SDouglas Gregor case MMToken::UmbrellaKeyword: { 2022524e33e1SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 2023524e33e1SDouglas Gregor if (Tok.is(MMToken::HeaderKeyword)) 2024b53e5483SLawrence Crowl parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc); 2025524e33e1SDouglas Gregor else 2026524e33e1SDouglas Gregor parseUmbrellaDirDecl(UmbrellaLoc); 2027718292f2SDouglas Gregor break; 2028524e33e1SDouglas Gregor } 2029718292f2SDouglas Gregor 2030202210b3SRichard Smith case MMToken::ExcludeKeyword: 2031202210b3SRichard Smith parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken()); 203259527666SDouglas Gregor break; 203359527666SDouglas Gregor 2034202210b3SRichard Smith case MMToken::PrivateKeyword: 2035202210b3SRichard Smith parseHeaderDecl(MMToken::PrivateKeyword, consumeToken()); 2036b53e5483SLawrence Crowl break; 2037b53e5483SLawrence Crowl 2038322f633cSDouglas Gregor case MMToken::HeaderKeyword: 2039202210b3SRichard Smith parseHeaderDecl(MMToken::HeaderKeyword, consumeToken()); 2040718292f2SDouglas Gregor break; 2041718292f2SDouglas Gregor 20426ddfca91SDouglas Gregor case MMToken::LinkKeyword: 20436ddfca91SDouglas Gregor parseLinkDecl(); 20446ddfca91SDouglas Gregor break; 20456ddfca91SDouglas Gregor 2046718292f2SDouglas Gregor default: 2047718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 2048718292f2SDouglas Gregor consumeToken(); 2049718292f2SDouglas Gregor break; 2050718292f2SDouglas Gregor } 2051718292f2SDouglas Gregor } while (!Done); 2052718292f2SDouglas Gregor 2053718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 2054718292f2SDouglas Gregor consumeToken(); 2055718292f2SDouglas Gregor else { 2056718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 2057718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 2058718292f2SDouglas Gregor HadError = true; 2059718292f2SDouglas Gregor } 2060718292f2SDouglas Gregor 206111dfe6feSDouglas Gregor // If the active module is a top-level framework, and there are no link 206211dfe6feSDouglas Gregor // libraries, automatically link against the framework. 206311dfe6feSDouglas Gregor if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() && 206411dfe6feSDouglas Gregor ActiveModule->LinkLibraries.empty()) { 206511dfe6feSDouglas Gregor inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager()); 206611dfe6feSDouglas Gregor } 206711dfe6feSDouglas Gregor 2068ec8c9752SBen Langmuir // If the module meets all requirements but is still unavailable, mark the 2069ec8c9752SBen Langmuir // whole tree as unavailable to prevent it from building. 2070ec8c9752SBen Langmuir if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement && 2071ec8c9752SBen Langmuir ActiveModule->Parent) { 2072ec8c9752SBen Langmuir ActiveModule->getTopLevelModule()->markUnavailable(); 2073ec8c9752SBen Langmuir ActiveModule->getTopLevelModule()->MissingHeaders.append( 2074ec8c9752SBen Langmuir ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end()); 2075ec8c9752SBen Langmuir } 2076ec8c9752SBen Langmuir 2077e7ab3669SDouglas Gregor // We're done parsing this module. Pop back to the previous module. 2078e7ab3669SDouglas Gregor ActiveModule = PreviousActiveModule; 2079718292f2SDouglas Gregor } 2080718292f2SDouglas Gregor 20819fc8faf9SAdrian Prantl /// Parse an extern module declaration. 208297292843SDaniel Jasper /// 208397292843SDaniel Jasper /// extern module-declaration: 208497292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 208597292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() { 208697292843SDaniel Jasper assert(Tok.is(MMToken::ExternKeyword)); 2087ae6df27eSRichard Smith SourceLocation ExternLoc = consumeToken(); // 'extern' keyword 208897292843SDaniel Jasper 208997292843SDaniel Jasper // Parse 'module' keyword. 209097292843SDaniel Jasper if (!Tok.is(MMToken::ModuleKeyword)) { 209197292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 209297292843SDaniel Jasper consumeToken(); 209397292843SDaniel Jasper HadError = true; 209497292843SDaniel Jasper return; 209597292843SDaniel Jasper } 209697292843SDaniel Jasper consumeToken(); // 'module' keyword 209797292843SDaniel Jasper 209897292843SDaniel Jasper // Parse the module name. 209997292843SDaniel Jasper ModuleId Id; 210097292843SDaniel Jasper if (parseModuleId(Id)) { 210197292843SDaniel Jasper HadError = true; 210297292843SDaniel Jasper return; 210397292843SDaniel Jasper } 210497292843SDaniel Jasper 210597292843SDaniel Jasper // Parse the referenced module map file name. 210697292843SDaniel Jasper if (!Tok.is(MMToken::StringLiteral)) { 210797292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file); 210897292843SDaniel Jasper HadError = true; 210997292843SDaniel Jasper return; 211097292843SDaniel Jasper } 211197292843SDaniel Jasper std::string FileName = Tok.getString(); 211297292843SDaniel Jasper consumeToken(); // filename 211397292843SDaniel Jasper 211497292843SDaniel Jasper StringRef FileNameRef = FileName; 211597292843SDaniel Jasper SmallString<128> ModuleMapFileName; 211697292843SDaniel Jasper if (llvm::sys::path::is_relative(FileNameRef)) { 211797292843SDaniel Jasper ModuleMapFileName += Directory->getName(); 211897292843SDaniel Jasper llvm::sys::path::append(ModuleMapFileName, FileName); 211992e1b62dSYaron Keren FileNameRef = ModuleMapFileName; 212097292843SDaniel Jasper } 212197292843SDaniel Jasper if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef)) 21229acb99e3SRichard Smith Map.parseModuleMapFile( 21239acb99e3SRichard Smith File, /*IsSystem=*/false, 21249acb99e3SRichard Smith Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd 21259acb99e3SRichard Smith ? Directory 21268128f332SRichard Smith : File->getDir(), 2127c192d194SBruno Cardoso Lopes FileID(), nullptr, ExternLoc); 212897292843SDaniel Jasper } 212997292843SDaniel Jasper 21307ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M. 21317ff29148SBen Langmuir /// 21327ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system 21337ff29148SBen Langmuir /// module map files: 21347ff29148SBen Langmuir /// 21357ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which 21367ff29148SBen Langmuir /// should really be mapped to 'textual' now that we have this feature. We 21377ff29148SBen Langmuir /// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to 21387ff29148SBen Langmuir /// true. Later, this bit will be used to map all the headers inside this 21397ff29148SBen Langmuir /// module to 'textual'. 21407ff29148SBen Langmuir /// 21417ff29148SBen Langmuir /// This affects Darwin.C.excluded (for assert.h) and Tcl.Private. 21427ff29148SBen Langmuir /// 21437ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement 21447ff29148SBen Langmuir /// was never correct and causes issues now that we check it, so drop it. 21457ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature, 21467ff29148SBen Langmuir bool &IsRequiresExcludedHack) { 21478013e81dSBenjamin Kramer if (Feature == "excluded" && 21488013e81dSBenjamin Kramer (M->fullModuleNameIs({"Darwin", "C", "excluded"}) || 21498013e81dSBenjamin Kramer M->fullModuleNameIs({"Tcl", "Private"}))) { 21507ff29148SBen Langmuir IsRequiresExcludedHack = true; 21517ff29148SBen Langmuir return false; 21528013e81dSBenjamin Kramer } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) { 21537ff29148SBen Langmuir return false; 21547ff29148SBen Langmuir } 21557ff29148SBen Langmuir 21567ff29148SBen Langmuir return true; 21577ff29148SBen Langmuir } 21587ff29148SBen Langmuir 21599fc8faf9SAdrian Prantl /// Parse a requires declaration. 21601fb5c3a6SDouglas Gregor /// 21611fb5c3a6SDouglas Gregor /// requires-declaration: 21621fb5c3a6SDouglas Gregor /// 'requires' feature-list 21631fb5c3a6SDouglas Gregor /// 21641fb5c3a6SDouglas Gregor /// feature-list: 2165a3feee2aSRichard Smith /// feature ',' feature-list 2166a3feee2aSRichard Smith /// feature 2167a3feee2aSRichard Smith /// 2168a3feee2aSRichard Smith /// feature: 2169a3feee2aSRichard Smith /// '!'[opt] identifier 21701fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() { 21711fb5c3a6SDouglas Gregor assert(Tok.is(MMToken::RequiresKeyword)); 21721fb5c3a6SDouglas Gregor 21731fb5c3a6SDouglas Gregor // Parse 'requires' keyword. 21741fb5c3a6SDouglas Gregor consumeToken(); 21751fb5c3a6SDouglas Gregor 21761fb5c3a6SDouglas Gregor // Parse the feature-list. 21771fb5c3a6SDouglas Gregor do { 2178a3feee2aSRichard Smith bool RequiredState = true; 2179a3feee2aSRichard Smith if (Tok.is(MMToken::Exclaim)) { 2180a3feee2aSRichard Smith RequiredState = false; 2181a3feee2aSRichard Smith consumeToken(); 2182a3feee2aSRichard Smith } 2183a3feee2aSRichard Smith 21841fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 21851fb5c3a6SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature); 21861fb5c3a6SDouglas Gregor HadError = true; 21871fb5c3a6SDouglas Gregor return; 21881fb5c3a6SDouglas Gregor } 21891fb5c3a6SDouglas Gregor 21901fb5c3a6SDouglas Gregor // Consume the feature name. 21911fb5c3a6SDouglas Gregor std::string Feature = Tok.getString(); 21921fb5c3a6SDouglas Gregor consumeToken(); 21931fb5c3a6SDouglas Gregor 21947ff29148SBen Langmuir bool IsRequiresExcludedHack = false; 21957ff29148SBen Langmuir bool ShouldAddRequirement = 21967ff29148SBen Langmuir shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack); 21977ff29148SBen Langmuir 21987ff29148SBen Langmuir if (IsRequiresExcludedHack) 21997ff29148SBen Langmuir UsesRequiresExcludedHack.insert(ActiveModule); 22007ff29148SBen Langmuir 22017ff29148SBen Langmuir if (ShouldAddRequirement) { 22021fb5c3a6SDouglas Gregor // Add this feature. 22037ff29148SBen Langmuir ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts, 22047ff29148SBen Langmuir *Map.Target); 22057ff29148SBen Langmuir } 22061fb5c3a6SDouglas Gregor 22071fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Comma)) 22081fb5c3a6SDouglas Gregor break; 22091fb5c3a6SDouglas Gregor 22101fb5c3a6SDouglas Gregor // Consume the comma. 22111fb5c3a6SDouglas Gregor consumeToken(); 22121fb5c3a6SDouglas Gregor } while (true); 22131fb5c3a6SDouglas Gregor } 22141fb5c3a6SDouglas Gregor 22159fc8faf9SAdrian Prantl /// Parse a header declaration. 2216718292f2SDouglas Gregor /// 2217718292f2SDouglas Gregor /// header-declaration: 2218306d8920SRichard Smith /// 'textual'[opt] 'header' string-literal 2219202210b3SRichard Smith /// 'private' 'textual'[opt] 'header' string-literal 2220202210b3SRichard Smith /// 'exclude' 'header' string-literal 2221202210b3SRichard Smith /// 'umbrella' 'header' string-literal 2222306d8920SRichard Smith /// 2223306d8920SRichard Smith /// FIXME: Support 'private textual header'. 2224b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, 2225b53e5483SLawrence Crowl SourceLocation LeadingLoc) { 2226202210b3SRichard Smith // We've already consumed the first token. 2227202210b3SRichard Smith ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader; 2228202210b3SRichard Smith if (LeadingToken == MMToken::PrivateKeyword) { 2229202210b3SRichard Smith Role = ModuleMap::PrivateHeader; 2230202210b3SRichard Smith // 'private' may optionally be followed by 'textual'. 2231202210b3SRichard Smith if (Tok.is(MMToken::TextualKeyword)) { 2232202210b3SRichard Smith LeadingToken = Tok.Kind; 22331871ed3dSBenjamin Kramer consumeToken(); 2234202210b3SRichard Smith } 2235202210b3SRichard Smith } 22367ff29148SBen Langmuir 2237202210b3SRichard Smith if (LeadingToken == MMToken::TextualKeyword) 2238202210b3SRichard Smith Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 2239202210b3SRichard Smith 22407ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 22417ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 22427ff29148SBen Langmuir // Module::UsesRequiresExcludedHack). 22437ff29148SBen Langmuir Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 22447ff29148SBen Langmuir } 22457ff29148SBen Langmuir 2246202210b3SRichard Smith if (LeadingToken != MMToken::HeaderKeyword) { 2247202210b3SRichard Smith if (!Tok.is(MMToken::HeaderKeyword)) { 2248202210b3SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2249202210b3SRichard Smith << (LeadingToken == MMToken::PrivateKeyword ? "private" : 2250202210b3SRichard Smith LeadingToken == MMToken::ExcludeKeyword ? "exclude" : 2251202210b3SRichard Smith LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella"); 2252202210b3SRichard Smith return; 2253202210b3SRichard Smith } 2254202210b3SRichard Smith consumeToken(); 2255202210b3SRichard Smith } 2256718292f2SDouglas Gregor 2257718292f2SDouglas Gregor // Parse the header name. 2258718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2259718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2260718292f2SDouglas Gregor << "header"; 2261718292f2SDouglas Gregor HadError = true; 2262718292f2SDouglas Gregor return; 2263718292f2SDouglas Gregor } 22643c1a41adSRichard Smith Module::UnresolvedHeaderDirective Header; 22650761a8a0SDaniel Jasper Header.FileName = Tok.getString(); 22660761a8a0SDaniel Jasper Header.FileNameLoc = consumeToken(); 22671d60987fSRichard Smith Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword; 2268040e1266SRichard Smith Header.Kind = 2269040e1266SRichard Smith (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded 2270040e1266SRichard Smith : Map.headerRoleToKind(Role)); 2271718292f2SDouglas Gregor 2272524e33e1SDouglas Gregor // Check whether we already have an umbrella. 22731d60987fSRichard Smith if (Header.IsUmbrella && ActiveModule->Umbrella) { 22740761a8a0SDaniel Jasper Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) 2275524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2276322f633cSDouglas Gregor HadError = true; 2277322f633cSDouglas Gregor return; 2278322f633cSDouglas Gregor } 2279322f633cSDouglas Gregor 2280040e1266SRichard Smith // If we were given stat information, parse it so we can skip looking for 2281040e1266SRichard Smith // the file. 2282040e1266SRichard Smith if (Tok.is(MMToken::LBrace)) { 2283040e1266SRichard Smith SourceLocation LBraceLoc = consumeToken(); 22843ec6663bSDouglas Gregor 2285040e1266SRichard Smith while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) { 2286040e1266SRichard Smith enum Attribute { Size, ModTime, Unknown }; 2287040e1266SRichard Smith StringRef Str = Tok.getString(); 2288040e1266SRichard Smith SourceLocation Loc = consumeToken(); 2289040e1266SRichard Smith switch (llvm::StringSwitch<Attribute>(Str) 2290040e1266SRichard Smith .Case("size", Size) 2291040e1266SRichard Smith .Case("mtime", ModTime) 2292040e1266SRichard Smith .Default(Unknown)) { 2293040e1266SRichard Smith case Size: 2294040e1266SRichard Smith if (Header.Size) 2295040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2296040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2297040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2298040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2299040e1266SRichard Smith skipUntil(MMToken::RBrace); 2300040e1266SRichard Smith break; 2301040e1266SRichard Smith } 2302040e1266SRichard Smith Header.Size = Tok.getInteger(); 2303040e1266SRichard Smith consumeToken(); 2304040e1266SRichard Smith break; 2305040e1266SRichard Smith 2306040e1266SRichard Smith case ModTime: 2307040e1266SRichard Smith if (Header.ModTime) 2308040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2309040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2310040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2311040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2312040e1266SRichard Smith skipUntil(MMToken::RBrace); 2313040e1266SRichard Smith break; 2314040e1266SRichard Smith } 2315040e1266SRichard Smith Header.ModTime = Tok.getInteger(); 2316040e1266SRichard Smith consumeToken(); 2317040e1266SRichard Smith break; 2318040e1266SRichard Smith 2319040e1266SRichard Smith case Unknown: 2320040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_expected_header_attribute); 2321040e1266SRichard Smith skipUntil(MMToken::RBrace); 2322040e1266SRichard Smith break; 2323040e1266SRichard Smith } 23243ec6663bSDouglas Gregor } 23255257fc63SDouglas Gregor 2326040e1266SRichard Smith if (Tok.is(MMToken::RBrace)) 2327040e1266SRichard Smith consumeToken(); 2328040e1266SRichard Smith else { 2329040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 2330040e1266SRichard Smith Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 2331322f633cSDouglas Gregor HadError = true; 2332322f633cSDouglas Gregor } 23330101b540SHans Wennborg } 233425d50758SRichard Smith 23359f6020bcSBruno Cardoso Lopes bool NeedsFramework = false; 23369f6020bcSBruno Cardoso Lopes Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework); 23379f6020bcSBruno Cardoso Lopes 23389f6020bcSBruno Cardoso Lopes if (NeedsFramework && ActiveModule) 23399f6020bcSBruno Cardoso Lopes Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword) 23409f6020bcSBruno Cardoso Lopes << ActiveModule->getFullModuleName() 23419f6020bcSBruno Cardoso Lopes << FixItHint::CreateReplacement(CurrModuleDeclLoc, "framework module"); 2342718292f2SDouglas Gregor } 2343718292f2SDouglas Gregor 234441f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A, 234541f81994SBen Langmuir const Module::Header *B) { 234641f81994SBen Langmuir return A->NameAsWritten.compare(B->NameAsWritten); 234741f81994SBen Langmuir } 234841f81994SBen Langmuir 23499fc8faf9SAdrian Prantl /// Parse an umbrella directory declaration. 2350524e33e1SDouglas Gregor /// 2351524e33e1SDouglas Gregor /// umbrella-dir-declaration: 2352524e33e1SDouglas Gregor /// umbrella string-literal 2353524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { 2354524e33e1SDouglas Gregor // Parse the directory name. 2355524e33e1SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2356524e33e1SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2357524e33e1SDouglas Gregor << "umbrella"; 2358524e33e1SDouglas Gregor HadError = true; 2359524e33e1SDouglas Gregor return; 2360524e33e1SDouglas Gregor } 2361524e33e1SDouglas Gregor 2362524e33e1SDouglas Gregor std::string DirName = Tok.getString(); 2363524e33e1SDouglas Gregor SourceLocation DirNameLoc = consumeToken(); 2364524e33e1SDouglas Gregor 2365524e33e1SDouglas Gregor // Check whether we already have an umbrella. 2366524e33e1SDouglas Gregor if (ActiveModule->Umbrella) { 2367524e33e1SDouglas Gregor Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash) 2368524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2369524e33e1SDouglas Gregor HadError = true; 2370524e33e1SDouglas Gregor return; 2371524e33e1SDouglas Gregor } 2372524e33e1SDouglas Gregor 2373524e33e1SDouglas Gregor // Look for this file. 2374d2d442caSCraig Topper const DirectoryEntry *Dir = nullptr; 2375524e33e1SDouglas Gregor if (llvm::sys::path::is_absolute(DirName)) 2376524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(DirName); 2377524e33e1SDouglas Gregor else { 23782c1dd271SDylan Noblesmith SmallString<128> PathName; 2379524e33e1SDouglas Gregor PathName = Directory->getName(); 2380524e33e1SDouglas Gregor llvm::sys::path::append(PathName, DirName); 2381524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(PathName); 2382524e33e1SDouglas Gregor } 2383524e33e1SDouglas Gregor 2384524e33e1SDouglas Gregor if (!Dir) { 2385a0320b97SVassil Vassilev Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found) 2386524e33e1SDouglas Gregor << DirName; 2387524e33e1SDouglas Gregor return; 2388524e33e1SDouglas Gregor } 2389524e33e1SDouglas Gregor 23907ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 23917ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 23927ff29148SBen Langmuir // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the 23937ff29148SBen Langmuir // directory is relatively expensive, in practice this only applies to the 23947ff29148SBen Langmuir // uncommonly used Tcl module on Darwin platforms. 23957ff29148SBen Langmuir std::error_code EC; 23967ff29148SBen Langmuir SmallVector<Module::Header, 6> Headers; 2397b171a59bSBruno Cardoso Lopes vfs::FileSystem &FS = *SourceMgr.getFileManager().getVirtualFileSystem(); 2398b171a59bSBruno Cardoso Lopes for (vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E; 23997ff29148SBen Langmuir I != E && !EC; I.increment(EC)) { 24000ae00567SSam McCall if (const FileEntry *FE = SourceMgr.getFileManager().getFile(I->path())) { 24017ff29148SBen Langmuir 24020ae00567SSam McCall Module::Header Header = {I->path(), FE}; 24037ff29148SBen Langmuir Headers.push_back(std::move(Header)); 24047ff29148SBen Langmuir } 24057ff29148SBen Langmuir } 24067ff29148SBen Langmuir 24077ff29148SBen Langmuir // Sort header paths so that the pcm doesn't depend on iteration order. 240841f81994SBen Langmuir llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders); 240941f81994SBen Langmuir 24107ff29148SBen Langmuir for (auto &Header : Headers) 24117ff29148SBen Langmuir Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader); 24127ff29148SBen Langmuir return; 24137ff29148SBen Langmuir } 24147ff29148SBen Langmuir 2415524e33e1SDouglas Gregor if (Module *OwningModule = Map.UmbrellaDirs[Dir]) { 2416524e33e1SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 2417524e33e1SDouglas Gregor << OwningModule->getFullModuleName(); 2418524e33e1SDouglas Gregor HadError = true; 2419524e33e1SDouglas Gregor return; 2420524e33e1SDouglas Gregor } 2421524e33e1SDouglas Gregor 2422524e33e1SDouglas Gregor // Record this umbrella directory. 24232b63d15fSRichard Smith Map.setUmbrellaDir(ActiveModule, Dir, DirName); 2424524e33e1SDouglas Gregor } 2425524e33e1SDouglas Gregor 24269fc8faf9SAdrian Prantl /// Parse a module export declaration. 24272b82c2a5SDouglas Gregor /// 24282b82c2a5SDouglas Gregor /// export-declaration: 24292b82c2a5SDouglas Gregor /// 'export' wildcard-module-id 24302b82c2a5SDouglas Gregor /// 24312b82c2a5SDouglas Gregor /// wildcard-module-id: 24322b82c2a5SDouglas Gregor /// identifier 24332b82c2a5SDouglas Gregor /// '*' 24342b82c2a5SDouglas Gregor /// identifier '.' wildcard-module-id 24352b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() { 24362b82c2a5SDouglas Gregor assert(Tok.is(MMToken::ExportKeyword)); 24372b82c2a5SDouglas Gregor SourceLocation ExportLoc = consumeToken(); 24382b82c2a5SDouglas Gregor 24392b82c2a5SDouglas Gregor // Parse the module-id with an optional wildcard at the end. 24402b82c2a5SDouglas Gregor ModuleId ParsedModuleId; 24412b82c2a5SDouglas Gregor bool Wildcard = false; 24422b82c2a5SDouglas Gregor do { 2443306d8920SRichard Smith // FIXME: Support string-literal module names here. 24442b82c2a5SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 24452b82c2a5SDouglas Gregor ParsedModuleId.push_back(std::make_pair(Tok.getString(), 24462b82c2a5SDouglas Gregor Tok.getLocation())); 24472b82c2a5SDouglas Gregor consumeToken(); 24482b82c2a5SDouglas Gregor 24492b82c2a5SDouglas Gregor if (Tok.is(MMToken::Period)) { 24502b82c2a5SDouglas Gregor consumeToken(); 24512b82c2a5SDouglas Gregor continue; 24522b82c2a5SDouglas Gregor } 24532b82c2a5SDouglas Gregor 24542b82c2a5SDouglas Gregor break; 24552b82c2a5SDouglas Gregor } 24562b82c2a5SDouglas Gregor 24572b82c2a5SDouglas Gregor if(Tok.is(MMToken::Star)) { 24582b82c2a5SDouglas Gregor Wildcard = true; 2459f5eedd05SDouglas Gregor consumeToken(); 24602b82c2a5SDouglas Gregor break; 24612b82c2a5SDouglas Gregor } 24622b82c2a5SDouglas Gregor 2463ba7f2f71SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_module_id); 24642b82c2a5SDouglas Gregor HadError = true; 24652b82c2a5SDouglas Gregor return; 24662b82c2a5SDouglas Gregor } while (true); 24672b82c2a5SDouglas Gregor 24682b82c2a5SDouglas Gregor Module::UnresolvedExportDecl Unresolved = { 24692b82c2a5SDouglas Gregor ExportLoc, ParsedModuleId, Wildcard 24702b82c2a5SDouglas Gregor }; 24712b82c2a5SDouglas Gregor ActiveModule->UnresolvedExports.push_back(Unresolved); 24722b82c2a5SDouglas Gregor } 24732b82c2a5SDouglas Gregor 24749fc8faf9SAdrian Prantl /// Parse a module export_as declaration. 2475f0b11de2SDouglas Gregor /// 2476f0b11de2SDouglas Gregor /// export-as-declaration: 2477f0b11de2SDouglas Gregor /// 'export_as' identifier 2478f0b11de2SDouglas Gregor void ModuleMapParser::parseExportAsDecl() { 2479f0b11de2SDouglas Gregor assert(Tok.is(MMToken::ExportAsKeyword)); 2480f0b11de2SDouglas Gregor consumeToken(); 2481f0b11de2SDouglas Gregor 2482f0b11de2SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 2483f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_module_id); 2484f0b11de2SDouglas Gregor HadError = true; 2485f0b11de2SDouglas Gregor return; 2486f0b11de2SDouglas Gregor } 2487f0b11de2SDouglas Gregor 2488f0b11de2SDouglas Gregor if (ActiveModule->Parent) { 2489f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as); 2490f0b11de2SDouglas Gregor consumeToken(); 2491f0b11de2SDouglas Gregor return; 2492f0b11de2SDouglas Gregor } 2493f0b11de2SDouglas Gregor 2494f0b11de2SDouglas Gregor if (!ActiveModule->ExportAsModule.empty()) { 2495f0b11de2SDouglas Gregor if (ActiveModule->ExportAsModule == Tok.getString()) { 2496f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as) 2497f0b11de2SDouglas Gregor << ActiveModule->Name << Tok.getString(); 2498f0b11de2SDouglas Gregor } else { 2499f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as) 2500f0b11de2SDouglas Gregor << ActiveModule->Name << ActiveModule->ExportAsModule 2501f0b11de2SDouglas Gregor << Tok.getString(); 2502f0b11de2SDouglas Gregor } 2503f0b11de2SDouglas Gregor } 2504f0b11de2SDouglas Gregor 2505f0b11de2SDouglas Gregor ActiveModule->ExportAsModule = Tok.getString(); 2506a3b5f71eSBruno Cardoso Lopes Map.addLinkAsDependency(ActiveModule); 2507a3b5f71eSBruno Cardoso Lopes 2508f0b11de2SDouglas Gregor consumeToken(); 2509f0b11de2SDouglas Gregor } 2510f0b11de2SDouglas Gregor 25119fc8faf9SAdrian Prantl /// Parse a module use declaration. 2512ba7f2f71SDaniel Jasper /// 25138f4d3ff1SRichard Smith /// use-declaration: 25148f4d3ff1SRichard Smith /// 'use' wildcard-module-id 2515ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() { 2516ba7f2f71SDaniel Jasper assert(Tok.is(MMToken::UseKeyword)); 25178f4d3ff1SRichard Smith auto KWLoc = consumeToken(); 2518ba7f2f71SDaniel Jasper // Parse the module-id. 2519ba7f2f71SDaniel Jasper ModuleId ParsedModuleId; 25203cd34c76SDaniel Jasper parseModuleId(ParsedModuleId); 2521ba7f2f71SDaniel Jasper 25228f4d3ff1SRichard Smith if (ActiveModule->Parent) 25238f4d3ff1SRichard Smith Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule); 25248f4d3ff1SRichard Smith else 2525ba7f2f71SDaniel Jasper ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId); 2526ba7f2f71SDaniel Jasper } 2527ba7f2f71SDaniel Jasper 25289fc8faf9SAdrian Prantl /// Parse a link declaration. 25296ddfca91SDouglas Gregor /// 25306ddfca91SDouglas Gregor /// module-declaration: 25316ddfca91SDouglas Gregor /// 'link' 'framework'[opt] string-literal 25326ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() { 25336ddfca91SDouglas Gregor assert(Tok.is(MMToken::LinkKeyword)); 25346ddfca91SDouglas Gregor SourceLocation LinkLoc = consumeToken(); 25356ddfca91SDouglas Gregor 25366ddfca91SDouglas Gregor // Parse the optional 'framework' keyword. 25376ddfca91SDouglas Gregor bool IsFramework = false; 25386ddfca91SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 25396ddfca91SDouglas Gregor consumeToken(); 25406ddfca91SDouglas Gregor IsFramework = true; 25416ddfca91SDouglas Gregor } 25426ddfca91SDouglas Gregor 25436ddfca91SDouglas Gregor // Parse the library name 25446ddfca91SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 25456ddfca91SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name) 25466ddfca91SDouglas Gregor << IsFramework << SourceRange(LinkLoc); 25476ddfca91SDouglas Gregor HadError = true; 25486ddfca91SDouglas Gregor return; 25496ddfca91SDouglas Gregor } 25506ddfca91SDouglas Gregor 25516ddfca91SDouglas Gregor std::string LibraryName = Tok.getString(); 25526ddfca91SDouglas Gregor consumeToken(); 25536ddfca91SDouglas Gregor ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName, 25546ddfca91SDouglas Gregor IsFramework)); 25556ddfca91SDouglas Gregor } 25566ddfca91SDouglas Gregor 25579fc8faf9SAdrian Prantl /// Parse a configuration macro declaration. 255835b13eceSDouglas Gregor /// 255935b13eceSDouglas Gregor /// module-declaration: 256035b13eceSDouglas Gregor /// 'config_macros' attributes[opt] config-macro-list? 256135b13eceSDouglas Gregor /// 256235b13eceSDouglas Gregor /// config-macro-list: 256335b13eceSDouglas Gregor /// identifier (',' identifier)? 256435b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() { 256535b13eceSDouglas Gregor assert(Tok.is(MMToken::ConfigMacros)); 256635b13eceSDouglas Gregor SourceLocation ConfigMacrosLoc = consumeToken(); 256735b13eceSDouglas Gregor 256835b13eceSDouglas Gregor // Only top-level modules can have configuration macros. 256935b13eceSDouglas Gregor if (ActiveModule->Parent) { 257035b13eceSDouglas Gregor Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule); 257135b13eceSDouglas Gregor } 257235b13eceSDouglas Gregor 257335b13eceSDouglas Gregor // Parse the optional attributes. 257435b13eceSDouglas Gregor Attributes Attrs; 25755d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 25765d29dee0SDavide Italiano return; 25775d29dee0SDavide Italiano 257835b13eceSDouglas Gregor if (Attrs.IsExhaustive && !ActiveModule->Parent) { 257935b13eceSDouglas Gregor ActiveModule->ConfigMacrosExhaustive = true; 258035b13eceSDouglas Gregor } 258135b13eceSDouglas Gregor 258235b13eceSDouglas Gregor // If we don't have an identifier, we're done. 2583306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 258435b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) 258535b13eceSDouglas Gregor return; 258635b13eceSDouglas Gregor 258735b13eceSDouglas Gregor // Consume the first identifier. 258835b13eceSDouglas Gregor if (!ActiveModule->Parent) { 258935b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 259035b13eceSDouglas Gregor } 259135b13eceSDouglas Gregor consumeToken(); 259235b13eceSDouglas Gregor 259335b13eceSDouglas Gregor do { 259435b13eceSDouglas Gregor // If there's a comma, consume it. 259535b13eceSDouglas Gregor if (!Tok.is(MMToken::Comma)) 259635b13eceSDouglas Gregor break; 259735b13eceSDouglas Gregor consumeToken(); 259835b13eceSDouglas Gregor 259935b13eceSDouglas Gregor // We expect to see a macro name here. 2600306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 260135b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 260235b13eceSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro); 260335b13eceSDouglas Gregor break; 260435b13eceSDouglas Gregor } 260535b13eceSDouglas Gregor 260635b13eceSDouglas Gregor // Consume the macro name. 260735b13eceSDouglas Gregor if (!ActiveModule->Parent) { 260835b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 260935b13eceSDouglas Gregor } 261035b13eceSDouglas Gregor consumeToken(); 261135b13eceSDouglas Gregor } while (true); 261235b13eceSDouglas Gregor } 261335b13eceSDouglas Gregor 26149fc8faf9SAdrian Prantl /// Format a module-id into a string. 2615fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) { 2616fb912657SDouglas Gregor std::string result; 2617fb912657SDouglas Gregor { 2618fb912657SDouglas Gregor llvm::raw_string_ostream OS(result); 2619fb912657SDouglas Gregor 2620fb912657SDouglas Gregor for (unsigned I = 0, N = Id.size(); I != N; ++I) { 2621fb912657SDouglas Gregor if (I) 2622fb912657SDouglas Gregor OS << "."; 2623fb912657SDouglas Gregor OS << Id[I].first; 2624fb912657SDouglas Gregor } 2625fb912657SDouglas Gregor } 2626fb912657SDouglas Gregor 2627fb912657SDouglas Gregor return result; 2628fb912657SDouglas Gregor } 2629fb912657SDouglas Gregor 26309fc8faf9SAdrian Prantl /// Parse a conflict declaration. 2631fb912657SDouglas Gregor /// 2632fb912657SDouglas Gregor /// module-declaration: 2633fb912657SDouglas Gregor /// 'conflict' module-id ',' string-literal 2634fb912657SDouglas Gregor void ModuleMapParser::parseConflict() { 2635fb912657SDouglas Gregor assert(Tok.is(MMToken::Conflict)); 2636fb912657SDouglas Gregor SourceLocation ConflictLoc = consumeToken(); 2637fb912657SDouglas Gregor Module::UnresolvedConflict Conflict; 2638fb912657SDouglas Gregor 2639fb912657SDouglas Gregor // Parse the module-id. 2640fb912657SDouglas Gregor if (parseModuleId(Conflict.Id)) 2641fb912657SDouglas Gregor return; 2642fb912657SDouglas Gregor 2643fb912657SDouglas Gregor // Parse the ','. 2644fb912657SDouglas Gregor if (!Tok.is(MMToken::Comma)) { 2645fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma) 2646fb912657SDouglas Gregor << SourceRange(ConflictLoc); 2647fb912657SDouglas Gregor return; 2648fb912657SDouglas Gregor } 2649fb912657SDouglas Gregor consumeToken(); 2650fb912657SDouglas Gregor 2651fb912657SDouglas Gregor // Parse the message. 2652fb912657SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2653fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message) 2654fb912657SDouglas Gregor << formatModuleId(Conflict.Id); 2655fb912657SDouglas Gregor return; 2656fb912657SDouglas Gregor } 2657fb912657SDouglas Gregor Conflict.Message = Tok.getString().str(); 2658fb912657SDouglas Gregor consumeToken(); 2659fb912657SDouglas Gregor 2660fb912657SDouglas Gregor // Add this unresolved conflict. 2661fb912657SDouglas Gregor ActiveModule->UnresolvedConflicts.push_back(Conflict); 2662fb912657SDouglas Gregor } 2663fb912657SDouglas Gregor 26649fc8faf9SAdrian Prantl /// Parse an inferred module declaration (wildcard modules). 26659194a91dSDouglas Gregor /// 26669194a91dSDouglas Gregor /// module-declaration: 26679194a91dSDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt] 26689194a91dSDouglas Gregor /// { inferred-module-member* } 26699194a91dSDouglas Gregor /// 26709194a91dSDouglas Gregor /// inferred-module-member: 26719194a91dSDouglas Gregor /// 'export' '*' 26729194a91dSDouglas Gregor /// 'exclude' identifier 26739194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { 267473441091SDouglas Gregor assert(Tok.is(MMToken::Star)); 267573441091SDouglas Gregor SourceLocation StarLoc = consumeToken(); 267673441091SDouglas Gregor bool Failed = false; 267773441091SDouglas Gregor 267873441091SDouglas Gregor // Inferred modules must be submodules. 26799194a91dSDouglas Gregor if (!ActiveModule && !Framework) { 268073441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule); 268173441091SDouglas Gregor Failed = true; 268273441091SDouglas Gregor } 268373441091SDouglas Gregor 26849194a91dSDouglas Gregor if (ActiveModule) { 2685524e33e1SDouglas Gregor // Inferred modules must have umbrella directories. 26864898cde4SBen Langmuir if (!Failed && ActiveModule->IsAvailable && 26874898cde4SBen Langmuir !ActiveModule->getUmbrellaDir()) { 268873441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); 268973441091SDouglas Gregor Failed = true; 269073441091SDouglas Gregor } 269173441091SDouglas Gregor 269273441091SDouglas Gregor // Check for redefinition of an inferred module. 2693dd005f69SDouglas Gregor if (!Failed && ActiveModule->InferSubmodules) { 269473441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_redef); 2695dd005f69SDouglas Gregor if (ActiveModule->InferredSubmoduleLoc.isValid()) 2696dd005f69SDouglas Gregor Diags.Report(ActiveModule->InferredSubmoduleLoc, 269773441091SDouglas Gregor diag::note_mmap_prev_definition); 269873441091SDouglas Gregor Failed = true; 269973441091SDouglas Gregor } 270073441091SDouglas Gregor 27019194a91dSDouglas Gregor // Check for the 'framework' keyword, which is not permitted here. 27029194a91dSDouglas Gregor if (Framework) { 27039194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule); 27049194a91dSDouglas Gregor Framework = false; 27059194a91dSDouglas Gregor } 27069194a91dSDouglas Gregor } else if (Explicit) { 27079194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework); 27089194a91dSDouglas Gregor Explicit = false; 27099194a91dSDouglas Gregor } 27109194a91dSDouglas Gregor 271173441091SDouglas Gregor // If there were any problems with this inferred submodule, skip its body. 271273441091SDouglas Gregor if (Failed) { 271373441091SDouglas Gregor if (Tok.is(MMToken::LBrace)) { 271473441091SDouglas Gregor consumeToken(); 271573441091SDouglas Gregor skipUntil(MMToken::RBrace); 271673441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 271773441091SDouglas Gregor consumeToken(); 271873441091SDouglas Gregor } 271973441091SDouglas Gregor HadError = true; 272073441091SDouglas Gregor return; 272173441091SDouglas Gregor } 272273441091SDouglas Gregor 27239194a91dSDouglas Gregor // Parse optional attributes. 27244442605fSBill Wendling Attributes Attrs; 27255d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 27265d29dee0SDavide Italiano return; 27279194a91dSDouglas Gregor 27289194a91dSDouglas Gregor if (ActiveModule) { 272973441091SDouglas Gregor // Note that we have an inferred submodule. 2730dd005f69SDouglas Gregor ActiveModule->InferSubmodules = true; 2731dd005f69SDouglas Gregor ActiveModule->InferredSubmoduleLoc = StarLoc; 2732dd005f69SDouglas Gregor ActiveModule->InferExplicitSubmodules = Explicit; 27339194a91dSDouglas Gregor } else { 27349194a91dSDouglas Gregor // We'll be inferring framework modules for this directory. 27359194a91dSDouglas Gregor Map.InferredDirectories[Directory].InferModules = true; 2736c1d88ea5SBen Langmuir Map.InferredDirectories[Directory].Attrs = Attrs; 2737beee15e7SBen Langmuir Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile; 2738131daca0SRichard Smith // FIXME: Handle the 'framework' keyword. 27399194a91dSDouglas Gregor } 274073441091SDouglas Gregor 274173441091SDouglas Gregor // Parse the opening brace. 274273441091SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 274373441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard); 274473441091SDouglas Gregor HadError = true; 274573441091SDouglas Gregor return; 274673441091SDouglas Gregor } 274773441091SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 274873441091SDouglas Gregor 274973441091SDouglas Gregor // Parse the body of the inferred submodule. 275073441091SDouglas Gregor bool Done = false; 275173441091SDouglas Gregor do { 275273441091SDouglas Gregor switch (Tok.Kind) { 275373441091SDouglas Gregor case MMToken::EndOfFile: 275473441091SDouglas Gregor case MMToken::RBrace: 275573441091SDouglas Gregor Done = true; 275673441091SDouglas Gregor break; 275773441091SDouglas Gregor 2758afd1b1c9SEugene Zelenko case MMToken::ExcludeKeyword: 27599194a91dSDouglas Gregor if (ActiveModule) { 27609194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2761d2d442caSCraig Topper << (ActiveModule != nullptr); 27629194a91dSDouglas Gregor consumeToken(); 27639194a91dSDouglas Gregor break; 27649194a91dSDouglas Gregor } 27659194a91dSDouglas Gregor 27669194a91dSDouglas Gregor consumeToken(); 2767306d8920SRichard Smith // FIXME: Support string-literal module names here. 27689194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 27699194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name); 27709194a91dSDouglas Gregor break; 27719194a91dSDouglas Gregor } 27729194a91dSDouglas Gregor 27739194a91dSDouglas Gregor Map.InferredDirectories[Directory].ExcludedModules 27749194a91dSDouglas Gregor .push_back(Tok.getString()); 27759194a91dSDouglas Gregor consumeToken(); 27769194a91dSDouglas Gregor break; 27779194a91dSDouglas Gregor 27789194a91dSDouglas Gregor case MMToken::ExportKeyword: 27799194a91dSDouglas Gregor if (!ActiveModule) { 27809194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2781d2d442caSCraig Topper << (ActiveModule != nullptr); 27829194a91dSDouglas Gregor consumeToken(); 27839194a91dSDouglas Gregor break; 27849194a91dSDouglas Gregor } 27859194a91dSDouglas Gregor 278673441091SDouglas Gregor consumeToken(); 278773441091SDouglas Gregor if (Tok.is(MMToken::Star)) 2788dd005f69SDouglas Gregor ActiveModule->InferExportWildcard = true; 278973441091SDouglas Gregor else 279073441091SDouglas Gregor Diags.Report(Tok.getLocation(), 279173441091SDouglas Gregor diag::err_mmap_expected_export_wildcard); 279273441091SDouglas Gregor consumeToken(); 279373441091SDouglas Gregor break; 279473441091SDouglas Gregor 279573441091SDouglas Gregor case MMToken::ExplicitKeyword: 279673441091SDouglas Gregor case MMToken::ModuleKeyword: 279773441091SDouglas Gregor case MMToken::HeaderKeyword: 2798b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 279973441091SDouglas Gregor case MMToken::UmbrellaKeyword: 280073441091SDouglas Gregor default: 28019194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2802d2d442caSCraig Topper << (ActiveModule != nullptr); 280373441091SDouglas Gregor consumeToken(); 280473441091SDouglas Gregor break; 280573441091SDouglas Gregor } 280673441091SDouglas Gregor } while (!Done); 280773441091SDouglas Gregor 280873441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 280973441091SDouglas Gregor consumeToken(); 281073441091SDouglas Gregor else { 281173441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 281273441091SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 281373441091SDouglas Gregor HadError = true; 281473441091SDouglas Gregor } 281573441091SDouglas Gregor } 281673441091SDouglas Gregor 28179fc8faf9SAdrian Prantl /// Parse optional attributes. 28189194a91dSDouglas Gregor /// 28199194a91dSDouglas Gregor /// attributes: 28209194a91dSDouglas Gregor /// attribute attributes 28219194a91dSDouglas Gregor /// attribute 28229194a91dSDouglas Gregor /// 28239194a91dSDouglas Gregor /// attribute: 28249194a91dSDouglas Gregor /// [ identifier ] 28259194a91dSDouglas Gregor /// 28269194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes. 28279194a91dSDouglas Gregor /// 28289194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise. 28294442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { 28309194a91dSDouglas Gregor bool HadError = false; 28319194a91dSDouglas Gregor 28329194a91dSDouglas Gregor while (Tok.is(MMToken::LSquare)) { 28339194a91dSDouglas Gregor // Consume the '['. 28349194a91dSDouglas Gregor SourceLocation LSquareLoc = consumeToken(); 28359194a91dSDouglas Gregor 28369194a91dSDouglas Gregor // Check whether we have an attribute name here. 28379194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 28389194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute); 28399194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 28409194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 28419194a91dSDouglas Gregor consumeToken(); 28429194a91dSDouglas Gregor HadError = true; 28439194a91dSDouglas Gregor } 28449194a91dSDouglas Gregor 28459194a91dSDouglas Gregor // Decode the attribute name. 28469194a91dSDouglas Gregor AttributeKind Attribute 28479194a91dSDouglas Gregor = llvm::StringSwitch<AttributeKind>(Tok.getString()) 284835b13eceSDouglas Gregor .Case("exhaustive", AT_exhaustive) 284977944868SRichard Smith .Case("extern_c", AT_extern_c) 2850ed84df00SBruno Cardoso Lopes .Case("no_undeclared_includes", AT_no_undeclared_includes) 28519194a91dSDouglas Gregor .Case("system", AT_system) 28529194a91dSDouglas Gregor .Default(AT_unknown); 28539194a91dSDouglas Gregor switch (Attribute) { 28549194a91dSDouglas Gregor case AT_unknown: 28559194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute) 28569194a91dSDouglas Gregor << Tok.getString(); 28579194a91dSDouglas Gregor break; 28589194a91dSDouglas Gregor 28599194a91dSDouglas Gregor case AT_system: 28609194a91dSDouglas Gregor Attrs.IsSystem = true; 28619194a91dSDouglas Gregor break; 286235b13eceSDouglas Gregor 286377944868SRichard Smith case AT_extern_c: 286477944868SRichard Smith Attrs.IsExternC = true; 286577944868SRichard Smith break; 286677944868SRichard Smith 286735b13eceSDouglas Gregor case AT_exhaustive: 286835b13eceSDouglas Gregor Attrs.IsExhaustive = true; 286935b13eceSDouglas Gregor break; 2870ed84df00SBruno Cardoso Lopes 2871ed84df00SBruno Cardoso Lopes case AT_no_undeclared_includes: 2872ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes = true; 2873ed84df00SBruno Cardoso Lopes break; 28749194a91dSDouglas Gregor } 28759194a91dSDouglas Gregor consumeToken(); 28769194a91dSDouglas Gregor 28779194a91dSDouglas Gregor // Consume the ']'. 28789194a91dSDouglas Gregor if (!Tok.is(MMToken::RSquare)) { 28799194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare); 28809194a91dSDouglas Gregor Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match); 28819194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 28829194a91dSDouglas Gregor HadError = true; 28839194a91dSDouglas Gregor } 28849194a91dSDouglas Gregor 28859194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 28869194a91dSDouglas Gregor consumeToken(); 28879194a91dSDouglas Gregor } 28889194a91dSDouglas Gregor 28899194a91dSDouglas Gregor return HadError; 28909194a91dSDouglas Gregor } 28919194a91dSDouglas Gregor 28929fc8faf9SAdrian Prantl /// Parse a module map file. 2893718292f2SDouglas Gregor /// 2894718292f2SDouglas Gregor /// module-map-file: 2895718292f2SDouglas Gregor /// module-declaration* 2896718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 2897718292f2SDouglas Gregor do { 2898718292f2SDouglas Gregor switch (Tok.Kind) { 2899718292f2SDouglas Gregor case MMToken::EndOfFile: 2900718292f2SDouglas Gregor return HadError; 2901718292f2SDouglas Gregor 2902e7ab3669SDouglas Gregor case MMToken::ExplicitKeyword: 290397292843SDaniel Jasper case MMToken::ExternKeyword: 2904718292f2SDouglas Gregor case MMToken::ModuleKeyword: 2905755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 2906718292f2SDouglas Gregor parseModuleDecl(); 2907718292f2SDouglas Gregor break; 2908718292f2SDouglas Gregor 29091fb5c3a6SDouglas Gregor case MMToken::Comma: 291035b13eceSDouglas Gregor case MMToken::ConfigMacros: 2911fb912657SDouglas Gregor case MMToken::Conflict: 2912a3feee2aSRichard Smith case MMToken::Exclaim: 291359527666SDouglas Gregor case MMToken::ExcludeKeyword: 29142b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 2915f0b11de2SDouglas Gregor case MMToken::ExportAsKeyword: 2916718292f2SDouglas Gregor case MMToken::HeaderKeyword: 2917718292f2SDouglas Gregor case MMToken::Identifier: 2918718292f2SDouglas Gregor case MMToken::LBrace: 29196ddfca91SDouglas Gregor case MMToken::LinkKeyword: 2920a686e1b0SDouglas Gregor case MMToken::LSquare: 29212b82c2a5SDouglas Gregor case MMToken::Period: 2922b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 2923718292f2SDouglas Gregor case MMToken::RBrace: 2924a686e1b0SDouglas Gregor case MMToken::RSquare: 29251fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 29262b82c2a5SDouglas Gregor case MMToken::Star: 2927718292f2SDouglas Gregor case MMToken::StringLiteral: 2928040e1266SRichard Smith case MMToken::IntegerLiteral: 2929b8afebe2SRichard Smith case MMToken::TextualKeyword: 2930718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 2931ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 2932718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 2933718292f2SDouglas Gregor HadError = true; 2934718292f2SDouglas Gregor consumeToken(); 2935718292f2SDouglas Gregor break; 2936718292f2SDouglas Gregor } 2937718292f2SDouglas Gregor } while (true); 2938718292f2SDouglas Gregor } 2939718292f2SDouglas Gregor 29409acb99e3SRichard Smith bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem, 2941c192d194SBruno Cardoso Lopes const DirectoryEntry *Dir, FileID ID, 29428128f332SRichard Smith unsigned *Offset, 2943ae6df27eSRichard Smith SourceLocation ExternModuleLoc) { 29448128f332SRichard Smith assert(Target && "Missing target information"); 29454ddf2221SDouglas Gregor llvm::DenseMap<const FileEntry *, bool>::iterator Known 29464ddf2221SDouglas Gregor = ParsedModuleMap.find(File); 29474ddf2221SDouglas Gregor if (Known != ParsedModuleMap.end()) 29484ddf2221SDouglas Gregor return Known->second; 29494ddf2221SDouglas Gregor 29508128f332SRichard Smith // If the module map file wasn't already entered, do so now. 29518128f332SRichard Smith if (ID.isInvalid()) { 2952f3f84616SRichard Smith auto FileCharacter = 2953f3f84616SRichard Smith IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap; 29548128f332SRichard Smith ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter); 29558128f332SRichard Smith } 29568128f332SRichard Smith 29578128f332SRichard Smith assert(Target && "Missing target information"); 29581f76c4e8SManuel Klimek const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID); 2959718292f2SDouglas Gregor if (!Buffer) 29604ddf2221SDouglas Gregor return ParsedModuleMap[File] = true; 29618128f332SRichard Smith assert((!Offset || *Offset <= Buffer->getBufferSize()) && 29628128f332SRichard Smith "invalid buffer offset"); 2963718292f2SDouglas Gregor 2964718292f2SDouglas Gregor // Parse this module map file. 29658128f332SRichard Smith Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts, 29668128f332SRichard Smith Buffer->getBufferStart(), 29678128f332SRichard Smith Buffer->getBufferStart() + (Offset ? *Offset : 0), 29688128f332SRichard Smith Buffer->getBufferEnd()); 29692a6edb30SRichard Smith SourceLocation Start = L.getSourceLocation(); 2970beee15e7SBen Langmuir ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir, 2971c192d194SBruno Cardoso Lopes IsSystem); 2972718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 29734ddf2221SDouglas Gregor ParsedModuleMap[File] = Result; 29742a6edb30SRichard Smith 29758128f332SRichard Smith if (Offset) { 29768128f332SRichard Smith auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation()); 29778128f332SRichard Smith assert(Loc.first == ID && "stopped in a different file?"); 29788128f332SRichard Smith *Offset = Loc.second; 29798128f332SRichard Smith } 29808128f332SRichard Smith 29812a6edb30SRichard Smith // Notify callbacks that we parsed it. 29822a6edb30SRichard Smith for (const auto &Cb : Callbacks) 29832a6edb30SRichard Smith Cb->moduleMapFileRead(Start, *File, IsSystem); 29848587dfd9SBruno Cardoso Lopes 2985718292f2SDouglas Gregor return Result; 2986718292f2SDouglas Gregor } 2987