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 57040e1266SRichard Smith Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) { 58040e1266SRichard Smith switch ((int)Role) { 59040e1266SRichard Smith default: llvm_unreachable("unknown header role"); 60040e1266SRichard Smith case NormalHeader: 61040e1266SRichard Smith return Module::HK_Normal; 62040e1266SRichard Smith case PrivateHeader: 63040e1266SRichard Smith return Module::HK_Private; 64040e1266SRichard Smith case TextualHeader: 65040e1266SRichard Smith return Module::HK_Textual; 66040e1266SRichard Smith case PrivateHeader | TextualHeader: 67040e1266SRichard Smith return Module::HK_PrivateTextual; 68040e1266SRichard Smith } 69040e1266SRichard Smith } 70040e1266SRichard Smith 71040e1266SRichard Smith ModuleMap::ModuleHeaderRole 72040e1266SRichard Smith ModuleMap::headerKindToRole(Module::HeaderKind Kind) { 73040e1266SRichard Smith switch ((int)Kind) { 74040e1266SRichard Smith case Module::HK_Normal: 75040e1266SRichard Smith return NormalHeader; 76040e1266SRichard Smith case Module::HK_Private: 77040e1266SRichard Smith return PrivateHeader; 78040e1266SRichard Smith case Module::HK_Textual: 79040e1266SRichard Smith return TextualHeader; 80040e1266SRichard Smith case Module::HK_PrivateTextual: 81040e1266SRichard Smith return ModuleHeaderRole(PrivateHeader | TextualHeader); 82040e1266SRichard Smith case Module::HK_Excluded: 83040e1266SRichard Smith llvm_unreachable("unexpected header kind"); 84040e1266SRichard Smith } 85040e1266SRichard Smith llvm_unreachable("unknown header kind"); 86040e1266SRichard Smith } 87040e1266SRichard Smith 882b82c2a5SDouglas Gregor Module::ExportDecl 892b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod, 902b82c2a5SDouglas Gregor const Module::UnresolvedExportDecl &Unresolved, 91e4412640SArgyrios Kyrtzidis bool Complain) const { 92f5eedd05SDouglas Gregor // We may have just a wildcard. 93f5eedd05SDouglas Gregor if (Unresolved.Id.empty()) { 94f5eedd05SDouglas Gregor assert(Unresolved.Wildcard && "Invalid unresolved export"); 95d2d442caSCraig Topper return Module::ExportDecl(nullptr, true); 96f5eedd05SDouglas Gregor } 97f5eedd05SDouglas Gregor 98fb912657SDouglas Gregor // Resolve the module-id. 99fb912657SDouglas Gregor Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain); 100fb912657SDouglas Gregor if (!Context) 101afd1b1c9SEugene Zelenko return {}; 102fb912657SDouglas Gregor 103fb912657SDouglas Gregor return Module::ExportDecl(Context, Unresolved.Wildcard); 104fb912657SDouglas Gregor } 105fb912657SDouglas Gregor 106fb912657SDouglas Gregor Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod, 107fb912657SDouglas Gregor bool Complain) const { 1082b82c2a5SDouglas Gregor // Find the starting module. 109fb912657SDouglas Gregor Module *Context = lookupModuleUnqualified(Id[0].first, Mod); 1102b82c2a5SDouglas Gregor if (!Context) { 1112b82c2a5SDouglas Gregor if (Complain) 1120761a8a0SDaniel Jasper Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified) 113fb912657SDouglas Gregor << Id[0].first << Mod->getFullModuleName(); 1142b82c2a5SDouglas Gregor 115d2d442caSCraig Topper return nullptr; 1162b82c2a5SDouglas Gregor } 1172b82c2a5SDouglas Gregor 1182b82c2a5SDouglas Gregor // Dig into the module path. 119fb912657SDouglas Gregor for (unsigned I = 1, N = Id.size(); I != N; ++I) { 120fb912657SDouglas Gregor Module *Sub = lookupModuleQualified(Id[I].first, Context); 1212b82c2a5SDouglas Gregor if (!Sub) { 1222b82c2a5SDouglas Gregor if (Complain) 1230761a8a0SDaniel Jasper Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified) 124fb912657SDouglas Gregor << Id[I].first << Context->getFullModuleName() 125fb912657SDouglas Gregor << SourceRange(Id[0].second, Id[I-1].second); 1262b82c2a5SDouglas Gregor 127d2d442caSCraig Topper return nullptr; 1282b82c2a5SDouglas Gregor } 1292b82c2a5SDouglas Gregor 1302b82c2a5SDouglas Gregor Context = Sub; 1312b82c2a5SDouglas Gregor } 1322b82c2a5SDouglas Gregor 133fb912657SDouglas Gregor return Context; 1342b82c2a5SDouglas Gregor } 1352b82c2a5SDouglas Gregor 1361d60987fSRichard Smith /// \brief Append to \p Paths the set of paths needed to get to the 1371d60987fSRichard Smith /// subframework in which the given module lives. 1381d60987fSRichard Smith static void appendSubframeworkPaths(Module *Mod, 1391d60987fSRichard Smith SmallVectorImpl<char> &Path) { 1401d60987fSRichard Smith // Collect the framework names from the given module to the top-level module. 1411d60987fSRichard Smith SmallVector<StringRef, 2> Paths; 1421d60987fSRichard Smith for (; Mod; Mod = Mod->Parent) { 1431d60987fSRichard Smith if (Mod->IsFramework) 1441d60987fSRichard Smith Paths.push_back(Mod->Name); 1451d60987fSRichard Smith } 1461d60987fSRichard Smith 1471d60987fSRichard Smith if (Paths.empty()) 1481d60987fSRichard Smith return; 1491d60987fSRichard Smith 1501d60987fSRichard Smith // Add Frameworks/Name.framework for each subframework. 1511d60987fSRichard Smith for (unsigned I = Paths.size() - 1; I != 0; --I) 1521d60987fSRichard Smith llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework"); 1531d60987fSRichard Smith } 1541d60987fSRichard Smith 1551d60987fSRichard Smith const FileEntry * 156040e1266SRichard Smith ModuleMap::findHeader(Module *M, 157040e1266SRichard Smith const Module::UnresolvedHeaderDirective &Header, 1581d60987fSRichard Smith SmallVectorImpl<char> &RelativePathName) { 159040e1266SRichard Smith auto GetFile = [&](StringRef Filename) -> const FileEntry * { 160040e1266SRichard Smith auto *File = SourceMgr.getFileManager().getFile(Filename); 161040e1266SRichard Smith if (!File || 162040e1266SRichard Smith (Header.Size && File->getSize() != *Header.Size) || 163040e1266SRichard Smith (Header.ModTime && File->getModificationTime() != *Header.ModTime)) 164040e1266SRichard Smith return nullptr; 165040e1266SRichard Smith return File; 166040e1266SRichard Smith }; 167040e1266SRichard Smith 1681d60987fSRichard Smith if (llvm::sys::path::is_absolute(Header.FileName)) { 1691d60987fSRichard Smith RelativePathName.clear(); 1701d60987fSRichard Smith RelativePathName.append(Header.FileName.begin(), Header.FileName.end()); 171040e1266SRichard Smith return GetFile(Header.FileName); 1721d60987fSRichard Smith } 1731d60987fSRichard Smith 1741d60987fSRichard Smith // Search for the header file within the module's home directory. 1751d60987fSRichard Smith auto *Directory = M->Directory; 1761d60987fSRichard Smith SmallString<128> FullPathName(Directory->getName()); 1771d60987fSRichard Smith unsigned FullPathLength = FullPathName.size(); 1781d60987fSRichard Smith 1791d60987fSRichard Smith if (M->isPartOfFramework()) { 1801d60987fSRichard Smith appendSubframeworkPaths(M, RelativePathName); 1811d60987fSRichard Smith unsigned RelativePathLength = RelativePathName.size(); 1821d60987fSRichard Smith 1831d60987fSRichard Smith // Check whether this file is in the public headers. 1841d60987fSRichard Smith llvm::sys::path::append(RelativePathName, "Headers", Header.FileName); 1851d60987fSRichard Smith llvm::sys::path::append(FullPathName, RelativePathName); 186040e1266SRichard Smith if (auto *File = GetFile(FullPathName)) 1871d60987fSRichard Smith return File; 1881d60987fSRichard Smith 1891d60987fSRichard Smith // Check whether this file is in the private headers. 1901d60987fSRichard Smith // Ideally, private modules in the form 'FrameworkName.Private' should 1911d60987fSRichard Smith // be defined as 'module FrameworkName.Private', and not as 1921d60987fSRichard Smith // 'framework module FrameworkName.Private', since a 'Private.Framework' 1931d60987fSRichard Smith // does not usually exist. However, since both are currently widely used 1941d60987fSRichard Smith // for private modules, make sure we find the right path in both cases. 1951d60987fSRichard Smith if (M->IsFramework && M->Name == "Private") 1961d60987fSRichard Smith RelativePathName.clear(); 1971d60987fSRichard Smith else 1981d60987fSRichard Smith RelativePathName.resize(RelativePathLength); 1991d60987fSRichard Smith FullPathName.resize(FullPathLength); 2001d60987fSRichard Smith llvm::sys::path::append(RelativePathName, "PrivateHeaders", 2011d60987fSRichard Smith Header.FileName); 2021d60987fSRichard Smith llvm::sys::path::append(FullPathName, RelativePathName); 203040e1266SRichard Smith return GetFile(FullPathName); 2041d60987fSRichard Smith } 2051d60987fSRichard Smith 2061d60987fSRichard Smith // Lookup for normal headers. 2071d60987fSRichard Smith llvm::sys::path::append(RelativePathName, Header.FileName); 2081d60987fSRichard Smith llvm::sys::path::append(FullPathName, RelativePathName); 209040e1266SRichard Smith return GetFile(FullPathName); 2101d60987fSRichard Smith } 2111d60987fSRichard Smith 212040e1266SRichard Smith void ModuleMap::resolveHeader(Module *Mod, 213040e1266SRichard Smith const Module::UnresolvedHeaderDirective &Header) { 214040e1266SRichard Smith SmallString<128> RelativePathName; 215040e1266SRichard Smith if (const FileEntry *File = findHeader(Mod, Header, RelativePathName)) { 216040e1266SRichard Smith if (Header.IsUmbrella) { 217040e1266SRichard Smith const DirectoryEntry *UmbrellaDir = File->getDir(); 218040e1266SRichard Smith if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir]) 219040e1266SRichard Smith Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) 220040e1266SRichard Smith << UmbrellaMod->getFullModuleName(); 221040e1266SRichard Smith else 222040e1266SRichard Smith // Record this umbrella header. 223040e1266SRichard Smith setUmbrellaHeader(Mod, File, RelativePathName.str()); 224040e1266SRichard Smith } else { 225040e1266SRichard Smith Module::Header H = {RelativePathName.str(), File}; 226040e1266SRichard Smith if (Header.Kind == Module::HK_Excluded) 227040e1266SRichard Smith excludeHeader(Mod, H); 228040e1266SRichard Smith else 229040e1266SRichard Smith addHeader(Mod, H, headerKindToRole(Header.Kind)); 230040e1266SRichard Smith } 231040e1266SRichard Smith } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) { 232040e1266SRichard Smith // There's a builtin header but no corresponding on-disk header. Assume 233040e1266SRichard Smith // this was supposed to modularize the builtin header alone. 234040e1266SRichard Smith } else if (Header.Kind == Module::HK_Excluded) { 235040e1266SRichard Smith // Ignore missing excluded header files. They're optional anyway. 236040e1266SRichard Smith } else { 237040e1266SRichard Smith // If we find a module that has a missing header, we mark this module as 238040e1266SRichard Smith // unavailable and store the header directive for displaying diagnostics. 239040e1266SRichard Smith Mod->MissingHeaders.push_back(Header); 240040e1266SRichard Smith // A missing header with stat information doesn't make the module 241040e1266SRichard Smith // unavailable; this keeps our behavior consistent as headers are lazily 242040e1266SRichard Smith // resolved. (Such a module still can't be built though, except from 243040e1266SRichard Smith // preprocessed source.) 244040e1266SRichard Smith if (!Header.Size && !Header.ModTime) 245040e1266SRichard Smith Mod->markUnavailable(); 246040e1266SRichard Smith } 247040e1266SRichard Smith } 248040e1266SRichard Smith 249040e1266SRichard Smith bool ModuleMap::resolveAsBuiltinHeader( 250040e1266SRichard Smith Module *Mod, const Module::UnresolvedHeaderDirective &Header) { 251040e1266SRichard Smith if (Header.Kind == Module::HK_Excluded || 252040e1266SRichard Smith llvm::sys::path::is_absolute(Header.FileName) || 253040e1266SRichard Smith Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella || 254040e1266SRichard Smith !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory || 255040e1266SRichard Smith !isBuiltinHeader(Header.FileName)) 256040e1266SRichard Smith return false; 2571d60987fSRichard Smith 2581d60987fSRichard Smith // This is a system module with a top-level header. This header 2591d60987fSRichard Smith // may have a counterpart (or replacement) in the set of headers 2601d60987fSRichard Smith // supplied by Clang. Find that builtin header. 261040e1266SRichard Smith SmallString<128> Path; 262040e1266SRichard Smith llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName); 263040e1266SRichard Smith auto *File = SourceMgr.getFileManager().getFile(Path); 264040e1266SRichard Smith if (!File) 265040e1266SRichard Smith return false; 266040e1266SRichard Smith 267040e1266SRichard Smith auto Role = headerKindToRole(Header.Kind); 268040e1266SRichard Smith Module::Header H = {Path.str(), File}; 269040e1266SRichard Smith addHeader(Mod, H, Role); 270040e1266SRichard Smith return true; 2711d60987fSRichard Smith } 2721d60987fSRichard Smith 2730761a8a0SDaniel Jasper ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags, 274b146baabSArgyrios Kyrtzidis const LangOptions &LangOpts, const TargetInfo *Target, 275b146baabSArgyrios Kyrtzidis HeaderSearch &HeaderInfo) 2760761a8a0SDaniel Jasper : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target), 277056bf77fSRichard Smith HeaderInfo(HeaderInfo) { 2780414b857SRichard Smith MMapLangOpts.LineComment = true; 2790414b857SRichard Smith } 280718292f2SDouglas Gregor 281718292f2SDouglas Gregor ModuleMap::~ModuleMap() { 28221668754SDavide Italiano for (auto &M : Modules) 28321668754SDavide Italiano delete M.getValue(); 284*8587dfd9SBruno Cardoso Lopes for (auto *M : ShadowModules) 285*8587dfd9SBruno Cardoso Lopes delete M; 286718292f2SDouglas Gregor } 287718292f2SDouglas Gregor 28889929282SDouglas Gregor void ModuleMap::setTarget(const TargetInfo &Target) { 28989929282SDouglas Gregor assert((!this->Target || this->Target == &Target) && 29089929282SDouglas Gregor "Improper target override"); 29189929282SDouglas Gregor this->Target = &Target; 29289929282SDouglas Gregor } 29389929282SDouglas Gregor 294056396aeSDouglas Gregor /// \brief "Sanitize" a filename so that it can be used as an identifier. 295056396aeSDouglas Gregor static StringRef sanitizeFilenameAsIdentifier(StringRef Name, 296056396aeSDouglas Gregor SmallVectorImpl<char> &Buffer) { 297056396aeSDouglas Gregor if (Name.empty()) 298056396aeSDouglas Gregor return Name; 299056396aeSDouglas Gregor 300a7d03840SJordan Rose if (!isValidIdentifier(Name)) { 301056396aeSDouglas Gregor // If we don't already have something with the form of an identifier, 302056396aeSDouglas Gregor // create a buffer with the sanitized name. 303056396aeSDouglas Gregor Buffer.clear(); 304a7d03840SJordan Rose if (isDigit(Name[0])) 305056396aeSDouglas Gregor Buffer.push_back('_'); 306056396aeSDouglas Gregor Buffer.reserve(Buffer.size() + Name.size()); 307056396aeSDouglas Gregor for (unsigned I = 0, N = Name.size(); I != N; ++I) { 308a7d03840SJordan Rose if (isIdentifierBody(Name[I])) 309056396aeSDouglas Gregor Buffer.push_back(Name[I]); 310056396aeSDouglas Gregor else 311056396aeSDouglas Gregor Buffer.push_back('_'); 312056396aeSDouglas Gregor } 313056396aeSDouglas Gregor 314056396aeSDouglas Gregor Name = StringRef(Buffer.data(), Buffer.size()); 315056396aeSDouglas Gregor } 316056396aeSDouglas Gregor 317056396aeSDouglas Gregor while (llvm::StringSwitch<bool>(Name) 318056396aeSDouglas Gregor #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true) 319056396aeSDouglas Gregor #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true) 320056396aeSDouglas Gregor #include "clang/Basic/TokenKinds.def" 321056396aeSDouglas Gregor .Default(false)) { 322056396aeSDouglas Gregor if (Name.data() != Buffer.data()) 323056396aeSDouglas Gregor Buffer.append(Name.begin(), Name.end()); 324056396aeSDouglas Gregor Buffer.push_back('_'); 325056396aeSDouglas Gregor Name = StringRef(Buffer.data(), Buffer.size()); 326056396aeSDouglas Gregor } 327056396aeSDouglas Gregor 328056396aeSDouglas Gregor return Name; 329056396aeSDouglas Gregor } 330056396aeSDouglas Gregor 33134d52749SDouglas Gregor /// \brief Determine whether the given file name is the name of a builtin 33234d52749SDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system 33334d52749SDouglas Gregor /// headers. 334ba1b5c98SBruno Cardoso Lopes bool ModuleMap::isBuiltinHeader(StringRef FileName) { 33534d52749SDouglas Gregor return llvm::StringSwitch<bool>(FileName) 33634d52749SDouglas Gregor .Case("float.h", true) 33734d52749SDouglas Gregor .Case("iso646.h", true) 33834d52749SDouglas Gregor .Case("limits.h", true) 33934d52749SDouglas Gregor .Case("stdalign.h", true) 34034d52749SDouglas Gregor .Case("stdarg.h", true) 3413c4b1290SBen Langmuir .Case("stdatomic.h", true) 34234d52749SDouglas Gregor .Case("stdbool.h", true) 34334d52749SDouglas Gregor .Case("stddef.h", true) 34434d52749SDouglas Gregor .Case("stdint.h", true) 34534d52749SDouglas Gregor .Case("tgmath.h", true) 34634d52749SDouglas Gregor .Case("unwind.h", true) 34734d52749SDouglas Gregor .Default(false); 34834d52749SDouglas Gregor } 34934d52749SDouglas Gregor 35092669ee4SDaniel Jasper ModuleMap::HeadersMap::iterator 35192669ee4SDaniel Jasper ModuleMap::findKnownHeader(const FileEntry *File) { 352040e1266SRichard Smith resolveHeaderDirectives(File); 35359527666SDouglas Gregor HeadersMap::iterator Known = Headers.find(File); 35447972afdSRichard Smith if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && 35547972afdSRichard Smith Known == Headers.end() && File->getDir() == BuiltinIncludeDir && 356ba1b5c98SBruno Cardoso Lopes ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()))) { 3574eaf0a6cSDaniel Jasper HeaderInfo.loadTopLevelSystemModules(); 35892669ee4SDaniel Jasper return Headers.find(File); 3594eaf0a6cSDaniel Jasper } 36092669ee4SDaniel Jasper return Known; 36192669ee4SDaniel Jasper } 36292669ee4SDaniel Jasper 3634469138eSBen Langmuir ModuleMap::KnownHeader 3644469138eSBen Langmuir ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File, 3654469138eSBen Langmuir SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) { 36647972afdSRichard Smith if (UmbrellaDirs.empty()) 367afd1b1c9SEugene Zelenko return {}; 36847972afdSRichard Smith 3694469138eSBen Langmuir const DirectoryEntry *Dir = File->getDir(); 3704469138eSBen Langmuir assert(Dir && "file in no directory"); 3714469138eSBen Langmuir 3724469138eSBen Langmuir // Note: as an egregious but useful hack we use the real path here, because 3734469138eSBen Langmuir // frameworks moving from top-level frameworks to embedded frameworks tend 3744469138eSBen Langmuir // to be symlinked from the top-level location to the embedded location, 3754469138eSBen Langmuir // and we need to resolve lookups as if we had found the embedded location. 3764469138eSBen Langmuir StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir); 3774469138eSBen Langmuir 3784469138eSBen Langmuir // Keep walking up the directory hierarchy, looking for a directory with 3794469138eSBen Langmuir // an umbrella header. 3804469138eSBen Langmuir do { 3814469138eSBen Langmuir auto KnownDir = UmbrellaDirs.find(Dir); 3824469138eSBen Langmuir if (KnownDir != UmbrellaDirs.end()) 3834469138eSBen Langmuir return KnownHeader(KnownDir->second, NormalHeader); 3844469138eSBen Langmuir 3854469138eSBen Langmuir IntermediateDirs.push_back(Dir); 3864469138eSBen Langmuir 3874469138eSBen Langmuir // Retrieve our parent path. 3884469138eSBen Langmuir DirName = llvm::sys::path::parent_path(DirName); 3894469138eSBen Langmuir if (DirName.empty()) 3904469138eSBen Langmuir break; 3914469138eSBen Langmuir 3924469138eSBen Langmuir // Resolve the parent path to a directory entry. 3934469138eSBen Langmuir Dir = SourceMgr.getFileManager().getDirectory(DirName); 3944469138eSBen Langmuir } while (Dir); 395afd1b1c9SEugene Zelenko return {}; 3964469138eSBen Langmuir } 3974469138eSBen Langmuir 39892669ee4SDaniel Jasper static bool violatesPrivateInclude(Module *RequestingModule, 39992669ee4SDaniel Jasper const FileEntry *IncFileEnt, 4004eb8393cSRichard Smith ModuleMap::KnownHeader Header) { 40192669ee4SDaniel Jasper #ifndef NDEBUG 4024eb8393cSRichard Smith if (Header.getRole() & ModuleMap::PrivateHeader) { 40392669ee4SDaniel Jasper // Check for consistency between the module header role 40492669ee4SDaniel Jasper // as obtained from the lookup and as obtained from the module. 40592669ee4SDaniel Jasper // This check is not cheap, so enable it only for debugging. 4062708e520SRichard Smith bool IsPrivate = false; 4072708e520SRichard Smith SmallVectorImpl<Module::Header> *HeaderList[] = { 4084eb8393cSRichard Smith &Header.getModule()->Headers[Module::HK_Private], 4094eb8393cSRichard Smith &Header.getModule()->Headers[Module::HK_PrivateTextual]}; 4102708e520SRichard Smith for (auto *Hs : HeaderList) 4112708e520SRichard Smith IsPrivate |= 4122708e520SRichard Smith std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) { 4133c1a41adSRichard Smith return H.Entry == IncFileEnt; 4142708e520SRichard Smith }) != Hs->end(); 4154eb8393cSRichard Smith assert(IsPrivate && "inconsistent headers and roles"); 41600bc95ecSRichard Smith } 41792669ee4SDaniel Jasper #endif 4184eb8393cSRichard Smith return !Header.isAccessibleFrom(RequestingModule); 41992669ee4SDaniel Jasper } 42092669ee4SDaniel Jasper 42171e1a64fSBen Langmuir static Module *getTopLevelOrNull(Module *M) { 42271e1a64fSBen Langmuir return M ? M->getTopLevelModule() : nullptr; 42371e1a64fSBen Langmuir } 42471e1a64fSBen Langmuir 42592669ee4SDaniel Jasper void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, 4268d4e90b3SRichard Smith bool RequestingModuleIsModuleInterface, 42792669ee4SDaniel Jasper SourceLocation FilenameLoc, 42892669ee4SDaniel Jasper StringRef Filename, 42992669ee4SDaniel Jasper const FileEntry *File) { 43092669ee4SDaniel Jasper // No errors for indirect modules. This may be a bit of a problem for modules 43192669ee4SDaniel Jasper // with no source files. 43271e1a64fSBen Langmuir if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule)) 43392669ee4SDaniel Jasper return; 43492669ee4SDaniel Jasper 435040e1266SRichard Smith if (RequestingModule) { 43692669ee4SDaniel Jasper resolveUses(RequestingModule, /*Complain=*/false); 437040e1266SRichard Smith resolveHeaderDirectives(RequestingModule); 438040e1266SRichard Smith } 43992669ee4SDaniel Jasper 44071e1a64fSBen Langmuir bool Excluded = false; 441d2d442caSCraig Topper Module *Private = nullptr; 442d2d442caSCraig Topper Module *NotUsed = nullptr; 44371e1a64fSBen Langmuir 44471e1a64fSBen Langmuir HeadersMap::iterator Known = findKnownHeader(File); 44571e1a64fSBen Langmuir if (Known != Headers.end()) { 44671e1a64fSBen Langmuir for (const KnownHeader &Header : Known->second) { 44792669ee4SDaniel Jasper // Remember private headers for later printing of a diagnostic. 4484eb8393cSRichard Smith if (violatesPrivateInclude(RequestingModule, File, Header)) { 44971e1a64fSBen Langmuir Private = Header.getModule(); 45092669ee4SDaniel Jasper continue; 45192669ee4SDaniel Jasper } 45292669ee4SDaniel Jasper 45392669ee4SDaniel Jasper // If uses need to be specified explicitly, we are only allowed to return 45492669ee4SDaniel Jasper // modules that are explicitly used by the requesting module. 45592669ee4SDaniel Jasper if (RequestingModule && LangOpts.ModulesDeclUse && 4568f4d3ff1SRichard Smith !RequestingModule->directlyUses(Header.getModule())) { 45771e1a64fSBen Langmuir NotUsed = Header.getModule(); 45892669ee4SDaniel Jasper continue; 45992669ee4SDaniel Jasper } 46092669ee4SDaniel Jasper 46192669ee4SDaniel Jasper // We have found a module that we can happily use. 46292669ee4SDaniel Jasper return; 46392669ee4SDaniel Jasper } 464feb54b6dSRichard Smith 465feb54b6dSRichard Smith Excluded = true; 46671e1a64fSBen Langmuir } 46792669ee4SDaniel Jasper 46892669ee4SDaniel Jasper // We have found a header, but it is private. 469d2d442caSCraig Topper if (Private) { 47011152dd5SRichard Smith Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module) 47192669ee4SDaniel Jasper << Filename; 47292669ee4SDaniel Jasper return; 47392669ee4SDaniel Jasper } 47492669ee4SDaniel Jasper 47592669ee4SDaniel Jasper // We have found a module, but we don't use it. 476d2d442caSCraig Topper if (NotUsed) { 47711152dd5SRichard Smith Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) 47892669ee4SDaniel Jasper << RequestingModule->getFullModuleName() << Filename; 47992669ee4SDaniel Jasper return; 48092669ee4SDaniel Jasper } 48192669ee4SDaniel Jasper 48271e1a64fSBen Langmuir if (Excluded || isHeaderInUmbrellaDirs(File)) 48371e1a64fSBen Langmuir return; 48471e1a64fSBen Langmuir 48571e1a64fSBen Langmuir // At this point, only non-modular includes remain. 48671e1a64fSBen Langmuir 48771e1a64fSBen Langmuir if (LangOpts.ModulesStrictDeclUse) { 48811152dd5SRichard Smith Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) 48971e1a64fSBen Langmuir << RequestingModule->getFullModuleName() << Filename; 490a67e4d32SManman Ren } else if (RequestingModule && RequestingModuleIsModuleInterface && 491a67e4d32SManman Ren LangOpts.isCompilingModule()) { 492a67e4d32SManman Ren // Do not diagnose when we are not compiling a module. 49371e1a64fSBen Langmuir diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ? 49471e1a64fSBen Langmuir diag::warn_non_modular_include_in_framework_module : 49571e1a64fSBen Langmuir diag::warn_non_modular_include_in_module; 49670a7738fSManman Ren Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName() 49770a7738fSManman Ren << File->getName(); 49871e1a64fSBen Langmuir } 49992669ee4SDaniel Jasper } 50092669ee4SDaniel Jasper 501ec87a50aSRichard Smith static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New, 502ec87a50aSRichard Smith const ModuleMap::KnownHeader &Old) { 5038b7c0398SSean Silva // Prefer available modules. 5048b7c0398SSean Silva if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable()) 5058b7c0398SSean Silva return true; 5068b7c0398SSean Silva 507ec87a50aSRichard Smith // Prefer a public header over a private header. 508ec87a50aSRichard Smith if ((New.getRole() & ModuleMap::PrivateHeader) != 509ec87a50aSRichard Smith (Old.getRole() & ModuleMap::PrivateHeader)) 510ec87a50aSRichard Smith return !(New.getRole() & ModuleMap::PrivateHeader); 511ec87a50aSRichard Smith 512ec87a50aSRichard Smith // Prefer a non-textual header over a textual header. 513ec87a50aSRichard Smith if ((New.getRole() & ModuleMap::TextualHeader) != 514ec87a50aSRichard Smith (Old.getRole() & ModuleMap::TextualHeader)) 515ec87a50aSRichard Smith return !(New.getRole() & ModuleMap::TextualHeader); 516ec87a50aSRichard Smith 517ec87a50aSRichard Smith // Don't have a reason to choose between these. Just keep the first one. 518ec87a50aSRichard Smith return false; 519ec87a50aSRichard Smith } 520ec87a50aSRichard Smith 521ed84df00SBruno Cardoso Lopes ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File, 522ed84df00SBruno Cardoso Lopes bool AllowTextual) { 523306d8920SRichard Smith auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader { 524ed84df00SBruno Cardoso Lopes if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader) 525afd1b1c9SEugene Zelenko return {}; 526306d8920SRichard Smith return R; 527306d8920SRichard Smith }; 528306d8920SRichard Smith 5294881e8b2SSean Silva HeadersMap::iterator Known = findKnownHeader(File); 5301fb5c3a6SDouglas Gregor if (Known != Headers.end()) { 531202210b3SRichard Smith ModuleMap::KnownHeader Result; 53297da9178SDaniel Jasper // Iterate over all modules that 'File' is part of to find the best fit. 5334881e8b2SSean Silva for (KnownHeader &H : Known->second) { 5347e82e019SRichard Smith // Prefer a header from the source module over all others. 5357e82e019SRichard Smith if (H.getModule()->getTopLevelModule() == SourceModule) 5362f633e7cSRichard Smith return MakeResult(H); 5374881e8b2SSean Silva if (!Result || isBetterKnownHeader(H, Result)) 5384881e8b2SSean Silva Result = H; 53997da9178SDaniel Jasper } 540306d8920SRichard Smith return MakeResult(Result); 5411fb5c3a6SDouglas Gregor } 542ab0c8a84SDouglas Gregor 543386bb073SRichard Smith return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File)); 544386bb073SRichard Smith } 545386bb073SRichard Smith 546386bb073SRichard Smith ModuleMap::KnownHeader 547386bb073SRichard Smith ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) { 548386bb073SRichard Smith assert(!Headers.count(File) && "already have a module for this header"); 549386bb073SRichard Smith 550f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs; 5514469138eSBen Langmuir KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs); 5524469138eSBen Langmuir if (H) { 5534469138eSBen Langmuir Module *Result = H.getModule(); 554930a85ccSDouglas Gregor 555930a85ccSDouglas Gregor // Search up the module stack until we find a module with an umbrella 55673141fa9SDouglas Gregor // directory. 557930a85ccSDouglas Gregor Module *UmbrellaModule = Result; 55873141fa9SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 559930a85ccSDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 560930a85ccSDouglas Gregor 561930a85ccSDouglas Gregor if (UmbrellaModule->InferSubmodules) { 5629d6448b1SBen Langmuir const FileEntry *UmbrellaModuleMap = 5639d6448b1SBen Langmuir getModuleMapFileForUniquing(UmbrellaModule); 5649d6448b1SBen Langmuir 565a89c5ac4SDouglas Gregor // Infer submodules for each of the directories we found between 566a89c5ac4SDouglas Gregor // the directory of the umbrella header and the directory where 567a89c5ac4SDouglas Gregor // the actual header is located. 5689458f82dSDouglas Gregor bool Explicit = UmbrellaModule->InferExplicitSubmodules; 5699458f82dSDouglas Gregor 5707033127bSDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 571a89c5ac4SDouglas Gregor // Find or create the module that corresponds to this directory name. 572056396aeSDouglas Gregor SmallString<32> NameBuf; 573056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 5744469138eSBen Langmuir llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf); 5759d6448b1SBen Langmuir Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 5769d6448b1SBen Langmuir Explicit).first; 5779d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = UmbrellaModuleMap; 578ffbafa2aSBen Langmuir Result->IsInferred = true; 579a89c5ac4SDouglas Gregor 580a89c5ac4SDouglas Gregor // Associate the module and the directory. 581a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I-1]] = Result; 582a89c5ac4SDouglas Gregor 583a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 584a89c5ac4SDouglas Gregor // wildcard to the set of exports. 585930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 586d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 587a89c5ac4SDouglas Gregor } 588a89c5ac4SDouglas Gregor 589a89c5ac4SDouglas Gregor // Infer a submodule with the same name as this header file. 590056396aeSDouglas Gregor SmallString<32> NameBuf; 591056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 592056396aeSDouglas Gregor llvm::sys::path::stem(File->getName()), NameBuf); 5939d6448b1SBen Langmuir Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 5949d6448b1SBen Langmuir Explicit).first; 5959d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = UmbrellaModuleMap; 596ffbafa2aSBen Langmuir Result->IsInferred = true; 5973c5305c1SArgyrios Kyrtzidis Result->addTopHeader(File); 598a89c5ac4SDouglas Gregor 599a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 600a89c5ac4SDouglas Gregor // wildcard to the set of exports. 601930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 602d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 603a89c5ac4SDouglas Gregor } else { 604a89c5ac4SDouglas Gregor // Record each of the directories we stepped through as being part of 605a89c5ac4SDouglas Gregor // the module we found, since the umbrella header covers them all. 606a89c5ac4SDouglas Gregor for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I) 607a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I]] = Result; 608a89c5ac4SDouglas Gregor } 609a89c5ac4SDouglas Gregor 610386bb073SRichard Smith KnownHeader Header(Result, NormalHeader); 611386bb073SRichard Smith Headers[File].push_back(Header); 612386bb073SRichard Smith return Header; 613a89c5ac4SDouglas Gregor } 614a89c5ac4SDouglas Gregor 615afd1b1c9SEugene Zelenko return {}; 616ab0c8a84SDouglas Gregor } 617ab0c8a84SDouglas Gregor 618386bb073SRichard Smith ArrayRef<ModuleMap::KnownHeader> 619386bb073SRichard Smith ModuleMap::findAllModulesForHeader(const FileEntry *File) const { 620040e1266SRichard Smith resolveHeaderDirectives(File); 621386bb073SRichard Smith auto It = Headers.find(File); 622386bb073SRichard Smith if (It == Headers.end()) 623386bb073SRichard Smith return None; 624386bb073SRichard Smith return It->second; 625386bb073SRichard Smith } 626386bb073SRichard Smith 627e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const { 628d2d442caSCraig Topper return isHeaderUnavailableInModule(Header, nullptr); 62950996ce1SRichard Smith } 63050996ce1SRichard Smith 63162bcd925SDmitri Gribenko bool 63262bcd925SDmitri Gribenko ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, 63362bcd925SDmitri Gribenko const Module *RequestingModule) const { 634040e1266SRichard Smith resolveHeaderDirectives(Header); 635e4412640SArgyrios Kyrtzidis HeadersMap::const_iterator Known = Headers.find(Header); 63697da9178SDaniel Jasper if (Known != Headers.end()) { 63797da9178SDaniel Jasper for (SmallVectorImpl<KnownHeader>::const_iterator 63897da9178SDaniel Jasper I = Known->second.begin(), 63997da9178SDaniel Jasper E = Known->second.end(); 64097da9178SDaniel Jasper I != E; ++I) { 641052d95a6SBruno Cardoso Lopes 642052d95a6SBruno Cardoso Lopes if (I->isAvailable() && 643052d95a6SBruno Cardoso Lopes (!RequestingModule || 644052d95a6SBruno Cardoso Lopes I->getModule()->isSubModuleOf(RequestingModule))) { 645052d95a6SBruno Cardoso Lopes // When no requesting module is available, the caller is looking if a 646052d95a6SBruno Cardoso Lopes // header is part a module by only looking into the module map. This is 647052d95a6SBruno Cardoso Lopes // done by warn_uncovered_module_header checks; don't consider textual 648052d95a6SBruno Cardoso Lopes // headers part of it in this mode, otherwise we get misleading warnings 649052d95a6SBruno Cardoso Lopes // that a umbrella header is not including a textual header. 650052d95a6SBruno Cardoso Lopes if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader) 651052d95a6SBruno Cardoso Lopes continue; 65297da9178SDaniel Jasper return false; 65397da9178SDaniel Jasper } 654052d95a6SBruno Cardoso Lopes } 65597da9178SDaniel Jasper return true; 65697da9178SDaniel Jasper } 6571fb5c3a6SDouglas Gregor 6581fb5c3a6SDouglas Gregor const DirectoryEntry *Dir = Header->getDir(); 659f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs; 6601fb5c3a6SDouglas Gregor StringRef DirName = Dir->getName(); 6611fb5c3a6SDouglas Gregor 66250996ce1SRichard Smith auto IsUnavailable = [&](const Module *M) { 66350996ce1SRichard Smith return !M->isAvailable() && (!RequestingModule || 66450996ce1SRichard Smith M->isSubModuleOf(RequestingModule)); 66550996ce1SRichard Smith }; 66650996ce1SRichard Smith 6671fb5c3a6SDouglas Gregor // Keep walking up the directory hierarchy, looking for a directory with 6681fb5c3a6SDouglas Gregor // an umbrella header. 6691fb5c3a6SDouglas Gregor do { 670e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir 6711fb5c3a6SDouglas Gregor = UmbrellaDirs.find(Dir); 6721fb5c3a6SDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 6731fb5c3a6SDouglas Gregor Module *Found = KnownDir->second; 67450996ce1SRichard Smith if (IsUnavailable(Found)) 6751fb5c3a6SDouglas Gregor return true; 6761fb5c3a6SDouglas Gregor 6771fb5c3a6SDouglas Gregor // Search up the module stack until we find a module with an umbrella 6781fb5c3a6SDouglas Gregor // directory. 6791fb5c3a6SDouglas Gregor Module *UmbrellaModule = Found; 6801fb5c3a6SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 6811fb5c3a6SDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 6821fb5c3a6SDouglas Gregor 6831fb5c3a6SDouglas Gregor if (UmbrellaModule->InferSubmodules) { 6841fb5c3a6SDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 6851fb5c3a6SDouglas Gregor // Find or create the module that corresponds to this directory name. 686056396aeSDouglas Gregor SmallString<32> NameBuf; 687056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 688056396aeSDouglas Gregor llvm::sys::path::stem(SkippedDirs[I-1]->getName()), 689056396aeSDouglas Gregor NameBuf); 6901fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 6911fb5c3a6SDouglas Gregor if (!Found) 6921fb5c3a6SDouglas Gregor return false; 69350996ce1SRichard Smith if (IsUnavailable(Found)) 6941fb5c3a6SDouglas Gregor return true; 6951fb5c3a6SDouglas Gregor } 6961fb5c3a6SDouglas Gregor 6971fb5c3a6SDouglas Gregor // Infer a submodule with the same name as this header file. 698056396aeSDouglas Gregor SmallString<32> NameBuf; 699056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 700056396aeSDouglas Gregor llvm::sys::path::stem(Header->getName()), 701056396aeSDouglas Gregor NameBuf); 7021fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 7031fb5c3a6SDouglas Gregor if (!Found) 7041fb5c3a6SDouglas Gregor return false; 7051fb5c3a6SDouglas Gregor } 7061fb5c3a6SDouglas Gregor 70750996ce1SRichard Smith return IsUnavailable(Found); 7081fb5c3a6SDouglas Gregor } 7091fb5c3a6SDouglas Gregor 7101fb5c3a6SDouglas Gregor SkippedDirs.push_back(Dir); 7111fb5c3a6SDouglas Gregor 7121fb5c3a6SDouglas Gregor // Retrieve our parent path. 7131fb5c3a6SDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 7141fb5c3a6SDouglas Gregor if (DirName.empty()) 7151fb5c3a6SDouglas Gregor break; 7161fb5c3a6SDouglas Gregor 7171fb5c3a6SDouglas Gregor // Resolve the parent path to a directory entry. 7181f76c4e8SManuel Klimek Dir = SourceMgr.getFileManager().getDirectory(DirName); 7191fb5c3a6SDouglas Gregor } while (Dir); 7201fb5c3a6SDouglas Gregor 7211fb5c3a6SDouglas Gregor return false; 7221fb5c3a6SDouglas Gregor } 7231fb5c3a6SDouglas Gregor 724e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const { 725e4412640SArgyrios Kyrtzidis llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name); 72688bdfb0eSDouglas Gregor if (Known != Modules.end()) 72788bdfb0eSDouglas Gregor return Known->getValue(); 72888bdfb0eSDouglas Gregor 729d2d442caSCraig Topper return nullptr; 73088bdfb0eSDouglas Gregor } 73188bdfb0eSDouglas Gregor 732e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name, 733e4412640SArgyrios Kyrtzidis Module *Context) const { 7342b82c2a5SDouglas Gregor for(; Context; Context = Context->Parent) { 7352b82c2a5SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Context)) 7362b82c2a5SDouglas Gregor return Sub; 7372b82c2a5SDouglas Gregor } 7382b82c2a5SDouglas Gregor 7392b82c2a5SDouglas Gregor return findModule(Name); 7402b82c2a5SDouglas Gregor } 7412b82c2a5SDouglas Gregor 742e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{ 7432b82c2a5SDouglas Gregor if (!Context) 7442b82c2a5SDouglas Gregor return findModule(Name); 7452b82c2a5SDouglas Gregor 746eb90e830SDouglas Gregor return Context->findSubmodule(Name); 7472b82c2a5SDouglas Gregor } 7482b82c2a5SDouglas Gregor 749*8587dfd9SBruno Cardoso Lopes std::pair<Module *, bool> 750*8587dfd9SBruno Cardoso Lopes ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework, 751*8587dfd9SBruno Cardoso Lopes bool IsExplicit, bool UsesExplicitModuleMapFile) { 75269021974SDouglas Gregor // Try to find an existing module with this name. 753eb90e830SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Parent)) 754eb90e830SDouglas Gregor return std::make_pair(Sub, false); 75569021974SDouglas Gregor 75669021974SDouglas Gregor // Create a new module with this name. 7579ffe5a35SDavid Blaikie Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, 7589ffe5a35SDavid Blaikie IsExplicit, NumCreatedModules++); 7596f722b4eSArgyrios Kyrtzidis if (!Parent) { 7607e82e019SRichard Smith if (LangOpts.CurrentModule == Name) 7617e82e019SRichard Smith SourceModule = Result; 76269021974SDouglas Gregor Modules[Name] = Result; 763*8587dfd9SBruno Cardoso Lopes if (UsesExplicitModuleMapFile) 764*8587dfd9SBruno Cardoso Lopes ExplicitlyProvidedModules.insert(Result); 7656f722b4eSArgyrios Kyrtzidis } 76669021974SDouglas Gregor return std::make_pair(Result, true); 76769021974SDouglas Gregor } 76869021974SDouglas Gregor 769dd8b5337SRichard Smith Module *ModuleMap::createGlobalModuleForInterfaceUnit(SourceLocation Loc) { 770056bf77fSRichard Smith assert(!PendingGlobalModule && "created multiple global modules"); 771056bf77fSRichard Smith PendingGlobalModule.reset( 772056bf77fSRichard Smith new Module("<global>", Loc, nullptr, /*IsFramework*/ false, 773056bf77fSRichard Smith /*IsExplicit*/ true, NumCreatedModules++)); 774056bf77fSRichard Smith PendingGlobalModule->Kind = Module::GlobalModuleFragment; 775056bf77fSRichard Smith return PendingGlobalModule.get(); 776dd8b5337SRichard Smith } 777dd8b5337SRichard Smith 778bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc, 779dd8b5337SRichard Smith StringRef Name, 780dd8b5337SRichard Smith Module *GlobalModule) { 781bbcc9f04SRichard Smith assert(LangOpts.CurrentModule == Name && "module name mismatch"); 782bbcc9f04SRichard Smith assert(!Modules[Name] && "redefining existing module"); 783bbcc9f04SRichard Smith 784bbcc9f04SRichard Smith auto *Result = 785bbcc9f04SRichard Smith new Module(Name, Loc, nullptr, /*IsFramework*/ false, 786bbcc9f04SRichard Smith /*IsExplicit*/ false, NumCreatedModules++); 787145e15a3SRichard Smith Result->Kind = Module::ModuleInterfaceUnit; 788bbcc9f04SRichard Smith Modules[Name] = SourceModule = Result; 789bbcc9f04SRichard Smith 790dd8b5337SRichard Smith // Reparent the current global module fragment as a submodule of this module. 791056bf77fSRichard Smith assert(GlobalModule == PendingGlobalModule.get() && 792056bf77fSRichard Smith "unexpected global module"); 793dd8b5337SRichard Smith GlobalModule->setParent(Result); 794056bf77fSRichard Smith PendingGlobalModule.release(); // now owned by parent 795dd8b5337SRichard Smith 796bbcc9f04SRichard Smith // Mark the main source file as being within the newly-created module so that 797bbcc9f04SRichard Smith // declarations and macros are properly visibility-restricted to it. 798bbcc9f04SRichard Smith auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()); 799bbcc9f04SRichard Smith assert(MainFile && "no input file for module interface"); 800bbcc9f04SRichard Smith Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader)); 801bbcc9f04SRichard Smith 802bbcc9f04SRichard Smith return Result; 803bbcc9f04SRichard Smith } 804bbcc9f04SRichard Smith 80511dfe6feSDouglas Gregor /// \brief For a framework module, infer the framework against which we 80611dfe6feSDouglas Gregor /// should link. 80711dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir, 80811dfe6feSDouglas Gregor FileManager &FileMgr) { 80911dfe6feSDouglas Gregor assert(Mod->IsFramework && "Can only infer linking for framework modules"); 81011dfe6feSDouglas Gregor assert(!Mod->isSubFramework() && 81111dfe6feSDouglas Gregor "Can only infer linking for top-level frameworks"); 81211dfe6feSDouglas Gregor 81311dfe6feSDouglas Gregor SmallString<128> LibName; 81411dfe6feSDouglas Gregor LibName += FrameworkDir->getName(); 81511dfe6feSDouglas Gregor llvm::sys::path::append(LibName, Mod->Name); 8168aaae5a9SJuergen Ributzka 8178aaae5a9SJuergen Ributzka // The library name of a framework has more than one possible extension since 8188aaae5a9SJuergen Ributzka // the introduction of the text-based dynamic library format. We need to check 8198aaae5a9SJuergen Ributzka // for both before we give up. 8208013e81dSBenjamin Kramer for (const char *extension : {"", ".tbd"}) { 8218aaae5a9SJuergen Ributzka llvm::sys::path::replace_extension(LibName, extension); 82211dfe6feSDouglas Gregor if (FileMgr.getFile(LibName)) { 82311dfe6feSDouglas Gregor Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name, 82411dfe6feSDouglas Gregor /*IsFramework=*/true)); 8258aaae5a9SJuergen Ributzka return; 8268aaae5a9SJuergen Ributzka } 82711dfe6feSDouglas Gregor } 82811dfe6feSDouglas Gregor } 82911dfe6feSDouglas Gregor 830a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 831a525400dSBen Langmuir bool IsSystem, Module *Parent) { 832c1d88ea5SBen Langmuir Attributes Attrs; 833c1d88ea5SBen Langmuir Attrs.IsSystem = IsSystem; 834a525400dSBen Langmuir return inferFrameworkModule(FrameworkDir, Attrs, Parent); 835c1d88ea5SBen Langmuir } 836c1d88ea5SBen Langmuir 837a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 838c1d88ea5SBen Langmuir Attributes Attrs, Module *Parent) { 839a525400dSBen Langmuir // Note: as an egregious but useful hack we use the real path here, because 840a525400dSBen Langmuir // we might be looking at an embedded framework that symlinks out to a 841a525400dSBen Langmuir // top-level framework, and we need to infer as if we were naming the 842a525400dSBen Langmuir // top-level framework. 843a525400dSBen Langmuir StringRef FrameworkDirName = 844a525400dSBen Langmuir SourceMgr.getFileManager().getCanonicalName(FrameworkDir); 845a525400dSBen Langmuir 846a525400dSBen Langmuir // In case this is a case-insensitive filesystem, use the canonical 847a525400dSBen Langmuir // directory name as the ModuleName, since modules are case-sensitive. 848a525400dSBen Langmuir // FIXME: we should be able to give a fix-it hint for the correct spelling. 849a525400dSBen Langmuir SmallString<32> ModuleNameStorage; 850a525400dSBen Langmuir StringRef ModuleName = sanitizeFilenameAsIdentifier( 851a525400dSBen Langmuir llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage); 852c1d88ea5SBen Langmuir 85356c64013SDouglas Gregor // Check whether we've already found this module. 854e89dbc1dSDouglas Gregor if (Module *Mod = lookupModuleQualified(ModuleName, Parent)) 855e89dbc1dSDouglas Gregor return Mod; 856e89dbc1dSDouglas Gregor 8571f76c4e8SManuel Klimek FileManager &FileMgr = SourceMgr.getFileManager(); 85856c64013SDouglas Gregor 8599194a91dSDouglas Gregor // If the framework has a parent path from which we're allowed to infer 8609194a91dSDouglas Gregor // a framework module, do so. 861beee15e7SBen Langmuir const FileEntry *ModuleMapFile = nullptr; 8629194a91dSDouglas Gregor if (!Parent) { 8634ddf2221SDouglas Gregor // Determine whether we're allowed to infer a module map. 8649194a91dSDouglas Gregor bool canInfer = false; 8654ddf2221SDouglas Gregor if (llvm::sys::path::has_parent_path(FrameworkDirName)) { 8669194a91dSDouglas Gregor // Figure out the parent path. 8674ddf2221SDouglas Gregor StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName); 8689194a91dSDouglas Gregor if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) { 8699194a91dSDouglas Gregor // Check whether we have already looked into the parent directory 8709194a91dSDouglas Gregor // for a module map. 871e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator 8729194a91dSDouglas Gregor inferred = InferredDirectories.find(ParentDir); 8739194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) { 8749194a91dSDouglas Gregor // We haven't looked here before. Load a module map, if there is 8759194a91dSDouglas Gregor // one. 876984e1df7SBen Langmuir bool IsFrameworkDir = Parent.endswith(".framework"); 877984e1df7SBen Langmuir if (const FileEntry *ModMapFile = 878984e1df7SBen Langmuir HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) { 879c1d88ea5SBen Langmuir parseModuleMapFile(ModMapFile, Attrs.IsSystem, ParentDir); 8809194a91dSDouglas Gregor inferred = InferredDirectories.find(ParentDir); 8819194a91dSDouglas Gregor } 8829194a91dSDouglas Gregor 8839194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) 8849194a91dSDouglas Gregor inferred = InferredDirectories.insert( 8859194a91dSDouglas Gregor std::make_pair(ParentDir, InferredDirectory())).first; 8869194a91dSDouglas Gregor } 8879194a91dSDouglas Gregor 8889194a91dSDouglas Gregor if (inferred->second.InferModules) { 8899194a91dSDouglas Gregor // We're allowed to infer for this directory, but make sure it's okay 8909194a91dSDouglas Gregor // to infer this particular module. 8914ddf2221SDouglas Gregor StringRef Name = llvm::sys::path::stem(FrameworkDirName); 8929194a91dSDouglas Gregor canInfer = std::find(inferred->second.ExcludedModules.begin(), 8939194a91dSDouglas Gregor inferred->second.ExcludedModules.end(), 8949194a91dSDouglas Gregor Name) == inferred->second.ExcludedModules.end(); 8959194a91dSDouglas Gregor 896c1d88ea5SBen Langmuir Attrs.IsSystem |= inferred->second.Attrs.IsSystem; 897c1d88ea5SBen Langmuir Attrs.IsExternC |= inferred->second.Attrs.IsExternC; 898c1d88ea5SBen Langmuir Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive; 899ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes |= 900ed84df00SBruno Cardoso Lopes inferred->second.Attrs.NoUndeclaredIncludes; 901beee15e7SBen Langmuir ModuleMapFile = inferred->second.ModuleMapFile; 9029194a91dSDouglas Gregor } 9039194a91dSDouglas Gregor } 9049194a91dSDouglas Gregor } 9059194a91dSDouglas Gregor 9069194a91dSDouglas Gregor // If we're not allowed to infer a framework module, don't. 9079194a91dSDouglas Gregor if (!canInfer) 908d2d442caSCraig Topper return nullptr; 909beee15e7SBen Langmuir } else 9109d6448b1SBen Langmuir ModuleMapFile = getModuleMapFileForUniquing(Parent); 9119194a91dSDouglas Gregor 9129194a91dSDouglas Gregor 91356c64013SDouglas Gregor // Look for an umbrella header. 9142c1dd271SDylan Noblesmith SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 91517381a06SBenjamin Kramer llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h"); 916e89dbc1dSDouglas Gregor const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName); 91756c64013SDouglas Gregor 91856c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the 91956c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good 92056c64013SDouglas Gregor // idea. 92156c64013SDouglas Gregor if (!UmbrellaHeader) 922d2d442caSCraig Topper return nullptr; 92356c64013SDouglas Gregor 9249d6448b1SBen Langmuir Module *Result = new Module(ModuleName, SourceLocation(), Parent, 925a7e2cc68SRichard Smith /*IsFramework=*/true, /*IsExplicit=*/false, 926a7e2cc68SRichard Smith NumCreatedModules++); 9279d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = ModuleMapFile; 9289d6448b1SBen Langmuir Result->IsInferred = true; 9297e82e019SRichard Smith if (!Parent) { 9307e82e019SRichard Smith if (LangOpts.CurrentModule == ModuleName) 931ba7f2f71SDaniel Jasper SourceModule = Result; 9327e82e019SRichard Smith Modules[ModuleName] = Result; 933ba7f2f71SDaniel Jasper } 934c1d88ea5SBen Langmuir 935c1d88ea5SBen Langmuir Result->IsSystem |= Attrs.IsSystem; 936c1d88ea5SBen Langmuir Result->IsExternC |= Attrs.IsExternC; 937c1d88ea5SBen Langmuir Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive; 938ed84df00SBruno Cardoso Lopes Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes; 9392b63d15fSRichard Smith Result->Directory = FrameworkDir; 940a686e1b0SDouglas Gregor 941322f633cSDouglas Gregor // umbrella header "umbrella-header-name" 9422b63d15fSRichard Smith // 9432b63d15fSRichard Smith // The "Headers/" component of the name is implied because this is 9442b63d15fSRichard Smith // a framework module. 9452b63d15fSRichard Smith setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h"); 946d8bd7537SDouglas Gregor 947d8bd7537SDouglas Gregor // export * 948d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 949d8bd7537SDouglas Gregor 950a89c5ac4SDouglas Gregor // module * { export * } 951a89c5ac4SDouglas Gregor Result->InferSubmodules = true; 952a89c5ac4SDouglas Gregor Result->InferExportWildcard = true; 953a89c5ac4SDouglas Gregor 954e89dbc1dSDouglas Gregor // Look for subframeworks. 955c080917eSRafael Espindola std::error_code EC; 9562c1dd271SDylan Noblesmith SmallString<128> SubframeworksDirName 957ddaa69cbSDouglas Gregor = StringRef(FrameworkDir->getName()); 958e89dbc1dSDouglas Gregor llvm::sys::path::append(SubframeworksDirName, "Frameworks"); 9592d4d8cb3SBenjamin Kramer llvm::sys::path::native(SubframeworksDirName); 960b171a59bSBruno Cardoso Lopes vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); 961b171a59bSBruno Cardoso Lopes for (vfs::directory_iterator Dir = FS.dir_begin(SubframeworksDirName, EC), 962b171a59bSBruno Cardoso Lopes DirEnd; 963e89dbc1dSDouglas Gregor Dir != DirEnd && !EC; Dir.increment(EC)) { 964b171a59bSBruno Cardoso Lopes if (!StringRef(Dir->getName()).endswith(".framework")) 965e89dbc1dSDouglas Gregor continue; 966f2161a70SDouglas Gregor 967b171a59bSBruno Cardoso Lopes if (const DirectoryEntry *SubframeworkDir = 968b171a59bSBruno Cardoso Lopes FileMgr.getDirectory(Dir->getName())) { 96907c22b78SDouglas Gregor // Note: as an egregious but useful hack, we use the real path here and 97007c22b78SDouglas Gregor // check whether it is actually a subdirectory of the parent directory. 97107c22b78SDouglas Gregor // This will not be the case if the 'subframework' is actually a symlink 97207c22b78SDouglas Gregor // out to a top-level framework. 973e00c8b20SDouglas Gregor StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir); 97407c22b78SDouglas Gregor bool FoundParent = false; 97507c22b78SDouglas Gregor do { 97607c22b78SDouglas Gregor // Get the parent directory name. 97707c22b78SDouglas Gregor SubframeworkDirName 97807c22b78SDouglas Gregor = llvm::sys::path::parent_path(SubframeworkDirName); 97907c22b78SDouglas Gregor if (SubframeworkDirName.empty()) 98007c22b78SDouglas Gregor break; 98107c22b78SDouglas Gregor 98207c22b78SDouglas Gregor if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) { 98307c22b78SDouglas Gregor FoundParent = true; 98407c22b78SDouglas Gregor break; 98507c22b78SDouglas Gregor } 98607c22b78SDouglas Gregor } while (true); 98707c22b78SDouglas Gregor 98807c22b78SDouglas Gregor if (!FoundParent) 98907c22b78SDouglas Gregor continue; 99007c22b78SDouglas Gregor 991e89dbc1dSDouglas Gregor // FIXME: Do we want to warn about subframeworks without umbrella headers? 992a525400dSBen Langmuir inferFrameworkModule(SubframeworkDir, Attrs, Result); 993e89dbc1dSDouglas Gregor } 994e89dbc1dSDouglas Gregor } 995e89dbc1dSDouglas Gregor 99611dfe6feSDouglas Gregor // If the module is a top-level framework, automatically link against the 99711dfe6feSDouglas Gregor // framework. 99811dfe6feSDouglas Gregor if (!Result->isSubFramework()) { 99911dfe6feSDouglas Gregor inferFrameworkLink(Result, FrameworkDir, FileMgr); 100011dfe6feSDouglas Gregor } 100111dfe6feSDouglas Gregor 100256c64013SDouglas Gregor return Result; 100356c64013SDouglas Gregor } 100456c64013SDouglas Gregor 1005*8587dfd9SBruno Cardoso Lopes Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework, 1006*8587dfd9SBruno Cardoso Lopes Module *ShadowingModule) { 1007*8587dfd9SBruno Cardoso Lopes 1008*8587dfd9SBruno Cardoso Lopes // Create a new module with this name. 1009*8587dfd9SBruno Cardoso Lopes Module *Result = 1010*8587dfd9SBruno Cardoso Lopes new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework, 1011*8587dfd9SBruno Cardoso Lopes /*IsExplicit=*/false, NumCreatedModules++); 1012*8587dfd9SBruno Cardoso Lopes Result->ShadowingModule = ShadowingModule; 1013*8587dfd9SBruno Cardoso Lopes Result->IsAvailable = false; 1014*8587dfd9SBruno Cardoso Lopes ShadowModules.push_back(Result); 1015*8587dfd9SBruno Cardoso Lopes 1016*8587dfd9SBruno Cardoso Lopes return Result; 1017*8587dfd9SBruno Cardoso Lopes } 1018*8587dfd9SBruno Cardoso Lopes 10192b63d15fSRichard Smith void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader, 10202b63d15fSRichard Smith Twine NameAsWritten) { 102197da9178SDaniel Jasper Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader)); 102273141fa9SDouglas Gregor Mod->Umbrella = UmbrellaHeader; 10232b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 10247033127bSDouglas Gregor UmbrellaDirs[UmbrellaHeader->getDir()] = Mod; 1025b3a0fa48SBruno Cardoso Lopes 1026b3a0fa48SBruno Cardoso Lopes // Notify callbacks that we just added a new header. 1027b3a0fa48SBruno Cardoso Lopes for (const auto &Cb : Callbacks) 1028b3a0fa48SBruno Cardoso Lopes Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader); 1029a89c5ac4SDouglas Gregor } 1030a89c5ac4SDouglas Gregor 10312b63d15fSRichard Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, 10322b63d15fSRichard Smith Twine NameAsWritten) { 1033524e33e1SDouglas Gregor Mod->Umbrella = UmbrellaDir; 10342b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 1035524e33e1SDouglas Gregor UmbrellaDirs[UmbrellaDir] = Mod; 1036524e33e1SDouglas Gregor } 1037524e33e1SDouglas Gregor 1038040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod, 1039040e1266SRichard Smith Module::UnresolvedHeaderDirective Header) { 1040040e1266SRichard Smith // If there is a builtin counterpart to this file, add it now so it can 1041040e1266SRichard Smith // wrap the system header. 1042040e1266SRichard Smith if (resolveAsBuiltinHeader(Mod, Header)) { 1043040e1266SRichard Smith // If we have both a builtin and system version of the file, the 1044040e1266SRichard Smith // builtin version may want to inject macros into the system header, so 1045040e1266SRichard Smith // force the system header to be treated as a textual header in this 1046040e1266SRichard Smith // case. 1047040e1266SRichard Smith Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole( 1048040e1266SRichard Smith headerKindToRole(Header.Kind) | ModuleMap::TextualHeader)); 1049040e1266SRichard Smith Header.HasBuiltinHeader = true; 10503c1a41adSRichard Smith } 1051040e1266SRichard Smith 1052040e1266SRichard Smith // If possible, don't stat the header until we need to. This requires the 1053040e1266SRichard Smith // user to have provided us with some stat information about the file. 1054040e1266SRichard Smith // FIXME: Add support for lazily stat'ing umbrella headers and excluded 1055040e1266SRichard Smith // headers. 1056040e1266SRichard Smith if ((Header.Size || Header.ModTime) && !Header.IsUmbrella && 1057040e1266SRichard Smith Header.Kind != Module::HK_Excluded) { 1058040e1266SRichard Smith // We expect more variation in mtime than size, so if we're given both, 1059040e1266SRichard Smith // use the mtime as the key. 1060040e1266SRichard Smith if (Header.ModTime) 1061040e1266SRichard Smith LazyHeadersByModTime[*Header.ModTime].push_back(Mod); 1062040e1266SRichard Smith else 1063040e1266SRichard Smith LazyHeadersBySize[*Header.Size].push_back(Mod); 1064040e1266SRichard Smith Mod->UnresolvedHeaders.push_back(Header); 1065040e1266SRichard Smith return; 1066040e1266SRichard Smith } 1067040e1266SRichard Smith 1068040e1266SRichard Smith // We don't have stat information or can't defer looking this file up. 1069040e1266SRichard Smith // Perform the lookup now. 1070040e1266SRichard Smith resolveHeader(Mod, Header); 1071040e1266SRichard Smith } 1072040e1266SRichard Smith 1073040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const { 1074040e1266SRichard Smith auto BySize = LazyHeadersBySize.find(File->getSize()); 1075040e1266SRichard Smith if (BySize != LazyHeadersBySize.end()) { 1076040e1266SRichard Smith for (auto *M : BySize->second) 1077040e1266SRichard Smith resolveHeaderDirectives(M); 1078040e1266SRichard Smith LazyHeadersBySize.erase(BySize); 1079040e1266SRichard Smith } 1080040e1266SRichard Smith 1081040e1266SRichard Smith auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime()); 1082040e1266SRichard Smith if (ByModTime != LazyHeadersByModTime.end()) { 1083040e1266SRichard Smith for (auto *M : ByModTime->second) 1084040e1266SRichard Smith resolveHeaderDirectives(M); 1085040e1266SRichard Smith LazyHeadersByModTime.erase(ByModTime); 1086040e1266SRichard Smith } 1087040e1266SRichard Smith } 1088040e1266SRichard Smith 1089040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(Module *Mod) const { 1090040e1266SRichard Smith for (auto &Header : Mod->UnresolvedHeaders) 1091040e1266SRichard Smith // This operation is logically const; we're just changing how we represent 1092040e1266SRichard Smith // the header information for this file. 1093040e1266SRichard Smith const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header); 1094040e1266SRichard Smith Mod->UnresolvedHeaders.clear(); 10950e98d938SNAKAMURA Takumi } 1096202210b3SRichard Smith 10973c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header, 1098d8879c85SRichard Smith ModuleHeaderRole Role, bool Imported) { 1099386bb073SRichard Smith KnownHeader KH(Mod, Role); 11003c1a41adSRichard Smith 1101386bb073SRichard Smith // Only add each header to the headers list once. 1102386bb073SRichard Smith // FIXME: Should we diagnose if a header is listed twice in the 1103386bb073SRichard Smith // same module definition? 1104386bb073SRichard Smith auto &HeaderList = Headers[Header.Entry]; 1105386bb073SRichard Smith for (auto H : HeaderList) 1106386bb073SRichard Smith if (H == KH) 1107386bb073SRichard Smith return; 1108386bb073SRichard Smith 1109386bb073SRichard Smith HeaderList.push_back(KH); 11101ec383c7SPiotr Padlewski Mod->Headers[headerRoleToKind(Role)].push_back(Header); 1111386bb073SRichard Smith 11127e82e019SRichard Smith bool isCompilingModuleHeader = 1113bbcc9f04SRichard Smith LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule; 1114d8879c85SRichard Smith if (!Imported || isCompilingModuleHeader) { 1115d8879c85SRichard Smith // When we import HeaderFileInfo, the external source is expected to 1116d8879c85SRichard Smith // set the isModuleHeader flag itself. 1117d8879c85SRichard Smith HeaderInfo.MarkFileModuleHeader(Header.Entry, Role, 1118d8879c85SRichard Smith isCompilingModuleHeader); 1119d8879c85SRichard Smith } 1120e62cfd7cSBruno Cardoso Lopes 1121e62cfd7cSBruno Cardoso Lopes // Notify callbacks that we just added a new header. 1122e62cfd7cSBruno Cardoso Lopes for (const auto &Cb : Callbacks) 1123f0841790SBruno Cardoso Lopes Cb->moduleMapAddHeader(Header.Entry->getName()); 1124a89c5ac4SDouglas Gregor } 1125a89c5ac4SDouglas Gregor 11263c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) { 1127feb54b6dSRichard Smith // Add this as a known header so we won't implicitly add it to any 1128feb54b6dSRichard Smith // umbrella directory module. 1129feb54b6dSRichard Smith // FIXME: Should we only exclude it from umbrella modules within the 1130feb54b6dSRichard Smith // specified module? 11313c1a41adSRichard Smith (void) Headers[Header.Entry]; 11323c1a41adSRichard Smith 11333c1a41adSRichard Smith Mod->Headers[Module::HK_Excluded].push_back(std::move(Header)); 1134feb54b6dSRichard Smith } 1135feb54b6dSRichard Smith 1136*8587dfd9SBruno Cardoso Lopes void ModuleMap::setExplicitlyProvided(Module *Mod) { 1137*8587dfd9SBruno Cardoso Lopes assert(Modules[Mod->Name] == Mod && "explicitly provided module is shadowed"); 1138*8587dfd9SBruno Cardoso Lopes ExplicitlyProvidedModules.insert(Mod); 1139*8587dfd9SBruno Cardoso Lopes } 1140*8587dfd9SBruno Cardoso Lopes 1141514b636aSDouglas Gregor const FileEntry * 11424b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const { 11431f76c4e8SManuel Klimek if (Module->DefinitionLoc.isInvalid()) 1144d2d442caSCraig Topper return nullptr; 1145514b636aSDouglas Gregor 11461f76c4e8SManuel Klimek return SourceMgr.getFileEntryForID( 11471f76c4e8SManuel Klimek SourceMgr.getFileID(Module->DefinitionLoc)); 1148514b636aSDouglas Gregor } 1149514b636aSDouglas Gregor 11504b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const { 11519d6448b1SBen Langmuir if (M->IsInferred) { 11529d6448b1SBen Langmuir assert(InferredModuleAllowedBy.count(M) && "missing inferred module map"); 11539d6448b1SBen Langmuir return InferredModuleAllowedBy.find(M)->second; 11549d6448b1SBen Langmuir } 11559d6448b1SBen Langmuir return getContainingModuleMapFile(M); 11569d6448b1SBen Langmuir } 11579d6448b1SBen Langmuir 11589d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) { 11599d6448b1SBen Langmuir assert(M->IsInferred && "module not inferred"); 11609d6448b1SBen Langmuir InferredModuleAllowedBy[M] = ModMap; 11619d6448b1SBen Langmuir } 11629d6448b1SBen Langmuir 1163cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() { 1164718292f2SDouglas Gregor llvm::errs() << "Modules:"; 1165718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 1166718292f2SDouglas Gregor MEnd = Modules.end(); 1167718292f2SDouglas Gregor M != MEnd; ++M) 1168d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 1169718292f2SDouglas Gregor 1170718292f2SDouglas Gregor llvm::errs() << "Headers:"; 117159527666SDouglas Gregor for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end(); 1172718292f2SDouglas Gregor H != HEnd; ++H) { 117397da9178SDaniel Jasper llvm::errs() << " \"" << H->first->getName() << "\" -> "; 117497da9178SDaniel Jasper for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(), 117597da9178SDaniel Jasper E = H->second.end(); 117697da9178SDaniel Jasper I != E; ++I) { 117797da9178SDaniel Jasper if (I != H->second.begin()) 117897da9178SDaniel Jasper llvm::errs() << ","; 117997da9178SDaniel Jasper llvm::errs() << I->getModule()->getFullModuleName(); 118097da9178SDaniel Jasper } 118197da9178SDaniel Jasper llvm::errs() << "\n"; 1182718292f2SDouglas Gregor } 1183718292f2SDouglas Gregor } 1184718292f2SDouglas Gregor 11852b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) { 118642413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedExports); 118742413141SRichard Smith Mod->UnresolvedExports.clear(); 118842413141SRichard Smith for (auto &UE : Unresolved) { 118942413141SRichard Smith Module::ExportDecl Export = resolveExport(Mod, UE, Complain); 1190f5eedd05SDouglas Gregor if (Export.getPointer() || Export.getInt()) 11912b82c2a5SDouglas Gregor Mod->Exports.push_back(Export); 11922b82c2a5SDouglas Gregor else 119342413141SRichard Smith Mod->UnresolvedExports.push_back(UE); 11942b82c2a5SDouglas Gregor } 119542413141SRichard Smith return !Mod->UnresolvedExports.empty(); 11962b82c2a5SDouglas Gregor } 11972b82c2a5SDouglas Gregor 1198ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) { 119942413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedDirectUses); 120042413141SRichard Smith Mod->UnresolvedDirectUses.clear(); 120142413141SRichard Smith for (auto &UDU : Unresolved) { 120242413141SRichard Smith Module *DirectUse = resolveModuleId(UDU, Mod, Complain); 1203ba7f2f71SDaniel Jasper if (DirectUse) 1204ba7f2f71SDaniel Jasper Mod->DirectUses.push_back(DirectUse); 1205ba7f2f71SDaniel Jasper else 120642413141SRichard Smith Mod->UnresolvedDirectUses.push_back(UDU); 1207ba7f2f71SDaniel Jasper } 120842413141SRichard Smith return !Mod->UnresolvedDirectUses.empty(); 1209ba7f2f71SDaniel Jasper } 1210ba7f2f71SDaniel Jasper 1211fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) { 121242413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedConflicts); 121342413141SRichard Smith Mod->UnresolvedConflicts.clear(); 121442413141SRichard Smith for (auto &UC : Unresolved) { 121542413141SRichard Smith if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) { 1216fb912657SDouglas Gregor Module::Conflict Conflict; 1217fb912657SDouglas Gregor Conflict.Other = OtherMod; 121842413141SRichard Smith Conflict.Message = UC.Message; 1219fb912657SDouglas Gregor Mod->Conflicts.push_back(Conflict); 122042413141SRichard Smith } else 122142413141SRichard Smith Mod->UnresolvedConflicts.push_back(UC); 1222fb912657SDouglas Gregor } 122342413141SRichard Smith return !Mod->UnresolvedConflicts.empty(); 1224fb912657SDouglas Gregor } 1225fb912657SDouglas Gregor 1226718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1227718292f2SDouglas Gregor // Module map file parser 1228718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1229718292f2SDouglas Gregor 1230718292f2SDouglas Gregor namespace clang { 1231afd1b1c9SEugene Zelenko 1232718292f2SDouglas Gregor /// \brief A token in a module map file. 1233718292f2SDouglas Gregor struct MMToken { 1234718292f2SDouglas Gregor enum TokenKind { 12351fb5c3a6SDouglas Gregor Comma, 123635b13eceSDouglas Gregor ConfigMacros, 1237fb912657SDouglas Gregor Conflict, 1238718292f2SDouglas Gregor EndOfFile, 1239718292f2SDouglas Gregor HeaderKeyword, 1240718292f2SDouglas Gregor Identifier, 1241a3feee2aSRichard Smith Exclaim, 124259527666SDouglas Gregor ExcludeKeyword, 1243718292f2SDouglas Gregor ExplicitKeyword, 12442b82c2a5SDouglas Gregor ExportKeyword, 1245f0b11de2SDouglas Gregor ExportAsKeyword, 124697292843SDaniel Jasper ExternKeyword, 1247755b2055SDouglas Gregor FrameworkKeyword, 12486ddfca91SDouglas Gregor LinkKeyword, 1249718292f2SDouglas Gregor ModuleKeyword, 12502b82c2a5SDouglas Gregor Period, 1251b53e5483SLawrence Crowl PrivateKeyword, 1252718292f2SDouglas Gregor UmbrellaKeyword, 1253ba7f2f71SDaniel Jasper UseKeyword, 12541fb5c3a6SDouglas Gregor RequiresKeyword, 12552b82c2a5SDouglas Gregor Star, 1256718292f2SDouglas Gregor StringLiteral, 1257040e1266SRichard Smith IntegerLiteral, 1258306d8920SRichard Smith TextualKeyword, 1259718292f2SDouglas Gregor LBrace, 1260a686e1b0SDouglas Gregor RBrace, 1261a686e1b0SDouglas Gregor LSquare, 1262a686e1b0SDouglas Gregor RSquare 1263718292f2SDouglas Gregor } Kind; 1264718292f2SDouglas Gregor 1265718292f2SDouglas Gregor unsigned Location; 1266718292f2SDouglas Gregor unsigned StringLength; 1267040e1266SRichard Smith union { 1268040e1266SRichard Smith // If Kind != IntegerLiteral. 1269718292f2SDouglas Gregor const char *StringData; 1270afd1b1c9SEugene Zelenko 1271040e1266SRichard Smith // If Kind == IntegerLiteral. 1272040e1266SRichard Smith uint64_t IntegerValue; 1273040e1266SRichard Smith }; 1274718292f2SDouglas Gregor 1275718292f2SDouglas Gregor void clear() { 1276718292f2SDouglas Gregor Kind = EndOfFile; 1277718292f2SDouglas Gregor Location = 0; 1278718292f2SDouglas Gregor StringLength = 0; 1279d2d442caSCraig Topper StringData = nullptr; 1280718292f2SDouglas Gregor } 1281718292f2SDouglas Gregor 1282718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 1283718292f2SDouglas Gregor 1284718292f2SDouglas Gregor SourceLocation getLocation() const { 1285718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 1286718292f2SDouglas Gregor } 1287718292f2SDouglas Gregor 1288040e1266SRichard Smith uint64_t getInteger() const { 1289040e1266SRichard Smith return Kind == IntegerLiteral ? IntegerValue : 0; 1290040e1266SRichard Smith } 1291040e1266SRichard Smith 1292718292f2SDouglas Gregor StringRef getString() const { 1293040e1266SRichard Smith return Kind == IntegerLiteral ? StringRef() 1294040e1266SRichard Smith : StringRef(StringData, StringLength); 1295718292f2SDouglas Gregor } 1296718292f2SDouglas Gregor }; 1297718292f2SDouglas Gregor 1298718292f2SDouglas Gregor class ModuleMapParser { 1299718292f2SDouglas Gregor Lexer &L; 1300718292f2SDouglas Gregor SourceManager &SourceMgr; 1301bc10b9fbSDouglas Gregor 1302bc10b9fbSDouglas Gregor /// \brief Default target information, used only for string literal 1303bc10b9fbSDouglas Gregor /// parsing. 1304bc10b9fbSDouglas Gregor const TargetInfo *Target; 1305bc10b9fbSDouglas Gregor 1306718292f2SDouglas Gregor DiagnosticsEngine &Diags; 1307718292f2SDouglas Gregor ModuleMap ⤅ 1308718292f2SDouglas Gregor 1309beee15e7SBen Langmuir /// \brief The current module map file. 1310beee15e7SBen Langmuir const FileEntry *ModuleMapFile; 1311beee15e7SBen Langmuir 13129acb99e3SRichard Smith /// \brief The directory that file names in this module map file should 13139acb99e3SRichard Smith /// be resolved relative to. 13145257fc63SDouglas Gregor const DirectoryEntry *Directory; 13155257fc63SDouglas Gregor 1316963c5535SDouglas Gregor /// \brief Whether this module map is in a system header directory. 1317963c5535SDouglas Gregor bool IsSystem; 1318963c5535SDouglas Gregor 1319718292f2SDouglas Gregor /// \brief Whether an error occurred. 1320afd1b1c9SEugene Zelenko bool HadError = false; 1321718292f2SDouglas Gregor 1322718292f2SDouglas Gregor /// \brief Stores string data for the various string literals referenced 1323718292f2SDouglas Gregor /// during parsing. 1324718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 1325718292f2SDouglas Gregor 1326718292f2SDouglas Gregor /// \brief The current token. 1327718292f2SDouglas Gregor MMToken Tok; 1328718292f2SDouglas Gregor 1329718292f2SDouglas Gregor /// \brief The active module. 1330afd1b1c9SEugene Zelenko Module *ActiveModule = nullptr; 1331718292f2SDouglas Gregor 13327ff29148SBen Langmuir /// \brief Whether a module uses the 'requires excluded' hack to mark its 13337ff29148SBen Langmuir /// contents as 'textual'. 13347ff29148SBen Langmuir /// 13357ff29148SBen Langmuir /// On older Darwin SDK versions, 'requires excluded' is used to mark the 13367ff29148SBen Langmuir /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as 13377ff29148SBen Langmuir /// non-modular headers. For backwards compatibility, we continue to 13387ff29148SBen Langmuir /// support this idiom for just these modules, and map the headers to 13397ff29148SBen Langmuir /// 'textual' to match the original intent. 13407ff29148SBen Langmuir llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack; 13417ff29148SBen Langmuir 1342718292f2SDouglas Gregor /// \brief Consume the current token and return its location. 1343718292f2SDouglas Gregor SourceLocation consumeToken(); 1344718292f2SDouglas Gregor 1345*8587dfd9SBruno Cardoso Lopes bool UsesExplicitModuleMapFile = false; 1346*8587dfd9SBruno Cardoso Lopes 1347718292f2SDouglas Gregor /// \brief Skip tokens until we reach the a token with the given kind 1348718292f2SDouglas Gregor /// (or the end of the file). 1349718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 1350718292f2SDouglas Gregor 1351afd1b1c9SEugene Zelenko using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>; 1352afd1b1c9SEugene Zelenko 1353e7ab3669SDouglas Gregor bool parseModuleId(ModuleId &Id); 1354718292f2SDouglas Gregor void parseModuleDecl(); 135597292843SDaniel Jasper void parseExternModuleDecl(); 13561fb5c3a6SDouglas Gregor void parseRequiresDecl(); 1357afd1b1c9SEugene Zelenko void parseHeaderDecl(MMToken::TokenKind, SourceLocation LeadingLoc); 1358524e33e1SDouglas Gregor void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc); 13592b82c2a5SDouglas Gregor void parseExportDecl(); 1360f0b11de2SDouglas Gregor void parseExportAsDecl(); 1361ba7f2f71SDaniel Jasper void parseUseDecl(); 13626ddfca91SDouglas Gregor void parseLinkDecl(); 136335b13eceSDouglas Gregor void parseConfigMacros(); 1364fb912657SDouglas Gregor void parseConflict(); 13659194a91dSDouglas Gregor void parseInferredModuleDecl(bool Framework, bool Explicit); 1366c1d88ea5SBen Langmuir 1367afd1b1c9SEugene Zelenko using Attributes = ModuleMap::Attributes; 1368afd1b1c9SEugene Zelenko 13694442605fSBill Wendling bool parseOptionalAttributes(Attributes &Attrs); 1370718292f2SDouglas Gregor 1371718292f2SDouglas Gregor public: 1372718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 1373*8587dfd9SBruno Cardoso Lopes const TargetInfo *Target, DiagnosticsEngine &Diags, 1374*8587dfd9SBruno Cardoso Lopes ModuleMap &Map, const FileEntry *ModuleMapFile, 1375*8587dfd9SBruno Cardoso Lopes const DirectoryEntry *Directory, bool IsSystem, 1376*8587dfd9SBruno Cardoso Lopes bool UsesExplicitModuleMapFile) 1377bc10b9fbSDouglas Gregor : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map), 1378beee15e7SBen Langmuir ModuleMapFile(ModuleMapFile), Directory(Directory), 1379*8587dfd9SBruno Cardoso Lopes IsSystem(IsSystem), 1380*8587dfd9SBruno Cardoso Lopes UsesExplicitModuleMapFile(UsesExplicitModuleMapFile) { 1381718292f2SDouglas Gregor Tok.clear(); 1382718292f2SDouglas Gregor consumeToken(); 1383718292f2SDouglas Gregor } 1384718292f2SDouglas Gregor 1385718292f2SDouglas Gregor bool parseModuleMapFile(); 13868128f332SRichard Smith 13878128f332SRichard Smith bool terminatedByDirective() { return false; } 13888128f332SRichard Smith SourceLocation getLocation() { return Tok.getLocation(); } 1389718292f2SDouglas Gregor }; 1390afd1b1c9SEugene Zelenko 1391afd1b1c9SEugene Zelenko } // namespace clang 1392718292f2SDouglas Gregor 1393718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 1394718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 1395718292f2SDouglas Gregor 13968128f332SRichard Smith retry: 13978128f332SRichard Smith Tok.clear(); 1398718292f2SDouglas Gregor Token LToken; 1399718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 1400718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 1401718292f2SDouglas Gregor switch (LToken.getKind()) { 14022d57cea2SAlp Toker case tok::raw_identifier: { 14032d57cea2SAlp Toker StringRef RI = LToken.getRawIdentifier(); 14042d57cea2SAlp Toker Tok.StringData = RI.data(); 14052d57cea2SAlp Toker Tok.StringLength = RI.size(); 14062d57cea2SAlp Toker Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI) 140735b13eceSDouglas Gregor .Case("config_macros", MMToken::ConfigMacros) 1408fb912657SDouglas Gregor .Case("conflict", MMToken::Conflict) 140959527666SDouglas Gregor .Case("exclude", MMToken::ExcludeKeyword) 1410718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 14112b82c2a5SDouglas Gregor .Case("export", MMToken::ExportKeyword) 1412f0b11de2SDouglas Gregor .Case("export_as", MMToken::ExportAsKeyword) 141397292843SDaniel Jasper .Case("extern", MMToken::ExternKeyword) 1414755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 141535b13eceSDouglas Gregor .Case("header", MMToken::HeaderKeyword) 14166ddfca91SDouglas Gregor .Case("link", MMToken::LinkKeyword) 1417718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 1418b53e5483SLawrence Crowl .Case("private", MMToken::PrivateKeyword) 14191fb5c3a6SDouglas Gregor .Case("requires", MMToken::RequiresKeyword) 1420306d8920SRichard Smith .Case("textual", MMToken::TextualKeyword) 1421718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 1422ba7f2f71SDaniel Jasper .Case("use", MMToken::UseKeyword) 1423718292f2SDouglas Gregor .Default(MMToken::Identifier); 1424718292f2SDouglas Gregor break; 14252d57cea2SAlp Toker } 1426718292f2SDouglas Gregor 14271fb5c3a6SDouglas Gregor case tok::comma: 14281fb5c3a6SDouglas Gregor Tok.Kind = MMToken::Comma; 14291fb5c3a6SDouglas Gregor break; 14301fb5c3a6SDouglas Gregor 1431718292f2SDouglas Gregor case tok::eof: 1432718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 1433718292f2SDouglas Gregor break; 1434718292f2SDouglas Gregor 1435718292f2SDouglas Gregor case tok::l_brace: 1436718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 1437718292f2SDouglas Gregor break; 1438718292f2SDouglas Gregor 1439a686e1b0SDouglas Gregor case tok::l_square: 1440a686e1b0SDouglas Gregor Tok.Kind = MMToken::LSquare; 1441a686e1b0SDouglas Gregor break; 1442a686e1b0SDouglas Gregor 14432b82c2a5SDouglas Gregor case tok::period: 14442b82c2a5SDouglas Gregor Tok.Kind = MMToken::Period; 14452b82c2a5SDouglas Gregor break; 14462b82c2a5SDouglas Gregor 1447718292f2SDouglas Gregor case tok::r_brace: 1448718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 1449718292f2SDouglas Gregor break; 1450718292f2SDouglas Gregor 1451a686e1b0SDouglas Gregor case tok::r_square: 1452a686e1b0SDouglas Gregor Tok.Kind = MMToken::RSquare; 1453a686e1b0SDouglas Gregor break; 1454a686e1b0SDouglas Gregor 14552b82c2a5SDouglas Gregor case tok::star: 14562b82c2a5SDouglas Gregor Tok.Kind = MMToken::Star; 14572b82c2a5SDouglas Gregor break; 14582b82c2a5SDouglas Gregor 1459a3feee2aSRichard Smith case tok::exclaim: 1460a3feee2aSRichard Smith Tok.Kind = MMToken::Exclaim; 1461a3feee2aSRichard Smith break; 1462a3feee2aSRichard Smith 1463718292f2SDouglas Gregor case tok::string_literal: { 1464d67aea28SRichard Smith if (LToken.hasUDSuffix()) { 1465d67aea28SRichard Smith Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl); 1466d67aea28SRichard Smith HadError = true; 1467d67aea28SRichard Smith goto retry; 1468d67aea28SRichard Smith } 1469d67aea28SRichard Smith 1470718292f2SDouglas Gregor // Parse the string literal. 1471718292f2SDouglas Gregor LangOptions LangOpts; 14729d5583efSCraig Topper StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target); 1473718292f2SDouglas Gregor if (StringLiteral.hadError) 1474718292f2SDouglas Gregor goto retry; 1475718292f2SDouglas Gregor 1476718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 1477718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 1478718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 1479718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 1480718292f2SDouglas Gregor Saved[Length] = 0; 1481718292f2SDouglas Gregor 1482718292f2SDouglas Gregor // Form the token. 1483718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 1484718292f2SDouglas Gregor Tok.StringData = Saved; 1485718292f2SDouglas Gregor Tok.StringLength = Length; 1486718292f2SDouglas Gregor break; 1487718292f2SDouglas Gregor } 1488718292f2SDouglas Gregor 1489040e1266SRichard Smith case tok::numeric_constant: { 1490040e1266SRichard Smith // We don't support any suffixes or other complications. 1491040e1266SRichard Smith SmallString<32> SpellingBuffer; 1492040e1266SRichard Smith SpellingBuffer.resize(LToken.getLength() + 1); 1493040e1266SRichard Smith const char *Start = SpellingBuffer.data(); 1494040e1266SRichard Smith unsigned Length = 1495040e1266SRichard Smith Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts()); 1496040e1266SRichard Smith uint64_t Value; 1497040e1266SRichard Smith if (StringRef(Start, Length).getAsInteger(0, Value)) { 1498040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1499040e1266SRichard Smith HadError = true; 1500040e1266SRichard Smith goto retry; 1501040e1266SRichard Smith } 1502040e1266SRichard Smith 1503040e1266SRichard Smith Tok.Kind = MMToken::IntegerLiteral; 1504040e1266SRichard Smith Tok.IntegerValue = Value; 1505040e1266SRichard Smith break; 1506040e1266SRichard Smith } 1507040e1266SRichard Smith 1508718292f2SDouglas Gregor case tok::comment: 1509718292f2SDouglas Gregor goto retry; 1510718292f2SDouglas Gregor 15118128f332SRichard Smith case tok::hash: 15128128f332SRichard Smith // A module map can be terminated prematurely by 15138128f332SRichard Smith // #pragma clang module contents 15148128f332SRichard Smith // When building the module, we'll treat the rest of the file as the 15158128f332SRichard Smith // contents of the module. 15168128f332SRichard Smith { 15178128f332SRichard Smith auto NextIsIdent = [&](StringRef Str) -> bool { 15188128f332SRichard Smith L.LexFromRawLexer(LToken); 15198128f332SRichard Smith return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) && 15208128f332SRichard Smith LToken.getRawIdentifier() == Str; 15218128f332SRichard Smith }; 15228128f332SRichard Smith if (NextIsIdent("pragma") && NextIsIdent("clang") && 15238128f332SRichard Smith NextIsIdent("module") && NextIsIdent("contents")) { 15248128f332SRichard Smith Tok.Kind = MMToken::EndOfFile; 15258128f332SRichard Smith break; 15268128f332SRichard Smith } 15278128f332SRichard Smith } 15288128f332SRichard Smith LLVM_FALLTHROUGH; 15298128f332SRichard Smith 1530718292f2SDouglas Gregor default: 15318128f332SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1532718292f2SDouglas Gregor HadError = true; 1533718292f2SDouglas Gregor goto retry; 1534718292f2SDouglas Gregor } 1535718292f2SDouglas Gregor 1536718292f2SDouglas Gregor return Result; 1537718292f2SDouglas Gregor } 1538718292f2SDouglas Gregor 1539718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 1540718292f2SDouglas Gregor unsigned braceDepth = 0; 1541a686e1b0SDouglas Gregor unsigned squareDepth = 0; 1542718292f2SDouglas Gregor do { 1543718292f2SDouglas Gregor switch (Tok.Kind) { 1544718292f2SDouglas Gregor case MMToken::EndOfFile: 1545718292f2SDouglas Gregor return; 1546718292f2SDouglas Gregor 1547718292f2SDouglas Gregor case MMToken::LBrace: 1548a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1549718292f2SDouglas Gregor return; 1550718292f2SDouglas Gregor 1551718292f2SDouglas Gregor ++braceDepth; 1552718292f2SDouglas Gregor break; 1553718292f2SDouglas Gregor 1554a686e1b0SDouglas Gregor case MMToken::LSquare: 1555a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1556a686e1b0SDouglas Gregor return; 1557a686e1b0SDouglas Gregor 1558a686e1b0SDouglas Gregor ++squareDepth; 1559a686e1b0SDouglas Gregor break; 1560a686e1b0SDouglas Gregor 1561718292f2SDouglas Gregor case MMToken::RBrace: 1562718292f2SDouglas Gregor if (braceDepth > 0) 1563718292f2SDouglas Gregor --braceDepth; 1564718292f2SDouglas Gregor else if (Tok.is(K)) 1565718292f2SDouglas Gregor return; 1566718292f2SDouglas Gregor break; 1567718292f2SDouglas Gregor 1568a686e1b0SDouglas Gregor case MMToken::RSquare: 1569a686e1b0SDouglas Gregor if (squareDepth > 0) 1570a686e1b0SDouglas Gregor --squareDepth; 1571a686e1b0SDouglas Gregor else if (Tok.is(K)) 1572a686e1b0SDouglas Gregor return; 1573a686e1b0SDouglas Gregor break; 1574a686e1b0SDouglas Gregor 1575718292f2SDouglas Gregor default: 1576a686e1b0SDouglas Gregor if (braceDepth == 0 && squareDepth == 0 && Tok.is(K)) 1577718292f2SDouglas Gregor return; 1578718292f2SDouglas Gregor break; 1579718292f2SDouglas Gregor } 1580718292f2SDouglas Gregor 1581718292f2SDouglas Gregor consumeToken(); 1582718292f2SDouglas Gregor } while (true); 1583718292f2SDouglas Gregor } 1584718292f2SDouglas Gregor 1585e7ab3669SDouglas Gregor /// \brief Parse a module-id. 1586e7ab3669SDouglas Gregor /// 1587e7ab3669SDouglas Gregor /// module-id: 1588e7ab3669SDouglas Gregor /// identifier 1589e7ab3669SDouglas Gregor /// identifier '.' module-id 1590e7ab3669SDouglas Gregor /// 1591e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise. 1592e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) { 1593e7ab3669SDouglas Gregor Id.clear(); 1594e7ab3669SDouglas Gregor do { 15953cd34c76SDaniel Jasper if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) { 1596e7ab3669SDouglas Gregor Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation())); 1597e7ab3669SDouglas Gregor consumeToken(); 1598e7ab3669SDouglas Gregor } else { 1599e7ab3669SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 1600e7ab3669SDouglas Gregor return true; 1601e7ab3669SDouglas Gregor } 1602e7ab3669SDouglas Gregor 1603e7ab3669SDouglas Gregor if (!Tok.is(MMToken::Period)) 1604e7ab3669SDouglas Gregor break; 1605e7ab3669SDouglas Gregor 1606e7ab3669SDouglas Gregor consumeToken(); 1607e7ab3669SDouglas Gregor } while (true); 1608e7ab3669SDouglas Gregor 1609e7ab3669SDouglas Gregor return false; 1610e7ab3669SDouglas Gregor } 1611e7ab3669SDouglas Gregor 1612a686e1b0SDouglas Gregor namespace { 1613afd1b1c9SEugene Zelenko 1614a686e1b0SDouglas Gregor /// \brief Enumerates the known attributes. 1615a686e1b0SDouglas Gregor enum AttributeKind { 1616a686e1b0SDouglas Gregor /// \brief An unknown attribute. 1617a686e1b0SDouglas Gregor AT_unknown, 1618afd1b1c9SEugene Zelenko 1619a686e1b0SDouglas Gregor /// \brief The 'system' attribute. 162035b13eceSDouglas Gregor AT_system, 1621afd1b1c9SEugene Zelenko 162277944868SRichard Smith /// \brief The 'extern_c' attribute. 162377944868SRichard Smith AT_extern_c, 1624afd1b1c9SEugene Zelenko 162535b13eceSDouglas Gregor /// \brief The 'exhaustive' attribute. 1626ed84df00SBruno Cardoso Lopes AT_exhaustive, 1627afd1b1c9SEugene Zelenko 1628ed84df00SBruno Cardoso Lopes /// \brief The 'no_undeclared_includes' attribute. 1629ed84df00SBruno Cardoso Lopes AT_no_undeclared_includes 1630a686e1b0SDouglas Gregor }; 1631afd1b1c9SEugene Zelenko 1632afd1b1c9SEugene Zelenko } // namespace 1633a686e1b0SDouglas Gregor 163429729919SBruno Cardoso Lopes /// Private modules are canonicalized as Foo_Private. Clang provides extra 163529729919SBruno Cardoso Lopes /// module map search logic to find the appropriate private module when PCH 163629729919SBruno Cardoso Lopes /// is used with implicit module maps. Warn when private modules are written 163729729919SBruno Cardoso Lopes /// in other ways (FooPrivate and Foo.Private), providing notes and fixits. 163829729919SBruno Cardoso Lopes static void diagnosePrivateModules(const ModuleMap &Map, 163929729919SBruno Cardoso Lopes DiagnosticsEngine &Diags, 164029729919SBruno Cardoso Lopes const Module *ActiveModule) { 164129729919SBruno Cardoso Lopes 164229729919SBruno Cardoso Lopes auto GenNoteAndFixIt = [&](StringRef BadName, StringRef Canonical, 164329729919SBruno Cardoso Lopes const Module *M) { 164429729919SBruno Cardoso Lopes auto D = Diags.Report(ActiveModule->DefinitionLoc, 164529729919SBruno Cardoso Lopes diag::note_mmap_rename_top_level_private_module); 164629729919SBruno Cardoso Lopes D << BadName << M->Name; 164729729919SBruno Cardoso Lopes D << FixItHint::CreateReplacement(ActiveModule->DefinitionLoc, Canonical); 164829729919SBruno Cardoso Lopes }; 164929729919SBruno Cardoso Lopes 165029729919SBruno Cardoso Lopes for (auto E = Map.module_begin(); E != Map.module_end(); ++E) { 165129729919SBruno Cardoso Lopes auto const *M = E->getValue(); 165229729919SBruno Cardoso Lopes if (M->Directory != ActiveModule->Directory) 165329729919SBruno Cardoso Lopes continue; 165429729919SBruno Cardoso Lopes 165529729919SBruno Cardoso Lopes SmallString<128> FullName(ActiveModule->getFullModuleName()); 165629729919SBruno Cardoso Lopes if (!FullName.startswith(M->Name) && !FullName.endswith("Private")) 165729729919SBruno Cardoso Lopes continue; 165829729919SBruno Cardoso Lopes SmallString<128> Canonical(M->Name); 165929729919SBruno Cardoso Lopes Canonical.append("_Private"); 166029729919SBruno Cardoso Lopes 166129729919SBruno Cardoso Lopes // Foo.Private -> Foo_Private 166229729919SBruno Cardoso Lopes if (ActiveModule->Parent && ActiveModule->Name == "Private" && !M->Parent && 166329729919SBruno Cardoso Lopes M->Name == ActiveModule->Parent->Name) { 166429729919SBruno Cardoso Lopes Diags.Report(ActiveModule->DefinitionLoc, 166529729919SBruno Cardoso Lopes diag::warn_mmap_mismatched_private_submodule) 166629729919SBruno Cardoso Lopes << FullName; 166729729919SBruno Cardoso Lopes GenNoteAndFixIt(FullName, Canonical, M); 166829729919SBruno Cardoso Lopes continue; 166929729919SBruno Cardoso Lopes } 167029729919SBruno Cardoso Lopes 167129729919SBruno Cardoso Lopes // FooPrivate and whatnots -> Foo_Private 167229729919SBruno Cardoso Lopes if (!ActiveModule->Parent && !M->Parent && M->Name != ActiveModule->Name && 167329729919SBruno Cardoso Lopes ActiveModule->Name != Canonical) { 167429729919SBruno Cardoso Lopes Diags.Report(ActiveModule->DefinitionLoc, 167529729919SBruno Cardoso Lopes diag::warn_mmap_mismatched_private_module_name) 167629729919SBruno Cardoso Lopes << ActiveModule->Name; 167729729919SBruno Cardoso Lopes GenNoteAndFixIt(ActiveModule->Name, Canonical, M); 167829729919SBruno Cardoso Lopes } 167929729919SBruno Cardoso Lopes } 168029729919SBruno Cardoso Lopes } 168129729919SBruno Cardoso Lopes 1682718292f2SDouglas Gregor /// \brief Parse a module declaration. 1683718292f2SDouglas Gregor /// 1684718292f2SDouglas Gregor /// module-declaration: 168597292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 1686a686e1b0SDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt] 1687a686e1b0SDouglas Gregor /// { module-member* } 1688a686e1b0SDouglas Gregor /// 1689718292f2SDouglas Gregor /// module-member: 16901fb5c3a6SDouglas Gregor /// requires-declaration 1691718292f2SDouglas Gregor /// header-declaration 1692e7ab3669SDouglas Gregor /// submodule-declaration 16932b82c2a5SDouglas Gregor /// export-declaration 1694f0b11de2SDouglas Gregor /// export-as-declaration 16956ddfca91SDouglas Gregor /// link-declaration 169673441091SDouglas Gregor /// 169773441091SDouglas Gregor /// submodule-declaration: 169873441091SDouglas Gregor /// module-declaration 169973441091SDouglas Gregor /// inferred-submodule-declaration 1700718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 1701755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 170297292843SDaniel Jasper Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword)); 170397292843SDaniel Jasper if (Tok.is(MMToken::ExternKeyword)) { 170497292843SDaniel Jasper parseExternModuleDecl(); 170597292843SDaniel Jasper return; 170697292843SDaniel Jasper } 170797292843SDaniel Jasper 1708f2161a70SDouglas Gregor // Parse 'explicit' or 'framework' keyword, if present. 1709e7ab3669SDouglas Gregor SourceLocation ExplicitLoc; 1710718292f2SDouglas Gregor bool Explicit = false; 1711f2161a70SDouglas Gregor bool Framework = false; 1712755b2055SDouglas Gregor 1713f2161a70SDouglas Gregor // Parse 'explicit' keyword, if present. 1714f2161a70SDouglas Gregor if (Tok.is(MMToken::ExplicitKeyword)) { 1715e7ab3669SDouglas Gregor ExplicitLoc = consumeToken(); 1716f2161a70SDouglas Gregor Explicit = true; 1717f2161a70SDouglas Gregor } 1718f2161a70SDouglas Gregor 1719f2161a70SDouglas Gregor // Parse 'framework' keyword, if present. 1720755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 1721755b2055SDouglas Gregor consumeToken(); 1722755b2055SDouglas Gregor Framework = true; 1723755b2055SDouglas Gregor } 1724718292f2SDouglas Gregor 1725718292f2SDouglas Gregor // Parse 'module' keyword. 1726718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 1727d6343c99SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 1728718292f2SDouglas Gregor consumeToken(); 1729718292f2SDouglas Gregor HadError = true; 1730718292f2SDouglas Gregor return; 1731718292f2SDouglas Gregor } 1732718292f2SDouglas Gregor consumeToken(); // 'module' keyword 1733718292f2SDouglas Gregor 173473441091SDouglas Gregor // If we have a wildcard for the module name, this is an inferred submodule. 173573441091SDouglas Gregor // Parse it. 173673441091SDouglas Gregor if (Tok.is(MMToken::Star)) 17379194a91dSDouglas Gregor return parseInferredModuleDecl(Framework, Explicit); 173873441091SDouglas Gregor 1739718292f2SDouglas Gregor // Parse the module name. 1740e7ab3669SDouglas Gregor ModuleId Id; 1741e7ab3669SDouglas Gregor if (parseModuleId(Id)) { 1742718292f2SDouglas Gregor HadError = true; 1743718292f2SDouglas Gregor return; 1744718292f2SDouglas Gregor } 1745e7ab3669SDouglas Gregor 1746e7ab3669SDouglas Gregor if (ActiveModule) { 1747e7ab3669SDouglas Gregor if (Id.size() > 1) { 1748e7ab3669SDouglas Gregor Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id) 1749e7ab3669SDouglas Gregor << SourceRange(Id.front().second, Id.back().second); 1750e7ab3669SDouglas Gregor 1751e7ab3669SDouglas Gregor HadError = true; 1752e7ab3669SDouglas Gregor return; 1753e7ab3669SDouglas Gregor } 1754e7ab3669SDouglas Gregor } else if (Id.size() == 1 && Explicit) { 1755e7ab3669SDouglas Gregor // Top-level modules can't be explicit. 1756e7ab3669SDouglas Gregor Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level); 1757e7ab3669SDouglas Gregor Explicit = false; 1758e7ab3669SDouglas Gregor ExplicitLoc = SourceLocation(); 1759e7ab3669SDouglas Gregor HadError = true; 1760e7ab3669SDouglas Gregor } 1761e7ab3669SDouglas Gregor 1762e7ab3669SDouglas Gregor Module *PreviousActiveModule = ActiveModule; 1763e7ab3669SDouglas Gregor if (Id.size() > 1) { 1764e7ab3669SDouglas Gregor // This module map defines a submodule. Go find the module of which it 1765e7ab3669SDouglas Gregor // is a submodule. 1766d2d442caSCraig Topper ActiveModule = nullptr; 17674b8a9e95SBen Langmuir const Module *TopLevelModule = nullptr; 1768e7ab3669SDouglas Gregor for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) { 1769e7ab3669SDouglas Gregor if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) { 17704b8a9e95SBen Langmuir if (I == 0) 17714b8a9e95SBen Langmuir TopLevelModule = Next; 1772e7ab3669SDouglas Gregor ActiveModule = Next; 1773e7ab3669SDouglas Gregor continue; 1774e7ab3669SDouglas Gregor } 1775e7ab3669SDouglas Gregor 1776e7ab3669SDouglas Gregor if (ActiveModule) { 1777e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified) 17785b5d21eaSRichard Smith << Id[I].first 17795b5d21eaSRichard Smith << ActiveModule->getTopLevelModule()->getFullModuleName(); 1780e7ab3669SDouglas Gregor } else { 1781e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_expected_module_name); 1782e7ab3669SDouglas Gregor } 1783e7ab3669SDouglas Gregor HadError = true; 1784e7ab3669SDouglas Gregor return; 1785e7ab3669SDouglas Gregor } 17864b8a9e95SBen Langmuir 17874b8a9e95SBen Langmuir if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) { 17884b8a9e95SBen Langmuir assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) && 17894b8a9e95SBen Langmuir "submodule defined in same file as 'module *' that allowed its " 17904b8a9e95SBen Langmuir "top-level module"); 17914b8a9e95SBen Langmuir Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile); 17924b8a9e95SBen Langmuir } 1793e7ab3669SDouglas Gregor } 1794e7ab3669SDouglas Gregor 1795e7ab3669SDouglas Gregor StringRef ModuleName = Id.back().first; 1796e7ab3669SDouglas Gregor SourceLocation ModuleNameLoc = Id.back().second; 1797718292f2SDouglas Gregor 1798a686e1b0SDouglas Gregor // Parse the optional attribute list. 17994442605fSBill Wendling Attributes Attrs; 18005d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 18015d29dee0SDavide Italiano return; 18025d29dee0SDavide Italiano 1803718292f2SDouglas Gregor // Parse the opening brace. 1804718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 1805718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 1806718292f2SDouglas Gregor << ModuleName; 1807718292f2SDouglas Gregor HadError = true; 1808718292f2SDouglas Gregor return; 1809718292f2SDouglas Gregor } 1810718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 1811718292f2SDouglas Gregor 1812718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 1813*8587dfd9SBruno Cardoso Lopes Module *ShadowingModule = nullptr; 1814eb90e830SDouglas Gregor if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { 18154a3751ffSRichard Smith // We might see a (re)definition of a module that we already have a 18164a3751ffSRichard Smith // definition for in two cases: 18174a3751ffSRichard Smith // - If we loaded one definition from an AST file and we've just found a 18184a3751ffSRichard Smith // corresponding definition in a module map file, or 18194a3751ffSRichard Smith bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid(); 18204a3751ffSRichard Smith // - If we're building a (preprocessed) module and we've just loaded the 18214a3751ffSRichard Smith // module map file from which it was created. 18224a3751ffSRichard Smith bool ParsedAsMainInput = 18234a3751ffSRichard Smith Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap && 18244a3751ffSRichard Smith Map.LangOpts.CurrentModule == ModuleName && 18254a3751ffSRichard Smith SourceMgr.getDecomposedLoc(ModuleNameLoc).first != 18264a3751ffSRichard Smith SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first; 18274a3751ffSRichard Smith if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) { 1828fcc54a3bSDouglas Gregor // Skip the module definition. 1829fcc54a3bSDouglas Gregor skipUntil(MMToken::RBrace); 1830fcc54a3bSDouglas Gregor if (Tok.is(MMToken::RBrace)) 1831fcc54a3bSDouglas Gregor consumeToken(); 1832fcc54a3bSDouglas Gregor else { 1833fcc54a3bSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 1834fcc54a3bSDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 1835fcc54a3bSDouglas Gregor HadError = true; 1836fcc54a3bSDouglas Gregor } 1837fcc54a3bSDouglas Gregor return; 1838fcc54a3bSDouglas Gregor } 1839fcc54a3bSDouglas Gregor 1840*8587dfd9SBruno Cardoso Lopes if (!Existing->Parent && 1841*8587dfd9SBruno Cardoso Lopes Map.mayShadowModuleBeingParsed(Existing, UsesExplicitModuleMapFile)) { 1842*8587dfd9SBruno Cardoso Lopes ShadowingModule = Existing; 1843*8587dfd9SBruno Cardoso Lopes } else { 1844*8587dfd9SBruno Cardoso Lopes // This is not a shawdowed module decl, it is an illegal redefinition. 1845718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 1846718292f2SDouglas Gregor << ModuleName; 1847eb90e830SDouglas Gregor Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition); 1848718292f2SDouglas Gregor 1849718292f2SDouglas Gregor // Skip the module definition. 1850718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 1851718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 1852718292f2SDouglas Gregor consumeToken(); 1853718292f2SDouglas Gregor 1854718292f2SDouglas Gregor HadError = true; 1855718292f2SDouglas Gregor return; 1856718292f2SDouglas Gregor } 1857*8587dfd9SBruno Cardoso Lopes } 1858718292f2SDouglas Gregor 1859718292f2SDouglas Gregor // Start defining this module. 1860*8587dfd9SBruno Cardoso Lopes if (ShadowingModule) { 1861*8587dfd9SBruno Cardoso Lopes ActiveModule = 1862*8587dfd9SBruno Cardoso Lopes Map.createShadowedModule(ModuleName, Framework, ShadowingModule); 1863*8587dfd9SBruno Cardoso Lopes } else { 18649d6448b1SBen Langmuir ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework, 1865*8587dfd9SBruno Cardoso Lopes Explicit, UsesExplicitModuleMapFile) 1866*8587dfd9SBruno Cardoso Lopes .first; 1867*8587dfd9SBruno Cardoso Lopes } 1868*8587dfd9SBruno Cardoso Lopes 1869eb90e830SDouglas Gregor ActiveModule->DefinitionLoc = ModuleNameLoc; 1870963c5535SDouglas Gregor if (Attrs.IsSystem || IsSystem) 1871a686e1b0SDouglas Gregor ActiveModule->IsSystem = true; 187277944868SRichard Smith if (Attrs.IsExternC) 187377944868SRichard Smith ActiveModule->IsExternC = true; 1874ed84df00SBruno Cardoso Lopes if (Attrs.NoUndeclaredIncludes || 1875ed84df00SBruno Cardoso Lopes (!ActiveModule->Parent && ModuleName == "Darwin")) 1876ed84df00SBruno Cardoso Lopes ActiveModule->NoUndeclaredIncludes = true; 18773c1a41adSRichard Smith ActiveModule->Directory = Directory; 1878718292f2SDouglas Gregor 187929729919SBruno Cardoso Lopes 188029729919SBruno Cardoso Lopes // Private modules named as FooPrivate, Foo.Private or similar are likely a 188129729919SBruno Cardoso Lopes // user error; provide warnings, notes and fixits to direct users to use 188229729919SBruno Cardoso Lopes // Foo_Private instead. 188329729919SBruno Cardoso Lopes SourceLocation StartLoc = 188429729919SBruno Cardoso Lopes SourceMgr.getLocForStartOfFile(SourceMgr.getMainFileID()); 18854d867640SGraydon Hoare StringRef MapFileName(ModuleMapFile->getName()); 188629729919SBruno Cardoso Lopes if (Map.HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && 188729729919SBruno Cardoso Lopes !Diags.isIgnored(diag::warn_mmap_mismatched_private_submodule, 188829729919SBruno Cardoso Lopes StartLoc) && 188929729919SBruno Cardoso Lopes !Diags.isIgnored(diag::warn_mmap_mismatched_private_module_name, 189029729919SBruno Cardoso Lopes StartLoc) && 189129729919SBruno Cardoso Lopes (MapFileName.endswith("module.private.modulemap") || 189229729919SBruno Cardoso Lopes MapFileName.endswith("module_private.map"))) 189329729919SBruno Cardoso Lopes diagnosePrivateModules(Map, Diags, ActiveModule); 18944d867640SGraydon Hoare 1895718292f2SDouglas Gregor bool Done = false; 1896718292f2SDouglas Gregor do { 1897718292f2SDouglas Gregor switch (Tok.Kind) { 1898718292f2SDouglas Gregor case MMToken::EndOfFile: 1899718292f2SDouglas Gregor case MMToken::RBrace: 1900718292f2SDouglas Gregor Done = true; 1901718292f2SDouglas Gregor break; 1902718292f2SDouglas Gregor 190335b13eceSDouglas Gregor case MMToken::ConfigMacros: 190435b13eceSDouglas Gregor parseConfigMacros(); 190535b13eceSDouglas Gregor break; 190635b13eceSDouglas Gregor 1907fb912657SDouglas Gregor case MMToken::Conflict: 1908fb912657SDouglas Gregor parseConflict(); 1909fb912657SDouglas Gregor break; 1910fb912657SDouglas Gregor 1911718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 191297292843SDaniel Jasper case MMToken::ExternKeyword: 1913f2161a70SDouglas Gregor case MMToken::FrameworkKeyword: 1914718292f2SDouglas Gregor case MMToken::ModuleKeyword: 1915718292f2SDouglas Gregor parseModuleDecl(); 1916718292f2SDouglas Gregor break; 1917718292f2SDouglas Gregor 19182b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 19192b82c2a5SDouglas Gregor parseExportDecl(); 19202b82c2a5SDouglas Gregor break; 19212b82c2a5SDouglas Gregor 1922f0b11de2SDouglas Gregor case MMToken::ExportAsKeyword: 1923f0b11de2SDouglas Gregor parseExportAsDecl(); 1924f0b11de2SDouglas Gregor break; 1925f0b11de2SDouglas Gregor 1926ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 1927ba7f2f71SDaniel Jasper parseUseDecl(); 1928ba7f2f71SDaniel Jasper break; 1929ba7f2f71SDaniel Jasper 19301fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 19311fb5c3a6SDouglas Gregor parseRequiresDecl(); 19321fb5c3a6SDouglas Gregor break; 19331fb5c3a6SDouglas Gregor 1934202210b3SRichard Smith case MMToken::TextualKeyword: 1935202210b3SRichard Smith parseHeaderDecl(MMToken::TextualKeyword, consumeToken()); 1936306d8920SRichard Smith break; 1937306d8920SRichard Smith 1938524e33e1SDouglas Gregor case MMToken::UmbrellaKeyword: { 1939524e33e1SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 1940524e33e1SDouglas Gregor if (Tok.is(MMToken::HeaderKeyword)) 1941b53e5483SLawrence Crowl parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc); 1942524e33e1SDouglas Gregor else 1943524e33e1SDouglas Gregor parseUmbrellaDirDecl(UmbrellaLoc); 1944718292f2SDouglas Gregor break; 1945524e33e1SDouglas Gregor } 1946718292f2SDouglas Gregor 1947202210b3SRichard Smith case MMToken::ExcludeKeyword: 1948202210b3SRichard Smith parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken()); 194959527666SDouglas Gregor break; 195059527666SDouglas Gregor 1951202210b3SRichard Smith case MMToken::PrivateKeyword: 1952202210b3SRichard Smith parseHeaderDecl(MMToken::PrivateKeyword, consumeToken()); 1953b53e5483SLawrence Crowl break; 1954b53e5483SLawrence Crowl 1955322f633cSDouglas Gregor case MMToken::HeaderKeyword: 1956202210b3SRichard Smith parseHeaderDecl(MMToken::HeaderKeyword, consumeToken()); 1957718292f2SDouglas Gregor break; 1958718292f2SDouglas Gregor 19596ddfca91SDouglas Gregor case MMToken::LinkKeyword: 19606ddfca91SDouglas Gregor parseLinkDecl(); 19616ddfca91SDouglas Gregor break; 19626ddfca91SDouglas Gregor 1963718292f2SDouglas Gregor default: 1964718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 1965718292f2SDouglas Gregor consumeToken(); 1966718292f2SDouglas Gregor break; 1967718292f2SDouglas Gregor } 1968718292f2SDouglas Gregor } while (!Done); 1969718292f2SDouglas Gregor 1970718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 1971718292f2SDouglas Gregor consumeToken(); 1972718292f2SDouglas Gregor else { 1973718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 1974718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 1975718292f2SDouglas Gregor HadError = true; 1976718292f2SDouglas Gregor } 1977718292f2SDouglas Gregor 197811dfe6feSDouglas Gregor // If the active module is a top-level framework, and there are no link 197911dfe6feSDouglas Gregor // libraries, automatically link against the framework. 198011dfe6feSDouglas Gregor if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() && 198111dfe6feSDouglas Gregor ActiveModule->LinkLibraries.empty()) { 198211dfe6feSDouglas Gregor inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager()); 198311dfe6feSDouglas Gregor } 198411dfe6feSDouglas Gregor 1985ec8c9752SBen Langmuir // If the module meets all requirements but is still unavailable, mark the 1986ec8c9752SBen Langmuir // whole tree as unavailable to prevent it from building. 1987ec8c9752SBen Langmuir if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement && 1988ec8c9752SBen Langmuir ActiveModule->Parent) { 1989ec8c9752SBen Langmuir ActiveModule->getTopLevelModule()->markUnavailable(); 1990ec8c9752SBen Langmuir ActiveModule->getTopLevelModule()->MissingHeaders.append( 1991ec8c9752SBen Langmuir ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end()); 1992ec8c9752SBen Langmuir } 1993ec8c9752SBen Langmuir 1994e7ab3669SDouglas Gregor // We're done parsing this module. Pop back to the previous module. 1995e7ab3669SDouglas Gregor ActiveModule = PreviousActiveModule; 1996718292f2SDouglas Gregor } 1997718292f2SDouglas Gregor 199897292843SDaniel Jasper /// \brief Parse an extern module declaration. 199997292843SDaniel Jasper /// 200097292843SDaniel Jasper /// extern module-declaration: 200197292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 200297292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() { 200397292843SDaniel Jasper assert(Tok.is(MMToken::ExternKeyword)); 2004ae6df27eSRichard Smith SourceLocation ExternLoc = consumeToken(); // 'extern' keyword 200597292843SDaniel Jasper 200697292843SDaniel Jasper // Parse 'module' keyword. 200797292843SDaniel Jasper if (!Tok.is(MMToken::ModuleKeyword)) { 200897292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 200997292843SDaniel Jasper consumeToken(); 201097292843SDaniel Jasper HadError = true; 201197292843SDaniel Jasper return; 201297292843SDaniel Jasper } 201397292843SDaniel Jasper consumeToken(); // 'module' keyword 201497292843SDaniel Jasper 201597292843SDaniel Jasper // Parse the module name. 201697292843SDaniel Jasper ModuleId Id; 201797292843SDaniel Jasper if (parseModuleId(Id)) { 201897292843SDaniel Jasper HadError = true; 201997292843SDaniel Jasper return; 202097292843SDaniel Jasper } 202197292843SDaniel Jasper 202297292843SDaniel Jasper // Parse the referenced module map file name. 202397292843SDaniel Jasper if (!Tok.is(MMToken::StringLiteral)) { 202497292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file); 202597292843SDaniel Jasper HadError = true; 202697292843SDaniel Jasper return; 202797292843SDaniel Jasper } 202897292843SDaniel Jasper std::string FileName = Tok.getString(); 202997292843SDaniel Jasper consumeToken(); // filename 203097292843SDaniel Jasper 203197292843SDaniel Jasper StringRef FileNameRef = FileName; 203297292843SDaniel Jasper SmallString<128> ModuleMapFileName; 203397292843SDaniel Jasper if (llvm::sys::path::is_relative(FileNameRef)) { 203497292843SDaniel Jasper ModuleMapFileName += Directory->getName(); 203597292843SDaniel Jasper llvm::sys::path::append(ModuleMapFileName, FileName); 203692e1b62dSYaron Keren FileNameRef = ModuleMapFileName; 203797292843SDaniel Jasper } 203897292843SDaniel Jasper if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef)) 20399acb99e3SRichard Smith Map.parseModuleMapFile( 20409acb99e3SRichard Smith File, /*IsSystem=*/false, 20419acb99e3SRichard Smith Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd 20429acb99e3SRichard Smith ? Directory 20438128f332SRichard Smith : File->getDir(), 2044*8587dfd9SBruno Cardoso Lopes false /*IsExplicitlyProvided*/, FileID(), nullptr, ExternLoc); 204597292843SDaniel Jasper } 204697292843SDaniel Jasper 20477ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M. 20487ff29148SBen Langmuir /// 20497ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system 20507ff29148SBen Langmuir /// module map files: 20517ff29148SBen Langmuir /// 20527ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which 20537ff29148SBen Langmuir /// should really be mapped to 'textual' now that we have this feature. We 20547ff29148SBen Langmuir /// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to 20557ff29148SBen Langmuir /// true. Later, this bit will be used to map all the headers inside this 20567ff29148SBen Langmuir /// module to 'textual'. 20577ff29148SBen Langmuir /// 20587ff29148SBen Langmuir /// This affects Darwin.C.excluded (for assert.h) and Tcl.Private. 20597ff29148SBen Langmuir /// 20607ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement 20617ff29148SBen Langmuir /// was never correct and causes issues now that we check it, so drop it. 20627ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature, 20637ff29148SBen Langmuir bool &IsRequiresExcludedHack) { 20648013e81dSBenjamin Kramer if (Feature == "excluded" && 20658013e81dSBenjamin Kramer (M->fullModuleNameIs({"Darwin", "C", "excluded"}) || 20668013e81dSBenjamin Kramer M->fullModuleNameIs({"Tcl", "Private"}))) { 20677ff29148SBen Langmuir IsRequiresExcludedHack = true; 20687ff29148SBen Langmuir return false; 20698013e81dSBenjamin Kramer } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) { 20707ff29148SBen Langmuir return false; 20717ff29148SBen Langmuir } 20727ff29148SBen Langmuir 20737ff29148SBen Langmuir return true; 20747ff29148SBen Langmuir } 20757ff29148SBen Langmuir 20761fb5c3a6SDouglas Gregor /// \brief Parse a requires declaration. 20771fb5c3a6SDouglas Gregor /// 20781fb5c3a6SDouglas Gregor /// requires-declaration: 20791fb5c3a6SDouglas Gregor /// 'requires' feature-list 20801fb5c3a6SDouglas Gregor /// 20811fb5c3a6SDouglas Gregor /// feature-list: 2082a3feee2aSRichard Smith /// feature ',' feature-list 2083a3feee2aSRichard Smith /// feature 2084a3feee2aSRichard Smith /// 2085a3feee2aSRichard Smith /// feature: 2086a3feee2aSRichard Smith /// '!'[opt] identifier 20871fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() { 20881fb5c3a6SDouglas Gregor assert(Tok.is(MMToken::RequiresKeyword)); 20891fb5c3a6SDouglas Gregor 20901fb5c3a6SDouglas Gregor // Parse 'requires' keyword. 20911fb5c3a6SDouglas Gregor consumeToken(); 20921fb5c3a6SDouglas Gregor 20931fb5c3a6SDouglas Gregor // Parse the feature-list. 20941fb5c3a6SDouglas Gregor do { 2095a3feee2aSRichard Smith bool RequiredState = true; 2096a3feee2aSRichard Smith if (Tok.is(MMToken::Exclaim)) { 2097a3feee2aSRichard Smith RequiredState = false; 2098a3feee2aSRichard Smith consumeToken(); 2099a3feee2aSRichard Smith } 2100a3feee2aSRichard Smith 21011fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 21021fb5c3a6SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature); 21031fb5c3a6SDouglas Gregor HadError = true; 21041fb5c3a6SDouglas Gregor return; 21051fb5c3a6SDouglas Gregor } 21061fb5c3a6SDouglas Gregor 21071fb5c3a6SDouglas Gregor // Consume the feature name. 21081fb5c3a6SDouglas Gregor std::string Feature = Tok.getString(); 21091fb5c3a6SDouglas Gregor consumeToken(); 21101fb5c3a6SDouglas Gregor 21117ff29148SBen Langmuir bool IsRequiresExcludedHack = false; 21127ff29148SBen Langmuir bool ShouldAddRequirement = 21137ff29148SBen Langmuir shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack); 21147ff29148SBen Langmuir 21157ff29148SBen Langmuir if (IsRequiresExcludedHack) 21167ff29148SBen Langmuir UsesRequiresExcludedHack.insert(ActiveModule); 21177ff29148SBen Langmuir 21187ff29148SBen Langmuir if (ShouldAddRequirement) { 21191fb5c3a6SDouglas Gregor // Add this feature. 21207ff29148SBen Langmuir ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts, 21217ff29148SBen Langmuir *Map.Target); 21227ff29148SBen Langmuir } 21231fb5c3a6SDouglas Gregor 21241fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Comma)) 21251fb5c3a6SDouglas Gregor break; 21261fb5c3a6SDouglas Gregor 21271fb5c3a6SDouglas Gregor // Consume the comma. 21281fb5c3a6SDouglas Gregor consumeToken(); 21291fb5c3a6SDouglas Gregor } while (true); 21301fb5c3a6SDouglas Gregor } 21311fb5c3a6SDouglas Gregor 2132718292f2SDouglas Gregor /// \brief Parse a header declaration. 2133718292f2SDouglas Gregor /// 2134718292f2SDouglas Gregor /// header-declaration: 2135306d8920SRichard Smith /// 'textual'[opt] 'header' string-literal 2136202210b3SRichard Smith /// 'private' 'textual'[opt] 'header' string-literal 2137202210b3SRichard Smith /// 'exclude' 'header' string-literal 2138202210b3SRichard Smith /// 'umbrella' 'header' string-literal 2139306d8920SRichard Smith /// 2140306d8920SRichard Smith /// FIXME: Support 'private textual header'. 2141b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, 2142b53e5483SLawrence Crowl SourceLocation LeadingLoc) { 2143202210b3SRichard Smith // We've already consumed the first token. 2144202210b3SRichard Smith ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader; 2145202210b3SRichard Smith if (LeadingToken == MMToken::PrivateKeyword) { 2146202210b3SRichard Smith Role = ModuleMap::PrivateHeader; 2147202210b3SRichard Smith // 'private' may optionally be followed by 'textual'. 2148202210b3SRichard Smith if (Tok.is(MMToken::TextualKeyword)) { 2149202210b3SRichard Smith LeadingToken = Tok.Kind; 21501871ed3dSBenjamin Kramer consumeToken(); 2151202210b3SRichard Smith } 2152202210b3SRichard Smith } 21537ff29148SBen Langmuir 2154202210b3SRichard Smith if (LeadingToken == MMToken::TextualKeyword) 2155202210b3SRichard Smith Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 2156202210b3SRichard Smith 21577ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 21587ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 21597ff29148SBen Langmuir // Module::UsesRequiresExcludedHack). 21607ff29148SBen Langmuir Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 21617ff29148SBen Langmuir } 21627ff29148SBen Langmuir 2163202210b3SRichard Smith if (LeadingToken != MMToken::HeaderKeyword) { 2164202210b3SRichard Smith if (!Tok.is(MMToken::HeaderKeyword)) { 2165202210b3SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2166202210b3SRichard Smith << (LeadingToken == MMToken::PrivateKeyword ? "private" : 2167202210b3SRichard Smith LeadingToken == MMToken::ExcludeKeyword ? "exclude" : 2168202210b3SRichard Smith LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella"); 2169202210b3SRichard Smith return; 2170202210b3SRichard Smith } 2171202210b3SRichard Smith consumeToken(); 2172202210b3SRichard Smith } 2173718292f2SDouglas Gregor 2174718292f2SDouglas Gregor // Parse the header name. 2175718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2176718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2177718292f2SDouglas Gregor << "header"; 2178718292f2SDouglas Gregor HadError = true; 2179718292f2SDouglas Gregor return; 2180718292f2SDouglas Gregor } 21813c1a41adSRichard Smith Module::UnresolvedHeaderDirective Header; 21820761a8a0SDaniel Jasper Header.FileName = Tok.getString(); 21830761a8a0SDaniel Jasper Header.FileNameLoc = consumeToken(); 21841d60987fSRichard Smith Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword; 2185040e1266SRichard Smith Header.Kind = 2186040e1266SRichard Smith (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded 2187040e1266SRichard Smith : Map.headerRoleToKind(Role)); 2188718292f2SDouglas Gregor 2189524e33e1SDouglas Gregor // Check whether we already have an umbrella. 21901d60987fSRichard Smith if (Header.IsUmbrella && ActiveModule->Umbrella) { 21910761a8a0SDaniel Jasper Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) 2192524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2193322f633cSDouglas Gregor HadError = true; 2194322f633cSDouglas Gregor return; 2195322f633cSDouglas Gregor } 2196322f633cSDouglas Gregor 2197040e1266SRichard Smith // If we were given stat information, parse it so we can skip looking for 2198040e1266SRichard Smith // the file. 2199040e1266SRichard Smith if (Tok.is(MMToken::LBrace)) { 2200040e1266SRichard Smith SourceLocation LBraceLoc = consumeToken(); 22013ec6663bSDouglas Gregor 2202040e1266SRichard Smith while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) { 2203040e1266SRichard Smith enum Attribute { Size, ModTime, Unknown }; 2204040e1266SRichard Smith StringRef Str = Tok.getString(); 2205040e1266SRichard Smith SourceLocation Loc = consumeToken(); 2206040e1266SRichard Smith switch (llvm::StringSwitch<Attribute>(Str) 2207040e1266SRichard Smith .Case("size", Size) 2208040e1266SRichard Smith .Case("mtime", ModTime) 2209040e1266SRichard Smith .Default(Unknown)) { 2210040e1266SRichard Smith case Size: 2211040e1266SRichard Smith if (Header.Size) 2212040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2213040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2214040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2215040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2216040e1266SRichard Smith skipUntil(MMToken::RBrace); 2217040e1266SRichard Smith break; 2218040e1266SRichard Smith } 2219040e1266SRichard Smith Header.Size = Tok.getInteger(); 2220040e1266SRichard Smith consumeToken(); 2221040e1266SRichard Smith break; 2222040e1266SRichard Smith 2223040e1266SRichard Smith case ModTime: 2224040e1266SRichard Smith if (Header.ModTime) 2225040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2226040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2227040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2228040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2229040e1266SRichard Smith skipUntil(MMToken::RBrace); 2230040e1266SRichard Smith break; 2231040e1266SRichard Smith } 2232040e1266SRichard Smith Header.ModTime = Tok.getInteger(); 2233040e1266SRichard Smith consumeToken(); 2234040e1266SRichard Smith break; 2235040e1266SRichard Smith 2236040e1266SRichard Smith case Unknown: 2237040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_expected_header_attribute); 2238040e1266SRichard Smith skipUntil(MMToken::RBrace); 2239040e1266SRichard Smith break; 2240040e1266SRichard Smith } 22413ec6663bSDouglas Gregor } 22425257fc63SDouglas Gregor 2243040e1266SRichard Smith if (Tok.is(MMToken::RBrace)) 2244040e1266SRichard Smith consumeToken(); 2245040e1266SRichard Smith else { 2246040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 2247040e1266SRichard Smith Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 2248322f633cSDouglas Gregor HadError = true; 2249322f633cSDouglas Gregor } 22500101b540SHans Wennborg } 225125d50758SRichard Smith 2252040e1266SRichard Smith Map.addUnresolvedHeader(ActiveModule, std::move(Header)); 2253718292f2SDouglas Gregor } 2254718292f2SDouglas Gregor 225541f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A, 225641f81994SBen Langmuir const Module::Header *B) { 225741f81994SBen Langmuir return A->NameAsWritten.compare(B->NameAsWritten); 225841f81994SBen Langmuir } 225941f81994SBen Langmuir 2260524e33e1SDouglas Gregor /// \brief Parse an umbrella directory declaration. 2261524e33e1SDouglas Gregor /// 2262524e33e1SDouglas Gregor /// umbrella-dir-declaration: 2263524e33e1SDouglas Gregor /// umbrella string-literal 2264524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { 2265524e33e1SDouglas Gregor // Parse the directory name. 2266524e33e1SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2267524e33e1SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2268524e33e1SDouglas Gregor << "umbrella"; 2269524e33e1SDouglas Gregor HadError = true; 2270524e33e1SDouglas Gregor return; 2271524e33e1SDouglas Gregor } 2272524e33e1SDouglas Gregor 2273524e33e1SDouglas Gregor std::string DirName = Tok.getString(); 2274524e33e1SDouglas Gregor SourceLocation DirNameLoc = consumeToken(); 2275524e33e1SDouglas Gregor 2276524e33e1SDouglas Gregor // Check whether we already have an umbrella. 2277524e33e1SDouglas Gregor if (ActiveModule->Umbrella) { 2278524e33e1SDouglas Gregor Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash) 2279524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2280524e33e1SDouglas Gregor HadError = true; 2281524e33e1SDouglas Gregor return; 2282524e33e1SDouglas Gregor } 2283524e33e1SDouglas Gregor 2284524e33e1SDouglas Gregor // Look for this file. 2285d2d442caSCraig Topper const DirectoryEntry *Dir = nullptr; 2286524e33e1SDouglas Gregor if (llvm::sys::path::is_absolute(DirName)) 2287524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(DirName); 2288524e33e1SDouglas Gregor else { 22892c1dd271SDylan Noblesmith SmallString<128> PathName; 2290524e33e1SDouglas Gregor PathName = Directory->getName(); 2291524e33e1SDouglas Gregor llvm::sys::path::append(PathName, DirName); 2292524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(PathName); 2293524e33e1SDouglas Gregor } 2294524e33e1SDouglas Gregor 2295524e33e1SDouglas Gregor if (!Dir) { 2296a0320b97SVassil Vassilev Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found) 2297524e33e1SDouglas Gregor << DirName; 2298524e33e1SDouglas Gregor return; 2299524e33e1SDouglas Gregor } 2300524e33e1SDouglas Gregor 23017ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 23027ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 23037ff29148SBen Langmuir // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the 23047ff29148SBen Langmuir // directory is relatively expensive, in practice this only applies to the 23057ff29148SBen Langmuir // uncommonly used Tcl module on Darwin platforms. 23067ff29148SBen Langmuir std::error_code EC; 23077ff29148SBen Langmuir SmallVector<Module::Header, 6> Headers; 2308b171a59bSBruno Cardoso Lopes vfs::FileSystem &FS = *SourceMgr.getFileManager().getVirtualFileSystem(); 2309b171a59bSBruno Cardoso Lopes for (vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E; 23107ff29148SBen Langmuir I != E && !EC; I.increment(EC)) { 2311b171a59bSBruno Cardoso Lopes if (const FileEntry *FE = 2312b171a59bSBruno Cardoso Lopes SourceMgr.getFileManager().getFile(I->getName())) { 23137ff29148SBen Langmuir 2314b171a59bSBruno Cardoso Lopes Module::Header Header = {I->getName(), FE}; 23157ff29148SBen Langmuir Headers.push_back(std::move(Header)); 23167ff29148SBen Langmuir } 23177ff29148SBen Langmuir } 23187ff29148SBen Langmuir 23197ff29148SBen Langmuir // Sort header paths so that the pcm doesn't depend on iteration order. 232041f81994SBen Langmuir llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders); 232141f81994SBen Langmuir 23227ff29148SBen Langmuir for (auto &Header : Headers) 23237ff29148SBen Langmuir Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader); 23247ff29148SBen Langmuir return; 23257ff29148SBen Langmuir } 23267ff29148SBen Langmuir 2327524e33e1SDouglas Gregor if (Module *OwningModule = Map.UmbrellaDirs[Dir]) { 2328524e33e1SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 2329524e33e1SDouglas Gregor << OwningModule->getFullModuleName(); 2330524e33e1SDouglas Gregor HadError = true; 2331524e33e1SDouglas Gregor return; 2332524e33e1SDouglas Gregor } 2333524e33e1SDouglas Gregor 2334524e33e1SDouglas Gregor // Record this umbrella directory. 23352b63d15fSRichard Smith Map.setUmbrellaDir(ActiveModule, Dir, DirName); 2336524e33e1SDouglas Gregor } 2337524e33e1SDouglas Gregor 23382b82c2a5SDouglas Gregor /// \brief Parse a module export declaration. 23392b82c2a5SDouglas Gregor /// 23402b82c2a5SDouglas Gregor /// export-declaration: 23412b82c2a5SDouglas Gregor /// 'export' wildcard-module-id 23422b82c2a5SDouglas Gregor /// 23432b82c2a5SDouglas Gregor /// wildcard-module-id: 23442b82c2a5SDouglas Gregor /// identifier 23452b82c2a5SDouglas Gregor /// '*' 23462b82c2a5SDouglas Gregor /// identifier '.' wildcard-module-id 23472b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() { 23482b82c2a5SDouglas Gregor assert(Tok.is(MMToken::ExportKeyword)); 23492b82c2a5SDouglas Gregor SourceLocation ExportLoc = consumeToken(); 23502b82c2a5SDouglas Gregor 23512b82c2a5SDouglas Gregor // Parse the module-id with an optional wildcard at the end. 23522b82c2a5SDouglas Gregor ModuleId ParsedModuleId; 23532b82c2a5SDouglas Gregor bool Wildcard = false; 23542b82c2a5SDouglas Gregor do { 2355306d8920SRichard Smith // FIXME: Support string-literal module names here. 23562b82c2a5SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 23572b82c2a5SDouglas Gregor ParsedModuleId.push_back(std::make_pair(Tok.getString(), 23582b82c2a5SDouglas Gregor Tok.getLocation())); 23592b82c2a5SDouglas Gregor consumeToken(); 23602b82c2a5SDouglas Gregor 23612b82c2a5SDouglas Gregor if (Tok.is(MMToken::Period)) { 23622b82c2a5SDouglas Gregor consumeToken(); 23632b82c2a5SDouglas Gregor continue; 23642b82c2a5SDouglas Gregor } 23652b82c2a5SDouglas Gregor 23662b82c2a5SDouglas Gregor break; 23672b82c2a5SDouglas Gregor } 23682b82c2a5SDouglas Gregor 23692b82c2a5SDouglas Gregor if(Tok.is(MMToken::Star)) { 23702b82c2a5SDouglas Gregor Wildcard = true; 2371f5eedd05SDouglas Gregor consumeToken(); 23722b82c2a5SDouglas Gregor break; 23732b82c2a5SDouglas Gregor } 23742b82c2a5SDouglas Gregor 2375ba7f2f71SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_module_id); 23762b82c2a5SDouglas Gregor HadError = true; 23772b82c2a5SDouglas Gregor return; 23782b82c2a5SDouglas Gregor } while (true); 23792b82c2a5SDouglas Gregor 23802b82c2a5SDouglas Gregor Module::UnresolvedExportDecl Unresolved = { 23812b82c2a5SDouglas Gregor ExportLoc, ParsedModuleId, Wildcard 23822b82c2a5SDouglas Gregor }; 23832b82c2a5SDouglas Gregor ActiveModule->UnresolvedExports.push_back(Unresolved); 23842b82c2a5SDouglas Gregor } 23852b82c2a5SDouglas Gregor 2386f0b11de2SDouglas Gregor /// \brief Parse a module export_as declaration. 2387f0b11de2SDouglas Gregor /// 2388f0b11de2SDouglas Gregor /// export-as-declaration: 2389f0b11de2SDouglas Gregor /// 'export_as' identifier 2390f0b11de2SDouglas Gregor void ModuleMapParser::parseExportAsDecl() { 2391f0b11de2SDouglas Gregor assert(Tok.is(MMToken::ExportAsKeyword)); 2392f0b11de2SDouglas Gregor consumeToken(); 2393f0b11de2SDouglas Gregor 2394f0b11de2SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 2395f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_module_id); 2396f0b11de2SDouglas Gregor HadError = true; 2397f0b11de2SDouglas Gregor return; 2398f0b11de2SDouglas Gregor } 2399f0b11de2SDouglas Gregor 2400f0b11de2SDouglas Gregor if (ActiveModule->Parent) { 2401f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as); 2402f0b11de2SDouglas Gregor consumeToken(); 2403f0b11de2SDouglas Gregor return; 2404f0b11de2SDouglas Gregor } 2405f0b11de2SDouglas Gregor 2406f0b11de2SDouglas Gregor if (!ActiveModule->ExportAsModule.empty()) { 2407f0b11de2SDouglas Gregor if (ActiveModule->ExportAsModule == Tok.getString()) { 2408f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as) 2409f0b11de2SDouglas Gregor << ActiveModule->Name << Tok.getString(); 2410f0b11de2SDouglas Gregor } else { 2411f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as) 2412f0b11de2SDouglas Gregor << ActiveModule->Name << ActiveModule->ExportAsModule 2413f0b11de2SDouglas Gregor << Tok.getString(); 2414f0b11de2SDouglas Gregor } 2415f0b11de2SDouglas Gregor } 2416f0b11de2SDouglas Gregor 2417f0b11de2SDouglas Gregor ActiveModule->ExportAsModule = Tok.getString(); 2418f0b11de2SDouglas Gregor consumeToken(); 2419f0b11de2SDouglas Gregor } 2420f0b11de2SDouglas Gregor 24218f4d3ff1SRichard Smith /// \brief Parse a module use declaration. 2422ba7f2f71SDaniel Jasper /// 24238f4d3ff1SRichard Smith /// use-declaration: 24248f4d3ff1SRichard Smith /// 'use' wildcard-module-id 2425ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() { 2426ba7f2f71SDaniel Jasper assert(Tok.is(MMToken::UseKeyword)); 24278f4d3ff1SRichard Smith auto KWLoc = consumeToken(); 2428ba7f2f71SDaniel Jasper // Parse the module-id. 2429ba7f2f71SDaniel Jasper ModuleId ParsedModuleId; 24303cd34c76SDaniel Jasper parseModuleId(ParsedModuleId); 2431ba7f2f71SDaniel Jasper 24328f4d3ff1SRichard Smith if (ActiveModule->Parent) 24338f4d3ff1SRichard Smith Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule); 24348f4d3ff1SRichard Smith else 2435ba7f2f71SDaniel Jasper ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId); 2436ba7f2f71SDaniel Jasper } 2437ba7f2f71SDaniel Jasper 24386ddfca91SDouglas Gregor /// \brief Parse a link declaration. 24396ddfca91SDouglas Gregor /// 24406ddfca91SDouglas Gregor /// module-declaration: 24416ddfca91SDouglas Gregor /// 'link' 'framework'[opt] string-literal 24426ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() { 24436ddfca91SDouglas Gregor assert(Tok.is(MMToken::LinkKeyword)); 24446ddfca91SDouglas Gregor SourceLocation LinkLoc = consumeToken(); 24456ddfca91SDouglas Gregor 24466ddfca91SDouglas Gregor // Parse the optional 'framework' keyword. 24476ddfca91SDouglas Gregor bool IsFramework = false; 24486ddfca91SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 24496ddfca91SDouglas Gregor consumeToken(); 24506ddfca91SDouglas Gregor IsFramework = true; 24516ddfca91SDouglas Gregor } 24526ddfca91SDouglas Gregor 24536ddfca91SDouglas Gregor // Parse the library name 24546ddfca91SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 24556ddfca91SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name) 24566ddfca91SDouglas Gregor << IsFramework << SourceRange(LinkLoc); 24576ddfca91SDouglas Gregor HadError = true; 24586ddfca91SDouglas Gregor return; 24596ddfca91SDouglas Gregor } 24606ddfca91SDouglas Gregor 24616ddfca91SDouglas Gregor std::string LibraryName = Tok.getString(); 24626ddfca91SDouglas Gregor consumeToken(); 24636ddfca91SDouglas Gregor ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName, 24646ddfca91SDouglas Gregor IsFramework)); 24656ddfca91SDouglas Gregor } 24666ddfca91SDouglas Gregor 246735b13eceSDouglas Gregor /// \brief Parse a configuration macro declaration. 246835b13eceSDouglas Gregor /// 246935b13eceSDouglas Gregor /// module-declaration: 247035b13eceSDouglas Gregor /// 'config_macros' attributes[opt] config-macro-list? 247135b13eceSDouglas Gregor /// 247235b13eceSDouglas Gregor /// config-macro-list: 247335b13eceSDouglas Gregor /// identifier (',' identifier)? 247435b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() { 247535b13eceSDouglas Gregor assert(Tok.is(MMToken::ConfigMacros)); 247635b13eceSDouglas Gregor SourceLocation ConfigMacrosLoc = consumeToken(); 247735b13eceSDouglas Gregor 247835b13eceSDouglas Gregor // Only top-level modules can have configuration macros. 247935b13eceSDouglas Gregor if (ActiveModule->Parent) { 248035b13eceSDouglas Gregor Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule); 248135b13eceSDouglas Gregor } 248235b13eceSDouglas Gregor 248335b13eceSDouglas Gregor // Parse the optional attributes. 248435b13eceSDouglas Gregor Attributes Attrs; 24855d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 24865d29dee0SDavide Italiano return; 24875d29dee0SDavide Italiano 248835b13eceSDouglas Gregor if (Attrs.IsExhaustive && !ActiveModule->Parent) { 248935b13eceSDouglas Gregor ActiveModule->ConfigMacrosExhaustive = true; 249035b13eceSDouglas Gregor } 249135b13eceSDouglas Gregor 249235b13eceSDouglas Gregor // If we don't have an identifier, we're done. 2493306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 249435b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) 249535b13eceSDouglas Gregor return; 249635b13eceSDouglas Gregor 249735b13eceSDouglas Gregor // Consume the first identifier. 249835b13eceSDouglas Gregor if (!ActiveModule->Parent) { 249935b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 250035b13eceSDouglas Gregor } 250135b13eceSDouglas Gregor consumeToken(); 250235b13eceSDouglas Gregor 250335b13eceSDouglas Gregor do { 250435b13eceSDouglas Gregor // If there's a comma, consume it. 250535b13eceSDouglas Gregor if (!Tok.is(MMToken::Comma)) 250635b13eceSDouglas Gregor break; 250735b13eceSDouglas Gregor consumeToken(); 250835b13eceSDouglas Gregor 250935b13eceSDouglas Gregor // We expect to see a macro name here. 2510306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 251135b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 251235b13eceSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro); 251335b13eceSDouglas Gregor break; 251435b13eceSDouglas Gregor } 251535b13eceSDouglas Gregor 251635b13eceSDouglas Gregor // Consume the macro name. 251735b13eceSDouglas Gregor if (!ActiveModule->Parent) { 251835b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 251935b13eceSDouglas Gregor } 252035b13eceSDouglas Gregor consumeToken(); 252135b13eceSDouglas Gregor } while (true); 252235b13eceSDouglas Gregor } 252335b13eceSDouglas Gregor 2524fb912657SDouglas Gregor /// \brief Format a module-id into a string. 2525fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) { 2526fb912657SDouglas Gregor std::string result; 2527fb912657SDouglas Gregor { 2528fb912657SDouglas Gregor llvm::raw_string_ostream OS(result); 2529fb912657SDouglas Gregor 2530fb912657SDouglas Gregor for (unsigned I = 0, N = Id.size(); I != N; ++I) { 2531fb912657SDouglas Gregor if (I) 2532fb912657SDouglas Gregor OS << "."; 2533fb912657SDouglas Gregor OS << Id[I].first; 2534fb912657SDouglas Gregor } 2535fb912657SDouglas Gregor } 2536fb912657SDouglas Gregor 2537fb912657SDouglas Gregor return result; 2538fb912657SDouglas Gregor } 2539fb912657SDouglas Gregor 2540fb912657SDouglas Gregor /// \brief Parse a conflict declaration. 2541fb912657SDouglas Gregor /// 2542fb912657SDouglas Gregor /// module-declaration: 2543fb912657SDouglas Gregor /// 'conflict' module-id ',' string-literal 2544fb912657SDouglas Gregor void ModuleMapParser::parseConflict() { 2545fb912657SDouglas Gregor assert(Tok.is(MMToken::Conflict)); 2546fb912657SDouglas Gregor SourceLocation ConflictLoc = consumeToken(); 2547fb912657SDouglas Gregor Module::UnresolvedConflict Conflict; 2548fb912657SDouglas Gregor 2549fb912657SDouglas Gregor // Parse the module-id. 2550fb912657SDouglas Gregor if (parseModuleId(Conflict.Id)) 2551fb912657SDouglas Gregor return; 2552fb912657SDouglas Gregor 2553fb912657SDouglas Gregor // Parse the ','. 2554fb912657SDouglas Gregor if (!Tok.is(MMToken::Comma)) { 2555fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma) 2556fb912657SDouglas Gregor << SourceRange(ConflictLoc); 2557fb912657SDouglas Gregor return; 2558fb912657SDouglas Gregor } 2559fb912657SDouglas Gregor consumeToken(); 2560fb912657SDouglas Gregor 2561fb912657SDouglas Gregor // Parse the message. 2562fb912657SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2563fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message) 2564fb912657SDouglas Gregor << formatModuleId(Conflict.Id); 2565fb912657SDouglas Gregor return; 2566fb912657SDouglas Gregor } 2567fb912657SDouglas Gregor Conflict.Message = Tok.getString().str(); 2568fb912657SDouglas Gregor consumeToken(); 2569fb912657SDouglas Gregor 2570fb912657SDouglas Gregor // Add this unresolved conflict. 2571fb912657SDouglas Gregor ActiveModule->UnresolvedConflicts.push_back(Conflict); 2572fb912657SDouglas Gregor } 2573fb912657SDouglas Gregor 25746ddfca91SDouglas Gregor /// \brief Parse an inferred module declaration (wildcard modules). 25759194a91dSDouglas Gregor /// 25769194a91dSDouglas Gregor /// module-declaration: 25779194a91dSDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt] 25789194a91dSDouglas Gregor /// { inferred-module-member* } 25799194a91dSDouglas Gregor /// 25809194a91dSDouglas Gregor /// inferred-module-member: 25819194a91dSDouglas Gregor /// 'export' '*' 25829194a91dSDouglas Gregor /// 'exclude' identifier 25839194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { 258473441091SDouglas Gregor assert(Tok.is(MMToken::Star)); 258573441091SDouglas Gregor SourceLocation StarLoc = consumeToken(); 258673441091SDouglas Gregor bool Failed = false; 258773441091SDouglas Gregor 258873441091SDouglas Gregor // Inferred modules must be submodules. 25899194a91dSDouglas Gregor if (!ActiveModule && !Framework) { 259073441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule); 259173441091SDouglas Gregor Failed = true; 259273441091SDouglas Gregor } 259373441091SDouglas Gregor 25949194a91dSDouglas Gregor if (ActiveModule) { 2595524e33e1SDouglas Gregor // Inferred modules must have umbrella directories. 25964898cde4SBen Langmuir if (!Failed && ActiveModule->IsAvailable && 25974898cde4SBen Langmuir !ActiveModule->getUmbrellaDir()) { 259873441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); 259973441091SDouglas Gregor Failed = true; 260073441091SDouglas Gregor } 260173441091SDouglas Gregor 260273441091SDouglas Gregor // Check for redefinition of an inferred module. 2603dd005f69SDouglas Gregor if (!Failed && ActiveModule->InferSubmodules) { 260473441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_redef); 2605dd005f69SDouglas Gregor if (ActiveModule->InferredSubmoduleLoc.isValid()) 2606dd005f69SDouglas Gregor Diags.Report(ActiveModule->InferredSubmoduleLoc, 260773441091SDouglas Gregor diag::note_mmap_prev_definition); 260873441091SDouglas Gregor Failed = true; 260973441091SDouglas Gregor } 261073441091SDouglas Gregor 26119194a91dSDouglas Gregor // Check for the 'framework' keyword, which is not permitted here. 26129194a91dSDouglas Gregor if (Framework) { 26139194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule); 26149194a91dSDouglas Gregor Framework = false; 26159194a91dSDouglas Gregor } 26169194a91dSDouglas Gregor } else if (Explicit) { 26179194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework); 26189194a91dSDouglas Gregor Explicit = false; 26199194a91dSDouglas Gregor } 26209194a91dSDouglas Gregor 262173441091SDouglas Gregor // If there were any problems with this inferred submodule, skip its body. 262273441091SDouglas Gregor if (Failed) { 262373441091SDouglas Gregor if (Tok.is(MMToken::LBrace)) { 262473441091SDouglas Gregor consumeToken(); 262573441091SDouglas Gregor skipUntil(MMToken::RBrace); 262673441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 262773441091SDouglas Gregor consumeToken(); 262873441091SDouglas Gregor } 262973441091SDouglas Gregor HadError = true; 263073441091SDouglas Gregor return; 263173441091SDouglas Gregor } 263273441091SDouglas Gregor 26339194a91dSDouglas Gregor // Parse optional attributes. 26344442605fSBill Wendling Attributes Attrs; 26355d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 26365d29dee0SDavide Italiano return; 26379194a91dSDouglas Gregor 26389194a91dSDouglas Gregor if (ActiveModule) { 263973441091SDouglas Gregor // Note that we have an inferred submodule. 2640dd005f69SDouglas Gregor ActiveModule->InferSubmodules = true; 2641dd005f69SDouglas Gregor ActiveModule->InferredSubmoduleLoc = StarLoc; 2642dd005f69SDouglas Gregor ActiveModule->InferExplicitSubmodules = Explicit; 26439194a91dSDouglas Gregor } else { 26449194a91dSDouglas Gregor // We'll be inferring framework modules for this directory. 26459194a91dSDouglas Gregor Map.InferredDirectories[Directory].InferModules = true; 2646c1d88ea5SBen Langmuir Map.InferredDirectories[Directory].Attrs = Attrs; 2647beee15e7SBen Langmuir Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile; 2648131daca0SRichard Smith // FIXME: Handle the 'framework' keyword. 26499194a91dSDouglas Gregor } 265073441091SDouglas Gregor 265173441091SDouglas Gregor // Parse the opening brace. 265273441091SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 265373441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard); 265473441091SDouglas Gregor HadError = true; 265573441091SDouglas Gregor return; 265673441091SDouglas Gregor } 265773441091SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 265873441091SDouglas Gregor 265973441091SDouglas Gregor // Parse the body of the inferred submodule. 266073441091SDouglas Gregor bool Done = false; 266173441091SDouglas Gregor do { 266273441091SDouglas Gregor switch (Tok.Kind) { 266373441091SDouglas Gregor case MMToken::EndOfFile: 266473441091SDouglas Gregor case MMToken::RBrace: 266573441091SDouglas Gregor Done = true; 266673441091SDouglas Gregor break; 266773441091SDouglas Gregor 2668afd1b1c9SEugene Zelenko case MMToken::ExcludeKeyword: 26699194a91dSDouglas Gregor if (ActiveModule) { 26709194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2671d2d442caSCraig Topper << (ActiveModule != nullptr); 26729194a91dSDouglas Gregor consumeToken(); 26739194a91dSDouglas Gregor break; 26749194a91dSDouglas Gregor } 26759194a91dSDouglas Gregor 26769194a91dSDouglas Gregor consumeToken(); 2677306d8920SRichard Smith // FIXME: Support string-literal module names here. 26789194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 26799194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name); 26809194a91dSDouglas Gregor break; 26819194a91dSDouglas Gregor } 26829194a91dSDouglas Gregor 26839194a91dSDouglas Gregor Map.InferredDirectories[Directory].ExcludedModules 26849194a91dSDouglas Gregor .push_back(Tok.getString()); 26859194a91dSDouglas Gregor consumeToken(); 26869194a91dSDouglas Gregor break; 26879194a91dSDouglas Gregor 26889194a91dSDouglas Gregor case MMToken::ExportKeyword: 26899194a91dSDouglas Gregor if (!ActiveModule) { 26909194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2691d2d442caSCraig Topper << (ActiveModule != nullptr); 26929194a91dSDouglas Gregor consumeToken(); 26939194a91dSDouglas Gregor break; 26949194a91dSDouglas Gregor } 26959194a91dSDouglas Gregor 269673441091SDouglas Gregor consumeToken(); 269773441091SDouglas Gregor if (Tok.is(MMToken::Star)) 2698dd005f69SDouglas Gregor ActiveModule->InferExportWildcard = true; 269973441091SDouglas Gregor else 270073441091SDouglas Gregor Diags.Report(Tok.getLocation(), 270173441091SDouglas Gregor diag::err_mmap_expected_export_wildcard); 270273441091SDouglas Gregor consumeToken(); 270373441091SDouglas Gregor break; 270473441091SDouglas Gregor 270573441091SDouglas Gregor case MMToken::ExplicitKeyword: 270673441091SDouglas Gregor case MMToken::ModuleKeyword: 270773441091SDouglas Gregor case MMToken::HeaderKeyword: 2708b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 270973441091SDouglas Gregor case MMToken::UmbrellaKeyword: 271073441091SDouglas Gregor default: 27119194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2712d2d442caSCraig Topper << (ActiveModule != nullptr); 271373441091SDouglas Gregor consumeToken(); 271473441091SDouglas Gregor break; 271573441091SDouglas Gregor } 271673441091SDouglas Gregor } while (!Done); 271773441091SDouglas Gregor 271873441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 271973441091SDouglas Gregor consumeToken(); 272073441091SDouglas Gregor else { 272173441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 272273441091SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 272373441091SDouglas Gregor HadError = true; 272473441091SDouglas Gregor } 272573441091SDouglas Gregor } 272673441091SDouglas Gregor 27279194a91dSDouglas Gregor /// \brief Parse optional attributes. 27289194a91dSDouglas Gregor /// 27299194a91dSDouglas Gregor /// attributes: 27309194a91dSDouglas Gregor /// attribute attributes 27319194a91dSDouglas Gregor /// attribute 27329194a91dSDouglas Gregor /// 27339194a91dSDouglas Gregor /// attribute: 27349194a91dSDouglas Gregor /// [ identifier ] 27359194a91dSDouglas Gregor /// 27369194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes. 27379194a91dSDouglas Gregor /// 27389194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise. 27394442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { 27409194a91dSDouglas Gregor bool HadError = false; 27419194a91dSDouglas Gregor 27429194a91dSDouglas Gregor while (Tok.is(MMToken::LSquare)) { 27439194a91dSDouglas Gregor // Consume the '['. 27449194a91dSDouglas Gregor SourceLocation LSquareLoc = consumeToken(); 27459194a91dSDouglas Gregor 27469194a91dSDouglas Gregor // Check whether we have an attribute name here. 27479194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 27489194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute); 27499194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 27509194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 27519194a91dSDouglas Gregor consumeToken(); 27529194a91dSDouglas Gregor HadError = true; 27539194a91dSDouglas Gregor } 27549194a91dSDouglas Gregor 27559194a91dSDouglas Gregor // Decode the attribute name. 27569194a91dSDouglas Gregor AttributeKind Attribute 27579194a91dSDouglas Gregor = llvm::StringSwitch<AttributeKind>(Tok.getString()) 275835b13eceSDouglas Gregor .Case("exhaustive", AT_exhaustive) 275977944868SRichard Smith .Case("extern_c", AT_extern_c) 2760ed84df00SBruno Cardoso Lopes .Case("no_undeclared_includes", AT_no_undeclared_includes) 27619194a91dSDouglas Gregor .Case("system", AT_system) 27629194a91dSDouglas Gregor .Default(AT_unknown); 27639194a91dSDouglas Gregor switch (Attribute) { 27649194a91dSDouglas Gregor case AT_unknown: 27659194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute) 27669194a91dSDouglas Gregor << Tok.getString(); 27679194a91dSDouglas Gregor break; 27689194a91dSDouglas Gregor 27699194a91dSDouglas Gregor case AT_system: 27709194a91dSDouglas Gregor Attrs.IsSystem = true; 27719194a91dSDouglas Gregor break; 277235b13eceSDouglas Gregor 277377944868SRichard Smith case AT_extern_c: 277477944868SRichard Smith Attrs.IsExternC = true; 277577944868SRichard Smith break; 277677944868SRichard Smith 277735b13eceSDouglas Gregor case AT_exhaustive: 277835b13eceSDouglas Gregor Attrs.IsExhaustive = true; 277935b13eceSDouglas Gregor break; 2780ed84df00SBruno Cardoso Lopes 2781ed84df00SBruno Cardoso Lopes case AT_no_undeclared_includes: 2782ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes = true; 2783ed84df00SBruno Cardoso Lopes break; 27849194a91dSDouglas Gregor } 27859194a91dSDouglas Gregor consumeToken(); 27869194a91dSDouglas Gregor 27879194a91dSDouglas Gregor // Consume the ']'. 27889194a91dSDouglas Gregor if (!Tok.is(MMToken::RSquare)) { 27899194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare); 27909194a91dSDouglas Gregor Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match); 27919194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 27929194a91dSDouglas Gregor HadError = true; 27939194a91dSDouglas Gregor } 27949194a91dSDouglas Gregor 27959194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 27969194a91dSDouglas Gregor consumeToken(); 27979194a91dSDouglas Gregor } 27989194a91dSDouglas Gregor 27999194a91dSDouglas Gregor return HadError; 28009194a91dSDouglas Gregor } 28019194a91dSDouglas Gregor 2802718292f2SDouglas Gregor /// \brief Parse a module map file. 2803718292f2SDouglas Gregor /// 2804718292f2SDouglas Gregor /// module-map-file: 2805718292f2SDouglas Gregor /// module-declaration* 2806718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 2807718292f2SDouglas Gregor do { 2808718292f2SDouglas Gregor switch (Tok.Kind) { 2809718292f2SDouglas Gregor case MMToken::EndOfFile: 2810718292f2SDouglas Gregor return HadError; 2811718292f2SDouglas Gregor 2812e7ab3669SDouglas Gregor case MMToken::ExplicitKeyword: 281397292843SDaniel Jasper case MMToken::ExternKeyword: 2814718292f2SDouglas Gregor case MMToken::ModuleKeyword: 2815755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 2816718292f2SDouglas Gregor parseModuleDecl(); 2817718292f2SDouglas Gregor break; 2818718292f2SDouglas Gregor 28191fb5c3a6SDouglas Gregor case MMToken::Comma: 282035b13eceSDouglas Gregor case MMToken::ConfigMacros: 2821fb912657SDouglas Gregor case MMToken::Conflict: 2822a3feee2aSRichard Smith case MMToken::Exclaim: 282359527666SDouglas Gregor case MMToken::ExcludeKeyword: 28242b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 2825f0b11de2SDouglas Gregor case MMToken::ExportAsKeyword: 2826718292f2SDouglas Gregor case MMToken::HeaderKeyword: 2827718292f2SDouglas Gregor case MMToken::Identifier: 2828718292f2SDouglas Gregor case MMToken::LBrace: 28296ddfca91SDouglas Gregor case MMToken::LinkKeyword: 2830a686e1b0SDouglas Gregor case MMToken::LSquare: 28312b82c2a5SDouglas Gregor case MMToken::Period: 2832b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 2833718292f2SDouglas Gregor case MMToken::RBrace: 2834a686e1b0SDouglas Gregor case MMToken::RSquare: 28351fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 28362b82c2a5SDouglas Gregor case MMToken::Star: 2837718292f2SDouglas Gregor case MMToken::StringLiteral: 2838040e1266SRichard Smith case MMToken::IntegerLiteral: 2839b8afebe2SRichard Smith case MMToken::TextualKeyword: 2840718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 2841ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 2842718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 2843718292f2SDouglas Gregor HadError = true; 2844718292f2SDouglas Gregor consumeToken(); 2845718292f2SDouglas Gregor break; 2846718292f2SDouglas Gregor } 2847718292f2SDouglas Gregor } while (true); 2848718292f2SDouglas Gregor } 2849718292f2SDouglas Gregor 28509acb99e3SRichard Smith bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem, 2851*8587dfd9SBruno Cardoso Lopes const DirectoryEntry *Dir, 2852*8587dfd9SBruno Cardoso Lopes bool IsExplicitlyProvided, FileID ID, 28538128f332SRichard Smith unsigned *Offset, 2854ae6df27eSRichard Smith SourceLocation ExternModuleLoc) { 28558128f332SRichard Smith assert(Target && "Missing target information"); 28564ddf2221SDouglas Gregor llvm::DenseMap<const FileEntry *, bool>::iterator Known 28574ddf2221SDouglas Gregor = ParsedModuleMap.find(File); 28584ddf2221SDouglas Gregor if (Known != ParsedModuleMap.end()) 28594ddf2221SDouglas Gregor return Known->second; 28604ddf2221SDouglas Gregor 28618128f332SRichard Smith // If the module map file wasn't already entered, do so now. 28628128f332SRichard Smith if (ID.isInvalid()) { 2863f3f84616SRichard Smith auto FileCharacter = 2864f3f84616SRichard Smith IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap; 28658128f332SRichard Smith ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter); 28668128f332SRichard Smith } 28678128f332SRichard Smith 28688128f332SRichard Smith assert(Target && "Missing target information"); 28691f76c4e8SManuel Klimek const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID); 2870718292f2SDouglas Gregor if (!Buffer) 28714ddf2221SDouglas Gregor return ParsedModuleMap[File] = true; 28728128f332SRichard Smith assert((!Offset || *Offset <= Buffer->getBufferSize()) && 28738128f332SRichard Smith "invalid buffer offset"); 2874718292f2SDouglas Gregor 2875718292f2SDouglas Gregor // Parse this module map file. 28768128f332SRichard Smith Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts, 28778128f332SRichard Smith Buffer->getBufferStart(), 28788128f332SRichard Smith Buffer->getBufferStart() + (Offset ? *Offset : 0), 28798128f332SRichard Smith Buffer->getBufferEnd()); 28802a6edb30SRichard Smith SourceLocation Start = L.getSourceLocation(); 2881beee15e7SBen Langmuir ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir, 2882*8587dfd9SBruno Cardoso Lopes IsSystem, IsExplicitlyProvided); 2883718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 28844ddf2221SDouglas Gregor ParsedModuleMap[File] = Result; 28852a6edb30SRichard Smith 28868128f332SRichard Smith if (Offset) { 28878128f332SRichard Smith auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation()); 28888128f332SRichard Smith assert(Loc.first == ID && "stopped in a different file?"); 28898128f332SRichard Smith *Offset = Loc.second; 28908128f332SRichard Smith } 28918128f332SRichard Smith 28922a6edb30SRichard Smith // Notify callbacks that we parsed it. 28932a6edb30SRichard Smith for (const auto &Cb : Callbacks) 28942a6edb30SRichard Smith Cb->moduleMapFileRead(Start, *File, IsSystem); 2895*8587dfd9SBruno Cardoso Lopes 2896718292f2SDouglas Gregor return Result; 2897718292f2SDouglas Gregor } 2898