1718292f2SDouglas Gregor //===--- ModuleMap.cpp - Describe the layout of modules ---------*- C++ -*-===// 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 //===----------------------------------------------------------------------===// 14718292f2SDouglas Gregor #include "clang/Lex/ModuleMap.h" 15a7d03840SJordan Rose #include "clang/Basic/CharInfo.h" 16718292f2SDouglas Gregor #include "clang/Basic/Diagnostic.h" 17811db4eaSDouglas Gregor #include "clang/Basic/DiagnosticOptions.h" 18718292f2SDouglas Gregor #include "clang/Basic/FileManager.h" 19718292f2SDouglas Gregor #include "clang/Basic/TargetInfo.h" 20718292f2SDouglas Gregor #include "clang/Basic/TargetOptions.h" 21b146baabSArgyrios Kyrtzidis #include "clang/Lex/HeaderSearch.h" 229acb99e3SRichard Smith #include "clang/Lex/HeaderSearchOptions.h" 233a02247dSChandler Carruth #include "clang/Lex/LexDiagnostic.h" 243a02247dSChandler Carruth #include "clang/Lex/Lexer.h" 253a02247dSChandler Carruth #include "clang/Lex/LiteralSupport.h" 263a02247dSChandler Carruth #include "llvm/ADT/StringRef.h" 273a02247dSChandler Carruth #include "llvm/ADT/StringSwitch.h" 28718292f2SDouglas Gregor #include "llvm/Support/Allocator.h" 29e89dbc1dSDouglas Gregor #include "llvm/Support/FileSystem.h" 30718292f2SDouglas Gregor #include "llvm/Support/Host.h" 31552c169eSRafael Espindola #include "llvm/Support/Path.h" 32718292f2SDouglas Gregor #include "llvm/Support/raw_ostream.h" 3307c22b78SDouglas Gregor #include <stdlib.h> 3401c7cfa2SDouglas Gregor #if defined(LLVM_ON_UNIX) 35eadae014SDmitri Gribenko #include <limits.h> 3601c7cfa2SDouglas Gregor #endif 37718292f2SDouglas Gregor using namespace clang; 38718292f2SDouglas Gregor 39040e1266SRichard Smith Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) { 40040e1266SRichard Smith switch ((int)Role) { 41040e1266SRichard Smith default: llvm_unreachable("unknown header role"); 42040e1266SRichard Smith case NormalHeader: 43040e1266SRichard Smith return Module::HK_Normal; 44040e1266SRichard Smith case PrivateHeader: 45040e1266SRichard Smith return Module::HK_Private; 46040e1266SRichard Smith case TextualHeader: 47040e1266SRichard Smith return Module::HK_Textual; 48040e1266SRichard Smith case PrivateHeader | TextualHeader: 49040e1266SRichard Smith return Module::HK_PrivateTextual; 50040e1266SRichard Smith } 51040e1266SRichard Smith } 52040e1266SRichard Smith 53040e1266SRichard Smith ModuleMap::ModuleHeaderRole 54040e1266SRichard Smith ModuleMap::headerKindToRole(Module::HeaderKind Kind) { 55040e1266SRichard Smith switch ((int)Kind) { 56040e1266SRichard Smith case Module::HK_Normal: 57040e1266SRichard Smith return NormalHeader; 58040e1266SRichard Smith case Module::HK_Private: 59040e1266SRichard Smith return PrivateHeader; 60040e1266SRichard Smith case Module::HK_Textual: 61040e1266SRichard Smith return TextualHeader; 62040e1266SRichard Smith case Module::HK_PrivateTextual: 63040e1266SRichard Smith return ModuleHeaderRole(PrivateHeader | TextualHeader); 64040e1266SRichard Smith case Module::HK_Excluded: 65040e1266SRichard Smith llvm_unreachable("unexpected header kind"); 66040e1266SRichard Smith } 67040e1266SRichard Smith llvm_unreachable("unknown header kind"); 68040e1266SRichard Smith } 69040e1266SRichard Smith 702b82c2a5SDouglas Gregor Module::ExportDecl 712b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod, 722b82c2a5SDouglas Gregor const Module::UnresolvedExportDecl &Unresolved, 73e4412640SArgyrios Kyrtzidis bool Complain) const { 74f5eedd05SDouglas Gregor // We may have just a wildcard. 75f5eedd05SDouglas Gregor if (Unresolved.Id.empty()) { 76f5eedd05SDouglas Gregor assert(Unresolved.Wildcard && "Invalid unresolved export"); 77d2d442caSCraig Topper return Module::ExportDecl(nullptr, true); 78f5eedd05SDouglas Gregor } 79f5eedd05SDouglas Gregor 80fb912657SDouglas Gregor // Resolve the module-id. 81fb912657SDouglas Gregor Module *Context = resolveModuleId(Unresolved.Id, Mod, Complain); 82fb912657SDouglas Gregor if (!Context) 83fb912657SDouglas Gregor return Module::ExportDecl(); 84fb912657SDouglas Gregor 85fb912657SDouglas Gregor return Module::ExportDecl(Context, Unresolved.Wildcard); 86fb912657SDouglas Gregor } 87fb912657SDouglas Gregor 88fb912657SDouglas Gregor Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod, 89fb912657SDouglas Gregor bool Complain) const { 902b82c2a5SDouglas Gregor // Find the starting module. 91fb912657SDouglas Gregor Module *Context = lookupModuleUnqualified(Id[0].first, Mod); 922b82c2a5SDouglas Gregor if (!Context) { 932b82c2a5SDouglas Gregor if (Complain) 940761a8a0SDaniel Jasper Diags.Report(Id[0].second, diag::err_mmap_missing_module_unqualified) 95fb912657SDouglas Gregor << Id[0].first << Mod->getFullModuleName(); 962b82c2a5SDouglas Gregor 97d2d442caSCraig Topper return nullptr; 982b82c2a5SDouglas Gregor } 992b82c2a5SDouglas Gregor 1002b82c2a5SDouglas Gregor // Dig into the module path. 101fb912657SDouglas Gregor for (unsigned I = 1, N = Id.size(); I != N; ++I) { 102fb912657SDouglas Gregor Module *Sub = lookupModuleQualified(Id[I].first, Context); 1032b82c2a5SDouglas Gregor if (!Sub) { 1042b82c2a5SDouglas Gregor if (Complain) 1050761a8a0SDaniel Jasper Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified) 106fb912657SDouglas Gregor << Id[I].first << Context->getFullModuleName() 107fb912657SDouglas Gregor << SourceRange(Id[0].second, Id[I-1].second); 1082b82c2a5SDouglas Gregor 109d2d442caSCraig Topper return nullptr; 1102b82c2a5SDouglas Gregor } 1112b82c2a5SDouglas Gregor 1122b82c2a5SDouglas Gregor Context = Sub; 1132b82c2a5SDouglas Gregor } 1142b82c2a5SDouglas Gregor 115fb912657SDouglas Gregor return Context; 1162b82c2a5SDouglas Gregor } 1172b82c2a5SDouglas Gregor 1181d60987fSRichard Smith /// \brief Append to \p Paths the set of paths needed to get to the 1191d60987fSRichard Smith /// subframework in which the given module lives. 1201d60987fSRichard Smith static void appendSubframeworkPaths(Module *Mod, 1211d60987fSRichard Smith SmallVectorImpl<char> &Path) { 1221d60987fSRichard Smith // Collect the framework names from the given module to the top-level module. 1231d60987fSRichard Smith SmallVector<StringRef, 2> Paths; 1241d60987fSRichard Smith for (; Mod; Mod = Mod->Parent) { 1251d60987fSRichard Smith if (Mod->IsFramework) 1261d60987fSRichard Smith Paths.push_back(Mod->Name); 1271d60987fSRichard Smith } 1281d60987fSRichard Smith 1291d60987fSRichard Smith if (Paths.empty()) 1301d60987fSRichard Smith return; 1311d60987fSRichard Smith 1321d60987fSRichard Smith // Add Frameworks/Name.framework for each subframework. 1331d60987fSRichard Smith for (unsigned I = Paths.size() - 1; I != 0; --I) 1341d60987fSRichard Smith llvm::sys::path::append(Path, "Frameworks", Paths[I-1] + ".framework"); 1351d60987fSRichard Smith } 1361d60987fSRichard Smith 1371d60987fSRichard Smith const FileEntry * 138040e1266SRichard Smith ModuleMap::findHeader(Module *M, 139040e1266SRichard Smith const Module::UnresolvedHeaderDirective &Header, 1401d60987fSRichard Smith SmallVectorImpl<char> &RelativePathName) { 141040e1266SRichard Smith auto GetFile = [&](StringRef Filename) -> const FileEntry * { 142040e1266SRichard Smith auto *File = SourceMgr.getFileManager().getFile(Filename); 143040e1266SRichard Smith if (!File || 144040e1266SRichard Smith (Header.Size && File->getSize() != *Header.Size) || 145040e1266SRichard Smith (Header.ModTime && File->getModificationTime() != *Header.ModTime)) 146040e1266SRichard Smith return nullptr; 147040e1266SRichard Smith return File; 148040e1266SRichard Smith }; 149040e1266SRichard Smith 1501d60987fSRichard Smith if (llvm::sys::path::is_absolute(Header.FileName)) { 1511d60987fSRichard Smith RelativePathName.clear(); 1521d60987fSRichard Smith RelativePathName.append(Header.FileName.begin(), Header.FileName.end()); 153040e1266SRichard Smith return GetFile(Header.FileName); 1541d60987fSRichard Smith } 1551d60987fSRichard Smith 1561d60987fSRichard Smith // Search for the header file within the module's home directory. 1571d60987fSRichard Smith auto *Directory = M->Directory; 1581d60987fSRichard Smith SmallString<128> FullPathName(Directory->getName()); 1591d60987fSRichard Smith unsigned FullPathLength = FullPathName.size(); 1601d60987fSRichard Smith 1611d60987fSRichard Smith if (M->isPartOfFramework()) { 1621d60987fSRichard Smith appendSubframeworkPaths(M, RelativePathName); 1631d60987fSRichard Smith unsigned RelativePathLength = RelativePathName.size(); 1641d60987fSRichard Smith 1651d60987fSRichard Smith // Check whether this file is in the public headers. 1661d60987fSRichard Smith llvm::sys::path::append(RelativePathName, "Headers", Header.FileName); 1671d60987fSRichard Smith llvm::sys::path::append(FullPathName, RelativePathName); 168040e1266SRichard Smith if (auto *File = GetFile(FullPathName)) 1691d60987fSRichard Smith return File; 1701d60987fSRichard Smith 1711d60987fSRichard Smith // Check whether this file is in the private headers. 1721d60987fSRichard Smith // Ideally, private modules in the form 'FrameworkName.Private' should 1731d60987fSRichard Smith // be defined as 'module FrameworkName.Private', and not as 1741d60987fSRichard Smith // 'framework module FrameworkName.Private', since a 'Private.Framework' 1751d60987fSRichard Smith // does not usually exist. However, since both are currently widely used 1761d60987fSRichard Smith // for private modules, make sure we find the right path in both cases. 1771d60987fSRichard Smith if (M->IsFramework && M->Name == "Private") 1781d60987fSRichard Smith RelativePathName.clear(); 1791d60987fSRichard Smith else 1801d60987fSRichard Smith RelativePathName.resize(RelativePathLength); 1811d60987fSRichard Smith FullPathName.resize(FullPathLength); 1821d60987fSRichard Smith llvm::sys::path::append(RelativePathName, "PrivateHeaders", 1831d60987fSRichard Smith Header.FileName); 1841d60987fSRichard Smith llvm::sys::path::append(FullPathName, RelativePathName); 185040e1266SRichard Smith return GetFile(FullPathName); 1861d60987fSRichard Smith } 1871d60987fSRichard Smith 1881d60987fSRichard Smith // Lookup for normal headers. 1891d60987fSRichard Smith llvm::sys::path::append(RelativePathName, Header.FileName); 1901d60987fSRichard Smith llvm::sys::path::append(FullPathName, RelativePathName); 191040e1266SRichard Smith return GetFile(FullPathName); 1921d60987fSRichard Smith } 1931d60987fSRichard Smith 194040e1266SRichard Smith void ModuleMap::resolveHeader(Module *Mod, 195040e1266SRichard Smith const Module::UnresolvedHeaderDirective &Header) { 196040e1266SRichard Smith SmallString<128> RelativePathName; 197040e1266SRichard Smith if (const FileEntry *File = findHeader(Mod, Header, RelativePathName)) { 198040e1266SRichard Smith if (Header.IsUmbrella) { 199040e1266SRichard Smith const DirectoryEntry *UmbrellaDir = File->getDir(); 200040e1266SRichard Smith if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir]) 201040e1266SRichard Smith Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) 202040e1266SRichard Smith << UmbrellaMod->getFullModuleName(); 203040e1266SRichard Smith else 204040e1266SRichard Smith // Record this umbrella header. 205040e1266SRichard Smith setUmbrellaHeader(Mod, File, RelativePathName.str()); 206040e1266SRichard Smith } else { 207040e1266SRichard Smith Module::Header H = {RelativePathName.str(), File}; 208040e1266SRichard Smith if (Header.Kind == Module::HK_Excluded) 209040e1266SRichard Smith excludeHeader(Mod, H); 210040e1266SRichard Smith else 211040e1266SRichard Smith addHeader(Mod, H, headerKindToRole(Header.Kind)); 212040e1266SRichard Smith } 213040e1266SRichard Smith } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) { 214040e1266SRichard Smith // There's a builtin header but no corresponding on-disk header. Assume 215040e1266SRichard Smith // this was supposed to modularize the builtin header alone. 216040e1266SRichard Smith } else if (Header.Kind == Module::HK_Excluded) { 217040e1266SRichard Smith // Ignore missing excluded header files. They're optional anyway. 218040e1266SRichard Smith } else { 219040e1266SRichard Smith // If we find a module that has a missing header, we mark this module as 220040e1266SRichard Smith // unavailable and store the header directive for displaying diagnostics. 221040e1266SRichard Smith Mod->MissingHeaders.push_back(Header); 222040e1266SRichard Smith // A missing header with stat information doesn't make the module 223040e1266SRichard Smith // unavailable; this keeps our behavior consistent as headers are lazily 224040e1266SRichard Smith // resolved. (Such a module still can't be built though, except from 225040e1266SRichard Smith // preprocessed source.) 226040e1266SRichard Smith if (!Header.Size && !Header.ModTime) 227040e1266SRichard Smith Mod->markUnavailable(); 228040e1266SRichard Smith } 229040e1266SRichard Smith } 230040e1266SRichard Smith 231040e1266SRichard Smith bool ModuleMap::resolveAsBuiltinHeader( 232040e1266SRichard Smith Module *Mod, const Module::UnresolvedHeaderDirective &Header) { 233040e1266SRichard Smith if (Header.Kind == Module::HK_Excluded || 234040e1266SRichard Smith llvm::sys::path::is_absolute(Header.FileName) || 235040e1266SRichard Smith Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella || 236040e1266SRichard Smith !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory || 237040e1266SRichard Smith !isBuiltinHeader(Header.FileName)) 238040e1266SRichard Smith return false; 2391d60987fSRichard Smith 2401d60987fSRichard Smith // This is a system module with a top-level header. This header 2411d60987fSRichard Smith // may have a counterpart (or replacement) in the set of headers 2421d60987fSRichard Smith // supplied by Clang. Find that builtin header. 243040e1266SRichard Smith SmallString<128> Path; 244040e1266SRichard Smith llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName); 245040e1266SRichard Smith auto *File = SourceMgr.getFileManager().getFile(Path); 246040e1266SRichard Smith if (!File) 247040e1266SRichard Smith return false; 248040e1266SRichard Smith 249040e1266SRichard Smith auto Role = headerKindToRole(Header.Kind); 250040e1266SRichard Smith Module::Header H = {Path.str(), File}; 251040e1266SRichard Smith addHeader(Mod, H, Role); 252040e1266SRichard Smith return true; 2531d60987fSRichard Smith } 2541d60987fSRichard Smith 2550761a8a0SDaniel Jasper ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags, 256b146baabSArgyrios Kyrtzidis const LangOptions &LangOpts, const TargetInfo *Target, 257b146baabSArgyrios Kyrtzidis HeaderSearch &HeaderInfo) 2580761a8a0SDaniel Jasper : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target), 259056bf77fSRichard Smith HeaderInfo(HeaderInfo) { 2600414b857SRichard Smith MMapLangOpts.LineComment = true; 2610414b857SRichard Smith } 262718292f2SDouglas Gregor 263718292f2SDouglas Gregor ModuleMap::~ModuleMap() { 26421668754SDavide Italiano for (auto &M : Modules) 26521668754SDavide Italiano delete M.getValue(); 266718292f2SDouglas Gregor } 267718292f2SDouglas Gregor 26889929282SDouglas Gregor void ModuleMap::setTarget(const TargetInfo &Target) { 26989929282SDouglas Gregor assert((!this->Target || this->Target == &Target) && 27089929282SDouglas Gregor "Improper target override"); 27189929282SDouglas Gregor this->Target = &Target; 27289929282SDouglas Gregor } 27389929282SDouglas Gregor 274056396aeSDouglas Gregor /// \brief "Sanitize" a filename so that it can be used as an identifier. 275056396aeSDouglas Gregor static StringRef sanitizeFilenameAsIdentifier(StringRef Name, 276056396aeSDouglas Gregor SmallVectorImpl<char> &Buffer) { 277056396aeSDouglas Gregor if (Name.empty()) 278056396aeSDouglas Gregor return Name; 279056396aeSDouglas Gregor 280a7d03840SJordan Rose if (!isValidIdentifier(Name)) { 281056396aeSDouglas Gregor // If we don't already have something with the form of an identifier, 282056396aeSDouglas Gregor // create a buffer with the sanitized name. 283056396aeSDouglas Gregor Buffer.clear(); 284a7d03840SJordan Rose if (isDigit(Name[0])) 285056396aeSDouglas Gregor Buffer.push_back('_'); 286056396aeSDouglas Gregor Buffer.reserve(Buffer.size() + Name.size()); 287056396aeSDouglas Gregor for (unsigned I = 0, N = Name.size(); I != N; ++I) { 288a7d03840SJordan Rose if (isIdentifierBody(Name[I])) 289056396aeSDouglas Gregor Buffer.push_back(Name[I]); 290056396aeSDouglas Gregor else 291056396aeSDouglas Gregor Buffer.push_back('_'); 292056396aeSDouglas Gregor } 293056396aeSDouglas Gregor 294056396aeSDouglas Gregor Name = StringRef(Buffer.data(), Buffer.size()); 295056396aeSDouglas Gregor } 296056396aeSDouglas Gregor 297056396aeSDouglas Gregor while (llvm::StringSwitch<bool>(Name) 298056396aeSDouglas Gregor #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true) 299056396aeSDouglas Gregor #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true) 300056396aeSDouglas Gregor #include "clang/Basic/TokenKinds.def" 301056396aeSDouglas Gregor .Default(false)) { 302056396aeSDouglas Gregor if (Name.data() != Buffer.data()) 303056396aeSDouglas Gregor Buffer.append(Name.begin(), Name.end()); 304056396aeSDouglas Gregor Buffer.push_back('_'); 305056396aeSDouglas Gregor Name = StringRef(Buffer.data(), Buffer.size()); 306056396aeSDouglas Gregor } 307056396aeSDouglas Gregor 308056396aeSDouglas Gregor return Name; 309056396aeSDouglas Gregor } 310056396aeSDouglas Gregor 31134d52749SDouglas Gregor /// \brief Determine whether the given file name is the name of a builtin 31234d52749SDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system 31334d52749SDouglas Gregor /// headers. 314ba1b5c98SBruno Cardoso Lopes bool ModuleMap::isBuiltinHeader(StringRef FileName) { 31534d52749SDouglas Gregor return llvm::StringSwitch<bool>(FileName) 31634d52749SDouglas Gregor .Case("float.h", true) 31734d52749SDouglas Gregor .Case("iso646.h", true) 31834d52749SDouglas Gregor .Case("limits.h", true) 31934d52749SDouglas Gregor .Case("stdalign.h", true) 32034d52749SDouglas Gregor .Case("stdarg.h", true) 3213c4b1290SBen Langmuir .Case("stdatomic.h", true) 32234d52749SDouglas Gregor .Case("stdbool.h", true) 32334d52749SDouglas Gregor .Case("stddef.h", true) 32434d52749SDouglas Gregor .Case("stdint.h", true) 32534d52749SDouglas Gregor .Case("tgmath.h", true) 32634d52749SDouglas Gregor .Case("unwind.h", true) 32734d52749SDouglas Gregor .Default(false); 32834d52749SDouglas Gregor } 32934d52749SDouglas Gregor 33092669ee4SDaniel Jasper ModuleMap::HeadersMap::iterator 33192669ee4SDaniel Jasper ModuleMap::findKnownHeader(const FileEntry *File) { 332040e1266SRichard Smith resolveHeaderDirectives(File); 33359527666SDouglas Gregor HeadersMap::iterator Known = Headers.find(File); 33447972afdSRichard Smith if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && 33547972afdSRichard Smith Known == Headers.end() && File->getDir() == BuiltinIncludeDir && 336ba1b5c98SBruno Cardoso Lopes ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()))) { 3374eaf0a6cSDaniel Jasper HeaderInfo.loadTopLevelSystemModules(); 33892669ee4SDaniel Jasper return Headers.find(File); 3394eaf0a6cSDaniel Jasper } 34092669ee4SDaniel Jasper return Known; 34192669ee4SDaniel Jasper } 34292669ee4SDaniel Jasper 3434469138eSBen Langmuir ModuleMap::KnownHeader 3444469138eSBen Langmuir ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File, 3454469138eSBen Langmuir SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) { 34647972afdSRichard Smith if (UmbrellaDirs.empty()) 34747972afdSRichard Smith return KnownHeader(); 34847972afdSRichard Smith 3494469138eSBen Langmuir const DirectoryEntry *Dir = File->getDir(); 3504469138eSBen Langmuir assert(Dir && "file in no directory"); 3514469138eSBen Langmuir 3524469138eSBen Langmuir // Note: as an egregious but useful hack we use the real path here, because 3534469138eSBen Langmuir // frameworks moving from top-level frameworks to embedded frameworks tend 3544469138eSBen Langmuir // to be symlinked from the top-level location to the embedded location, 3554469138eSBen Langmuir // and we need to resolve lookups as if we had found the embedded location. 3564469138eSBen Langmuir StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir); 3574469138eSBen Langmuir 3584469138eSBen Langmuir // Keep walking up the directory hierarchy, looking for a directory with 3594469138eSBen Langmuir // an umbrella header. 3604469138eSBen Langmuir do { 3614469138eSBen Langmuir auto KnownDir = UmbrellaDirs.find(Dir); 3624469138eSBen Langmuir if (KnownDir != UmbrellaDirs.end()) 3634469138eSBen Langmuir return KnownHeader(KnownDir->second, NormalHeader); 3644469138eSBen Langmuir 3654469138eSBen Langmuir IntermediateDirs.push_back(Dir); 3664469138eSBen Langmuir 3674469138eSBen Langmuir // Retrieve our parent path. 3684469138eSBen Langmuir DirName = llvm::sys::path::parent_path(DirName); 3694469138eSBen Langmuir if (DirName.empty()) 3704469138eSBen Langmuir break; 3714469138eSBen Langmuir 3724469138eSBen Langmuir // Resolve the parent path to a directory entry. 3734469138eSBen Langmuir Dir = SourceMgr.getFileManager().getDirectory(DirName); 3744469138eSBen Langmuir } while (Dir); 3754469138eSBen Langmuir return KnownHeader(); 3764469138eSBen Langmuir } 3774469138eSBen Langmuir 37892669ee4SDaniel Jasper static bool violatesPrivateInclude(Module *RequestingModule, 37992669ee4SDaniel Jasper const FileEntry *IncFileEnt, 3804eb8393cSRichard Smith ModuleMap::KnownHeader Header) { 38192669ee4SDaniel Jasper #ifndef NDEBUG 3824eb8393cSRichard Smith if (Header.getRole() & ModuleMap::PrivateHeader) { 38392669ee4SDaniel Jasper // Check for consistency between the module header role 38492669ee4SDaniel Jasper // as obtained from the lookup and as obtained from the module. 38592669ee4SDaniel Jasper // This check is not cheap, so enable it only for debugging. 3862708e520SRichard Smith bool IsPrivate = false; 3872708e520SRichard Smith SmallVectorImpl<Module::Header> *HeaderList[] = { 3884eb8393cSRichard Smith &Header.getModule()->Headers[Module::HK_Private], 3894eb8393cSRichard Smith &Header.getModule()->Headers[Module::HK_PrivateTextual]}; 3902708e520SRichard Smith for (auto *Hs : HeaderList) 3912708e520SRichard Smith IsPrivate |= 3922708e520SRichard Smith std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) { 3933c1a41adSRichard Smith return H.Entry == IncFileEnt; 3942708e520SRichard Smith }) != Hs->end(); 3954eb8393cSRichard Smith assert(IsPrivate && "inconsistent headers and roles"); 39600bc95ecSRichard Smith } 39792669ee4SDaniel Jasper #endif 3984eb8393cSRichard Smith return !Header.isAccessibleFrom(RequestingModule); 39992669ee4SDaniel Jasper } 40092669ee4SDaniel Jasper 40171e1a64fSBen Langmuir static Module *getTopLevelOrNull(Module *M) { 40271e1a64fSBen Langmuir return M ? M->getTopLevelModule() : nullptr; 40371e1a64fSBen Langmuir } 40471e1a64fSBen Langmuir 40592669ee4SDaniel Jasper void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, 4068d4e90b3SRichard Smith bool RequestingModuleIsModuleInterface, 40792669ee4SDaniel Jasper SourceLocation FilenameLoc, 40892669ee4SDaniel Jasper StringRef Filename, 40992669ee4SDaniel Jasper const FileEntry *File) { 41092669ee4SDaniel Jasper // No errors for indirect modules. This may be a bit of a problem for modules 41192669ee4SDaniel Jasper // with no source files. 41271e1a64fSBen Langmuir if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule)) 41392669ee4SDaniel Jasper return; 41492669ee4SDaniel Jasper 415040e1266SRichard Smith if (RequestingModule) { 41692669ee4SDaniel Jasper resolveUses(RequestingModule, /*Complain=*/false); 417040e1266SRichard Smith resolveHeaderDirectives(RequestingModule); 418040e1266SRichard Smith } 41992669ee4SDaniel Jasper 42071e1a64fSBen Langmuir bool Excluded = false; 421d2d442caSCraig Topper Module *Private = nullptr; 422d2d442caSCraig Topper Module *NotUsed = nullptr; 42371e1a64fSBen Langmuir 42471e1a64fSBen Langmuir HeadersMap::iterator Known = findKnownHeader(File); 42571e1a64fSBen Langmuir if (Known != Headers.end()) { 42671e1a64fSBen Langmuir for (const KnownHeader &Header : Known->second) { 42792669ee4SDaniel Jasper // Remember private headers for later printing of a diagnostic. 4284eb8393cSRichard Smith if (violatesPrivateInclude(RequestingModule, File, Header)) { 42971e1a64fSBen Langmuir Private = Header.getModule(); 43092669ee4SDaniel Jasper continue; 43192669ee4SDaniel Jasper } 43292669ee4SDaniel Jasper 43392669ee4SDaniel Jasper // If uses need to be specified explicitly, we are only allowed to return 43492669ee4SDaniel Jasper // modules that are explicitly used by the requesting module. 43592669ee4SDaniel Jasper if (RequestingModule && LangOpts.ModulesDeclUse && 4368f4d3ff1SRichard Smith !RequestingModule->directlyUses(Header.getModule())) { 43771e1a64fSBen Langmuir NotUsed = Header.getModule(); 43892669ee4SDaniel Jasper continue; 43992669ee4SDaniel Jasper } 44092669ee4SDaniel Jasper 44192669ee4SDaniel Jasper // We have found a module that we can happily use. 44292669ee4SDaniel Jasper return; 44392669ee4SDaniel Jasper } 444feb54b6dSRichard Smith 445feb54b6dSRichard Smith Excluded = true; 44671e1a64fSBen Langmuir } 44792669ee4SDaniel Jasper 44892669ee4SDaniel Jasper // We have found a header, but it is private. 449d2d442caSCraig Topper if (Private) { 45011152dd5SRichard Smith Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module) 45192669ee4SDaniel Jasper << Filename; 45292669ee4SDaniel Jasper return; 45392669ee4SDaniel Jasper } 45492669ee4SDaniel Jasper 45592669ee4SDaniel Jasper // We have found a module, but we don't use it. 456d2d442caSCraig Topper if (NotUsed) { 45711152dd5SRichard Smith Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) 45892669ee4SDaniel Jasper << RequestingModule->getFullModuleName() << Filename; 45992669ee4SDaniel Jasper return; 46092669ee4SDaniel Jasper } 46192669ee4SDaniel Jasper 46271e1a64fSBen Langmuir if (Excluded || isHeaderInUmbrellaDirs(File)) 46371e1a64fSBen Langmuir return; 46471e1a64fSBen Langmuir 46571e1a64fSBen Langmuir // At this point, only non-modular includes remain. 46671e1a64fSBen Langmuir 46771e1a64fSBen Langmuir if (LangOpts.ModulesStrictDeclUse) { 46811152dd5SRichard Smith Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) 46971e1a64fSBen Langmuir << RequestingModule->getFullModuleName() << Filename; 470a67e4d32SManman Ren } else if (RequestingModule && RequestingModuleIsModuleInterface && 471a67e4d32SManman Ren LangOpts.isCompilingModule()) { 472a67e4d32SManman Ren // Do not diagnose when we are not compiling a module. 47371e1a64fSBen Langmuir diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ? 47471e1a64fSBen Langmuir diag::warn_non_modular_include_in_framework_module : 47571e1a64fSBen Langmuir diag::warn_non_modular_include_in_module; 47670a7738fSManman Ren Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName() 47770a7738fSManman Ren << File->getName(); 47871e1a64fSBen Langmuir } 47992669ee4SDaniel Jasper } 48092669ee4SDaniel Jasper 481ec87a50aSRichard Smith static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New, 482ec87a50aSRichard Smith const ModuleMap::KnownHeader &Old) { 4838b7c0398SSean Silva // Prefer available modules. 4848b7c0398SSean Silva if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable()) 4858b7c0398SSean Silva return true; 4868b7c0398SSean Silva 487ec87a50aSRichard Smith // Prefer a public header over a private header. 488ec87a50aSRichard Smith if ((New.getRole() & ModuleMap::PrivateHeader) != 489ec87a50aSRichard Smith (Old.getRole() & ModuleMap::PrivateHeader)) 490ec87a50aSRichard Smith return !(New.getRole() & ModuleMap::PrivateHeader); 491ec87a50aSRichard Smith 492ec87a50aSRichard Smith // Prefer a non-textual header over a textual header. 493ec87a50aSRichard Smith if ((New.getRole() & ModuleMap::TextualHeader) != 494ec87a50aSRichard Smith (Old.getRole() & ModuleMap::TextualHeader)) 495ec87a50aSRichard Smith return !(New.getRole() & ModuleMap::TextualHeader); 496ec87a50aSRichard Smith 497ec87a50aSRichard Smith // Don't have a reason to choose between these. Just keep the first one. 498ec87a50aSRichard Smith return false; 499ec87a50aSRichard Smith } 500ec87a50aSRichard Smith 501ed84df00SBruno Cardoso Lopes ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File, 502ed84df00SBruno Cardoso Lopes bool AllowTextual) { 503306d8920SRichard Smith auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader { 504ed84df00SBruno Cardoso Lopes if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader) 505306d8920SRichard Smith return ModuleMap::KnownHeader(); 506306d8920SRichard Smith return R; 507306d8920SRichard Smith }; 508306d8920SRichard Smith 5094881e8b2SSean Silva HeadersMap::iterator Known = findKnownHeader(File); 5101fb5c3a6SDouglas Gregor if (Known != Headers.end()) { 511202210b3SRichard Smith ModuleMap::KnownHeader Result; 51297da9178SDaniel Jasper // Iterate over all modules that 'File' is part of to find the best fit. 5134881e8b2SSean Silva for (KnownHeader &H : Known->second) { 5147e82e019SRichard Smith // Prefer a header from the source module over all others. 5157e82e019SRichard Smith if (H.getModule()->getTopLevelModule() == SourceModule) 5162f633e7cSRichard Smith return MakeResult(H); 5174881e8b2SSean Silva if (!Result || isBetterKnownHeader(H, Result)) 5184881e8b2SSean Silva Result = H; 51997da9178SDaniel Jasper } 520306d8920SRichard Smith return MakeResult(Result); 5211fb5c3a6SDouglas Gregor } 522ab0c8a84SDouglas Gregor 523386bb073SRichard Smith return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File)); 524386bb073SRichard Smith } 525386bb073SRichard Smith 526386bb073SRichard Smith ModuleMap::KnownHeader 527386bb073SRichard Smith ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) { 528386bb073SRichard Smith assert(!Headers.count(File) && "already have a module for this header"); 529386bb073SRichard Smith 530f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs; 5314469138eSBen Langmuir KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs); 5324469138eSBen Langmuir if (H) { 5334469138eSBen Langmuir Module *Result = H.getModule(); 534930a85ccSDouglas Gregor 535930a85ccSDouglas Gregor // Search up the module stack until we find a module with an umbrella 53673141fa9SDouglas Gregor // directory. 537930a85ccSDouglas Gregor Module *UmbrellaModule = Result; 53873141fa9SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 539930a85ccSDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 540930a85ccSDouglas Gregor 541930a85ccSDouglas Gregor if (UmbrellaModule->InferSubmodules) { 5429d6448b1SBen Langmuir const FileEntry *UmbrellaModuleMap = 5439d6448b1SBen Langmuir getModuleMapFileForUniquing(UmbrellaModule); 5449d6448b1SBen Langmuir 545a89c5ac4SDouglas Gregor // Infer submodules for each of the directories we found between 546a89c5ac4SDouglas Gregor // the directory of the umbrella header and the directory where 547a89c5ac4SDouglas Gregor // the actual header is located. 5489458f82dSDouglas Gregor bool Explicit = UmbrellaModule->InferExplicitSubmodules; 5499458f82dSDouglas Gregor 5507033127bSDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 551a89c5ac4SDouglas Gregor // Find or create the module that corresponds to this directory name. 552056396aeSDouglas Gregor SmallString<32> NameBuf; 553056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 5544469138eSBen Langmuir llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf); 5559d6448b1SBen Langmuir Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 5569d6448b1SBen Langmuir Explicit).first; 5579d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = UmbrellaModuleMap; 558ffbafa2aSBen Langmuir Result->IsInferred = true; 559a89c5ac4SDouglas Gregor 560a89c5ac4SDouglas Gregor // Associate the module and the directory. 561a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I-1]] = Result; 562a89c5ac4SDouglas Gregor 563a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 564a89c5ac4SDouglas Gregor // wildcard to the set of exports. 565930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 566d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 567a89c5ac4SDouglas Gregor } 568a89c5ac4SDouglas Gregor 569a89c5ac4SDouglas Gregor // Infer a submodule with the same name as this header file. 570056396aeSDouglas Gregor SmallString<32> NameBuf; 571056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 572056396aeSDouglas Gregor llvm::sys::path::stem(File->getName()), NameBuf); 5739d6448b1SBen Langmuir Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 5749d6448b1SBen Langmuir Explicit).first; 5759d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = UmbrellaModuleMap; 576ffbafa2aSBen Langmuir Result->IsInferred = true; 5773c5305c1SArgyrios Kyrtzidis Result->addTopHeader(File); 578a89c5ac4SDouglas Gregor 579a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 580a89c5ac4SDouglas Gregor // wildcard to the set of exports. 581930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 582d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 583a89c5ac4SDouglas Gregor } else { 584a89c5ac4SDouglas Gregor // Record each of the directories we stepped through as being part of 585a89c5ac4SDouglas Gregor // the module we found, since the umbrella header covers them all. 586a89c5ac4SDouglas Gregor for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I) 587a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I]] = Result; 588a89c5ac4SDouglas Gregor } 589a89c5ac4SDouglas Gregor 590386bb073SRichard Smith KnownHeader Header(Result, NormalHeader); 591386bb073SRichard Smith Headers[File].push_back(Header); 592386bb073SRichard Smith return Header; 593a89c5ac4SDouglas Gregor } 594a89c5ac4SDouglas Gregor 595b53e5483SLawrence Crowl return KnownHeader(); 596ab0c8a84SDouglas Gregor } 597ab0c8a84SDouglas Gregor 598386bb073SRichard Smith ArrayRef<ModuleMap::KnownHeader> 599386bb073SRichard Smith ModuleMap::findAllModulesForHeader(const FileEntry *File) const { 600040e1266SRichard Smith resolveHeaderDirectives(File); 601386bb073SRichard Smith auto It = Headers.find(File); 602386bb073SRichard Smith if (It == Headers.end()) 603386bb073SRichard Smith return None; 604386bb073SRichard Smith return It->second; 605386bb073SRichard Smith } 606386bb073SRichard Smith 607e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const { 608d2d442caSCraig Topper return isHeaderUnavailableInModule(Header, nullptr); 60950996ce1SRichard Smith } 61050996ce1SRichard Smith 61162bcd925SDmitri Gribenko bool 61262bcd925SDmitri Gribenko ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, 61362bcd925SDmitri Gribenko const Module *RequestingModule) const { 614040e1266SRichard Smith resolveHeaderDirectives(Header); 615e4412640SArgyrios Kyrtzidis HeadersMap::const_iterator Known = Headers.find(Header); 61697da9178SDaniel Jasper if (Known != Headers.end()) { 61797da9178SDaniel Jasper for (SmallVectorImpl<KnownHeader>::const_iterator 61897da9178SDaniel Jasper I = Known->second.begin(), 61997da9178SDaniel Jasper E = Known->second.end(); 62097da9178SDaniel Jasper I != E; ++I) { 621052d95a6SBruno Cardoso Lopes 622052d95a6SBruno Cardoso Lopes if (I->isAvailable() && 623052d95a6SBruno Cardoso Lopes (!RequestingModule || 624052d95a6SBruno Cardoso Lopes I->getModule()->isSubModuleOf(RequestingModule))) { 625052d95a6SBruno Cardoso Lopes // When no requesting module is available, the caller is looking if a 626052d95a6SBruno Cardoso Lopes // header is part a module by only looking into the module map. This is 627052d95a6SBruno Cardoso Lopes // done by warn_uncovered_module_header checks; don't consider textual 628052d95a6SBruno Cardoso Lopes // headers part of it in this mode, otherwise we get misleading warnings 629052d95a6SBruno Cardoso Lopes // that a umbrella header is not including a textual header. 630052d95a6SBruno Cardoso Lopes if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader) 631052d95a6SBruno Cardoso Lopes continue; 63297da9178SDaniel Jasper return false; 63397da9178SDaniel Jasper } 634052d95a6SBruno Cardoso Lopes } 63597da9178SDaniel Jasper return true; 63697da9178SDaniel Jasper } 6371fb5c3a6SDouglas Gregor 6381fb5c3a6SDouglas Gregor const DirectoryEntry *Dir = Header->getDir(); 639f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs; 6401fb5c3a6SDouglas Gregor StringRef DirName = Dir->getName(); 6411fb5c3a6SDouglas Gregor 64250996ce1SRichard Smith auto IsUnavailable = [&](const Module *M) { 64350996ce1SRichard Smith return !M->isAvailable() && (!RequestingModule || 64450996ce1SRichard Smith M->isSubModuleOf(RequestingModule)); 64550996ce1SRichard Smith }; 64650996ce1SRichard Smith 6471fb5c3a6SDouglas Gregor // Keep walking up the directory hierarchy, looking for a directory with 6481fb5c3a6SDouglas Gregor // an umbrella header. 6491fb5c3a6SDouglas Gregor do { 650e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir 6511fb5c3a6SDouglas Gregor = UmbrellaDirs.find(Dir); 6521fb5c3a6SDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 6531fb5c3a6SDouglas Gregor Module *Found = KnownDir->second; 65450996ce1SRichard Smith if (IsUnavailable(Found)) 6551fb5c3a6SDouglas Gregor return true; 6561fb5c3a6SDouglas Gregor 6571fb5c3a6SDouglas Gregor // Search up the module stack until we find a module with an umbrella 6581fb5c3a6SDouglas Gregor // directory. 6591fb5c3a6SDouglas Gregor Module *UmbrellaModule = Found; 6601fb5c3a6SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 6611fb5c3a6SDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 6621fb5c3a6SDouglas Gregor 6631fb5c3a6SDouglas Gregor if (UmbrellaModule->InferSubmodules) { 6641fb5c3a6SDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 6651fb5c3a6SDouglas Gregor // Find or create the module that corresponds to this directory name. 666056396aeSDouglas Gregor SmallString<32> NameBuf; 667056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 668056396aeSDouglas Gregor llvm::sys::path::stem(SkippedDirs[I-1]->getName()), 669056396aeSDouglas Gregor NameBuf); 6701fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 6711fb5c3a6SDouglas Gregor if (!Found) 6721fb5c3a6SDouglas Gregor return false; 67350996ce1SRichard Smith if (IsUnavailable(Found)) 6741fb5c3a6SDouglas Gregor return true; 6751fb5c3a6SDouglas Gregor } 6761fb5c3a6SDouglas Gregor 6771fb5c3a6SDouglas Gregor // Infer a submodule with the same name as this header file. 678056396aeSDouglas Gregor SmallString<32> NameBuf; 679056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 680056396aeSDouglas Gregor llvm::sys::path::stem(Header->getName()), 681056396aeSDouglas Gregor NameBuf); 6821fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 6831fb5c3a6SDouglas Gregor if (!Found) 6841fb5c3a6SDouglas Gregor return false; 6851fb5c3a6SDouglas Gregor } 6861fb5c3a6SDouglas Gregor 68750996ce1SRichard Smith return IsUnavailable(Found); 6881fb5c3a6SDouglas Gregor } 6891fb5c3a6SDouglas Gregor 6901fb5c3a6SDouglas Gregor SkippedDirs.push_back(Dir); 6911fb5c3a6SDouglas Gregor 6921fb5c3a6SDouglas Gregor // Retrieve our parent path. 6931fb5c3a6SDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 6941fb5c3a6SDouglas Gregor if (DirName.empty()) 6951fb5c3a6SDouglas Gregor break; 6961fb5c3a6SDouglas Gregor 6971fb5c3a6SDouglas Gregor // Resolve the parent path to a directory entry. 6981f76c4e8SManuel Klimek Dir = SourceMgr.getFileManager().getDirectory(DirName); 6991fb5c3a6SDouglas Gregor } while (Dir); 7001fb5c3a6SDouglas Gregor 7011fb5c3a6SDouglas Gregor return false; 7021fb5c3a6SDouglas Gregor } 7031fb5c3a6SDouglas Gregor 704e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const { 705e4412640SArgyrios Kyrtzidis llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name); 70688bdfb0eSDouglas Gregor if (Known != Modules.end()) 70788bdfb0eSDouglas Gregor return Known->getValue(); 70888bdfb0eSDouglas Gregor 709d2d442caSCraig Topper return nullptr; 71088bdfb0eSDouglas Gregor } 71188bdfb0eSDouglas Gregor 712e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name, 713e4412640SArgyrios Kyrtzidis Module *Context) const { 7142b82c2a5SDouglas Gregor for(; Context; Context = Context->Parent) { 7152b82c2a5SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Context)) 7162b82c2a5SDouglas Gregor return Sub; 7172b82c2a5SDouglas Gregor } 7182b82c2a5SDouglas Gregor 7192b82c2a5SDouglas Gregor return findModule(Name); 7202b82c2a5SDouglas Gregor } 7212b82c2a5SDouglas Gregor 722e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{ 7232b82c2a5SDouglas Gregor if (!Context) 7242b82c2a5SDouglas Gregor return findModule(Name); 7252b82c2a5SDouglas Gregor 726eb90e830SDouglas Gregor return Context->findSubmodule(Name); 7272b82c2a5SDouglas Gregor } 7282b82c2a5SDouglas Gregor 7299ffe5a35SDavid Blaikie std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name, 7309ffe5a35SDavid Blaikie Module *Parent, 7319ffe5a35SDavid Blaikie bool IsFramework, 73269021974SDouglas Gregor bool IsExplicit) { 73369021974SDouglas Gregor // Try to find an existing module with this name. 734eb90e830SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Parent)) 735eb90e830SDouglas Gregor return std::make_pair(Sub, false); 73669021974SDouglas Gregor 73769021974SDouglas Gregor // Create a new module with this name. 7389ffe5a35SDavid Blaikie Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, 7399ffe5a35SDavid Blaikie IsExplicit, NumCreatedModules++); 7406f722b4eSArgyrios Kyrtzidis if (!Parent) { 7417e82e019SRichard Smith if (LangOpts.CurrentModule == Name) 7427e82e019SRichard Smith SourceModule = Result; 74369021974SDouglas Gregor Modules[Name] = Result; 7446f722b4eSArgyrios Kyrtzidis } 74569021974SDouglas Gregor return std::make_pair(Result, true); 74669021974SDouglas Gregor } 74769021974SDouglas Gregor 748dd8b5337SRichard Smith Module *ModuleMap::createGlobalModuleForInterfaceUnit(SourceLocation Loc) { 749056bf77fSRichard Smith assert(!PendingGlobalModule && "created multiple global modules"); 750056bf77fSRichard Smith PendingGlobalModule.reset( 751056bf77fSRichard Smith new Module("<global>", Loc, nullptr, /*IsFramework*/ false, 752056bf77fSRichard Smith /*IsExplicit*/ true, NumCreatedModules++)); 753056bf77fSRichard Smith PendingGlobalModule->Kind = Module::GlobalModuleFragment; 754056bf77fSRichard Smith return PendingGlobalModule.get(); 755dd8b5337SRichard Smith } 756dd8b5337SRichard Smith 757bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc, 758dd8b5337SRichard Smith StringRef Name, 759dd8b5337SRichard Smith Module *GlobalModule) { 760bbcc9f04SRichard Smith assert(LangOpts.CurrentModule == Name && "module name mismatch"); 761bbcc9f04SRichard Smith assert(!Modules[Name] && "redefining existing module"); 762bbcc9f04SRichard Smith 763bbcc9f04SRichard Smith auto *Result = 764bbcc9f04SRichard Smith new Module(Name, Loc, nullptr, /*IsFramework*/ false, 765bbcc9f04SRichard Smith /*IsExplicit*/ false, NumCreatedModules++); 766145e15a3SRichard Smith Result->Kind = Module::ModuleInterfaceUnit; 767bbcc9f04SRichard Smith Modules[Name] = SourceModule = Result; 768bbcc9f04SRichard Smith 769dd8b5337SRichard Smith // Reparent the current global module fragment as a submodule of this module. 770056bf77fSRichard Smith assert(GlobalModule == PendingGlobalModule.get() && 771056bf77fSRichard Smith "unexpected global module"); 772dd8b5337SRichard Smith GlobalModule->setParent(Result); 773056bf77fSRichard Smith PendingGlobalModule.release(); // now owned by parent 774dd8b5337SRichard Smith 775bbcc9f04SRichard Smith // Mark the main source file as being within the newly-created module so that 776bbcc9f04SRichard Smith // declarations and macros are properly visibility-restricted to it. 777bbcc9f04SRichard Smith auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()); 778bbcc9f04SRichard Smith assert(MainFile && "no input file for module interface"); 779bbcc9f04SRichard Smith Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader)); 780bbcc9f04SRichard Smith 781bbcc9f04SRichard Smith return Result; 782bbcc9f04SRichard Smith } 783bbcc9f04SRichard Smith 78411dfe6feSDouglas Gregor /// \brief For a framework module, infer the framework against which we 78511dfe6feSDouglas Gregor /// should link. 78611dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir, 78711dfe6feSDouglas Gregor FileManager &FileMgr) { 78811dfe6feSDouglas Gregor assert(Mod->IsFramework && "Can only infer linking for framework modules"); 78911dfe6feSDouglas Gregor assert(!Mod->isSubFramework() && 79011dfe6feSDouglas Gregor "Can only infer linking for top-level frameworks"); 79111dfe6feSDouglas Gregor 79211dfe6feSDouglas Gregor SmallString<128> LibName; 79311dfe6feSDouglas Gregor LibName += FrameworkDir->getName(); 79411dfe6feSDouglas Gregor llvm::sys::path::append(LibName, Mod->Name); 7958aaae5a9SJuergen Ributzka 7968aaae5a9SJuergen Ributzka // The library name of a framework has more than one possible extension since 7978aaae5a9SJuergen Ributzka // the introduction of the text-based dynamic library format. We need to check 7988aaae5a9SJuergen Ributzka // for both before we give up. 7998013e81dSBenjamin Kramer for (const char *extension : {"", ".tbd"}) { 8008aaae5a9SJuergen Ributzka llvm::sys::path::replace_extension(LibName, extension); 80111dfe6feSDouglas Gregor if (FileMgr.getFile(LibName)) { 80211dfe6feSDouglas Gregor Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name, 80311dfe6feSDouglas Gregor /*IsFramework=*/true)); 8048aaae5a9SJuergen Ributzka return; 8058aaae5a9SJuergen Ributzka } 80611dfe6feSDouglas Gregor } 80711dfe6feSDouglas Gregor } 80811dfe6feSDouglas Gregor 809a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 810a525400dSBen Langmuir bool IsSystem, Module *Parent) { 811c1d88ea5SBen Langmuir Attributes Attrs; 812c1d88ea5SBen Langmuir Attrs.IsSystem = IsSystem; 813a525400dSBen Langmuir return inferFrameworkModule(FrameworkDir, Attrs, Parent); 814c1d88ea5SBen Langmuir } 815c1d88ea5SBen Langmuir 816a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 817c1d88ea5SBen Langmuir Attributes Attrs, Module *Parent) { 818a525400dSBen Langmuir // Note: as an egregious but useful hack we use the real path here, because 819a525400dSBen Langmuir // we might be looking at an embedded framework that symlinks out to a 820a525400dSBen Langmuir // top-level framework, and we need to infer as if we were naming the 821a525400dSBen Langmuir // top-level framework. 822a525400dSBen Langmuir StringRef FrameworkDirName = 823a525400dSBen Langmuir SourceMgr.getFileManager().getCanonicalName(FrameworkDir); 824a525400dSBen Langmuir 825a525400dSBen Langmuir // In case this is a case-insensitive filesystem, use the canonical 826a525400dSBen Langmuir // directory name as the ModuleName, since modules are case-sensitive. 827a525400dSBen Langmuir // FIXME: we should be able to give a fix-it hint for the correct spelling. 828a525400dSBen Langmuir SmallString<32> ModuleNameStorage; 829a525400dSBen Langmuir StringRef ModuleName = sanitizeFilenameAsIdentifier( 830a525400dSBen Langmuir llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage); 831c1d88ea5SBen Langmuir 83256c64013SDouglas Gregor // Check whether we've already found this module. 833e89dbc1dSDouglas Gregor if (Module *Mod = lookupModuleQualified(ModuleName, Parent)) 834e89dbc1dSDouglas Gregor return Mod; 835e89dbc1dSDouglas Gregor 8361f76c4e8SManuel Klimek FileManager &FileMgr = SourceMgr.getFileManager(); 83756c64013SDouglas Gregor 8389194a91dSDouglas Gregor // If the framework has a parent path from which we're allowed to infer 8399194a91dSDouglas Gregor // a framework module, do so. 840beee15e7SBen Langmuir const FileEntry *ModuleMapFile = nullptr; 8419194a91dSDouglas Gregor if (!Parent) { 8424ddf2221SDouglas Gregor // Determine whether we're allowed to infer a module map. 8439194a91dSDouglas Gregor bool canInfer = false; 8444ddf2221SDouglas Gregor if (llvm::sys::path::has_parent_path(FrameworkDirName)) { 8459194a91dSDouglas Gregor // Figure out the parent path. 8464ddf2221SDouglas Gregor StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName); 8479194a91dSDouglas Gregor if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) { 8489194a91dSDouglas Gregor // Check whether we have already looked into the parent directory 8499194a91dSDouglas Gregor // for a module map. 850e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator 8519194a91dSDouglas Gregor inferred = InferredDirectories.find(ParentDir); 8529194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) { 8539194a91dSDouglas Gregor // We haven't looked here before. Load a module map, if there is 8549194a91dSDouglas Gregor // one. 855984e1df7SBen Langmuir bool IsFrameworkDir = Parent.endswith(".framework"); 856984e1df7SBen Langmuir if (const FileEntry *ModMapFile = 857984e1df7SBen Langmuir HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) { 858c1d88ea5SBen Langmuir parseModuleMapFile(ModMapFile, Attrs.IsSystem, ParentDir); 8599194a91dSDouglas Gregor inferred = InferredDirectories.find(ParentDir); 8609194a91dSDouglas Gregor } 8619194a91dSDouglas Gregor 8629194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) 8639194a91dSDouglas Gregor inferred = InferredDirectories.insert( 8649194a91dSDouglas Gregor std::make_pair(ParentDir, InferredDirectory())).first; 8659194a91dSDouglas Gregor } 8669194a91dSDouglas Gregor 8679194a91dSDouglas Gregor if (inferred->second.InferModules) { 8689194a91dSDouglas Gregor // We're allowed to infer for this directory, but make sure it's okay 8699194a91dSDouglas Gregor // to infer this particular module. 8704ddf2221SDouglas Gregor StringRef Name = llvm::sys::path::stem(FrameworkDirName); 8719194a91dSDouglas Gregor canInfer = std::find(inferred->second.ExcludedModules.begin(), 8729194a91dSDouglas Gregor inferred->second.ExcludedModules.end(), 8739194a91dSDouglas Gregor Name) == inferred->second.ExcludedModules.end(); 8749194a91dSDouglas Gregor 875c1d88ea5SBen Langmuir Attrs.IsSystem |= inferred->second.Attrs.IsSystem; 876c1d88ea5SBen Langmuir Attrs.IsExternC |= inferred->second.Attrs.IsExternC; 877c1d88ea5SBen Langmuir Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive; 878ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes |= 879ed84df00SBruno Cardoso Lopes inferred->second.Attrs.NoUndeclaredIncludes; 880beee15e7SBen Langmuir ModuleMapFile = inferred->second.ModuleMapFile; 8819194a91dSDouglas Gregor } 8829194a91dSDouglas Gregor } 8839194a91dSDouglas Gregor } 8849194a91dSDouglas Gregor 8859194a91dSDouglas Gregor // If we're not allowed to infer a framework module, don't. 8869194a91dSDouglas Gregor if (!canInfer) 887d2d442caSCraig Topper return nullptr; 888beee15e7SBen Langmuir } else 8899d6448b1SBen Langmuir ModuleMapFile = getModuleMapFileForUniquing(Parent); 8909194a91dSDouglas Gregor 8919194a91dSDouglas Gregor 89256c64013SDouglas Gregor // Look for an umbrella header. 8932c1dd271SDylan Noblesmith SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 89417381a06SBenjamin Kramer llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h"); 895e89dbc1dSDouglas Gregor const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName); 89656c64013SDouglas Gregor 89756c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the 89856c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good 89956c64013SDouglas Gregor // idea. 90056c64013SDouglas Gregor if (!UmbrellaHeader) 901d2d442caSCraig Topper return nullptr; 90256c64013SDouglas Gregor 9039d6448b1SBen Langmuir Module *Result = new Module(ModuleName, SourceLocation(), Parent, 904a7e2cc68SRichard Smith /*IsFramework=*/true, /*IsExplicit=*/false, 905a7e2cc68SRichard Smith NumCreatedModules++); 9069d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = ModuleMapFile; 9079d6448b1SBen Langmuir Result->IsInferred = true; 9087e82e019SRichard Smith if (!Parent) { 9097e82e019SRichard Smith if (LangOpts.CurrentModule == ModuleName) 910ba7f2f71SDaniel Jasper SourceModule = Result; 9117e82e019SRichard Smith Modules[ModuleName] = Result; 912ba7f2f71SDaniel Jasper } 913c1d88ea5SBen Langmuir 914c1d88ea5SBen Langmuir Result->IsSystem |= Attrs.IsSystem; 915c1d88ea5SBen Langmuir Result->IsExternC |= Attrs.IsExternC; 916c1d88ea5SBen Langmuir Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive; 917ed84df00SBruno Cardoso Lopes Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes; 9182b63d15fSRichard Smith Result->Directory = FrameworkDir; 919a686e1b0SDouglas Gregor 920322f633cSDouglas Gregor // umbrella header "umbrella-header-name" 9212b63d15fSRichard Smith // 9222b63d15fSRichard Smith // The "Headers/" component of the name is implied because this is 9232b63d15fSRichard Smith // a framework module. 9242b63d15fSRichard Smith setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h"); 925d8bd7537SDouglas Gregor 926d8bd7537SDouglas Gregor // export * 927d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 928d8bd7537SDouglas Gregor 929a89c5ac4SDouglas Gregor // module * { export * } 930a89c5ac4SDouglas Gregor Result->InferSubmodules = true; 931a89c5ac4SDouglas Gregor Result->InferExportWildcard = true; 932a89c5ac4SDouglas Gregor 933e89dbc1dSDouglas Gregor // Look for subframeworks. 934c080917eSRafael Espindola std::error_code EC; 9352c1dd271SDylan Noblesmith SmallString<128> SubframeworksDirName 936ddaa69cbSDouglas Gregor = StringRef(FrameworkDir->getName()); 937e89dbc1dSDouglas Gregor llvm::sys::path::append(SubframeworksDirName, "Frameworks"); 9382d4d8cb3SBenjamin Kramer llvm::sys::path::native(SubframeworksDirName); 939b171a59bSBruno Cardoso Lopes vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); 940b171a59bSBruno Cardoso Lopes for (vfs::directory_iterator Dir = FS.dir_begin(SubframeworksDirName, EC), 941b171a59bSBruno Cardoso Lopes DirEnd; 942e89dbc1dSDouglas Gregor Dir != DirEnd && !EC; Dir.increment(EC)) { 943b171a59bSBruno Cardoso Lopes if (!StringRef(Dir->getName()).endswith(".framework")) 944e89dbc1dSDouglas Gregor continue; 945f2161a70SDouglas Gregor 946b171a59bSBruno Cardoso Lopes if (const DirectoryEntry *SubframeworkDir = 947b171a59bSBruno Cardoso Lopes FileMgr.getDirectory(Dir->getName())) { 94807c22b78SDouglas Gregor // Note: as an egregious but useful hack, we use the real path here and 94907c22b78SDouglas Gregor // check whether it is actually a subdirectory of the parent directory. 95007c22b78SDouglas Gregor // This will not be the case if the 'subframework' is actually a symlink 95107c22b78SDouglas Gregor // out to a top-level framework. 952e00c8b20SDouglas Gregor StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir); 95307c22b78SDouglas Gregor bool FoundParent = false; 95407c22b78SDouglas Gregor do { 95507c22b78SDouglas Gregor // Get the parent directory name. 95607c22b78SDouglas Gregor SubframeworkDirName 95707c22b78SDouglas Gregor = llvm::sys::path::parent_path(SubframeworkDirName); 95807c22b78SDouglas Gregor if (SubframeworkDirName.empty()) 95907c22b78SDouglas Gregor break; 96007c22b78SDouglas Gregor 96107c22b78SDouglas Gregor if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) { 96207c22b78SDouglas Gregor FoundParent = true; 96307c22b78SDouglas Gregor break; 96407c22b78SDouglas Gregor } 96507c22b78SDouglas Gregor } while (true); 96607c22b78SDouglas Gregor 96707c22b78SDouglas Gregor if (!FoundParent) 96807c22b78SDouglas Gregor continue; 96907c22b78SDouglas Gregor 970e89dbc1dSDouglas Gregor // FIXME: Do we want to warn about subframeworks without umbrella headers? 971a525400dSBen Langmuir inferFrameworkModule(SubframeworkDir, Attrs, Result); 972e89dbc1dSDouglas Gregor } 973e89dbc1dSDouglas Gregor } 974e89dbc1dSDouglas Gregor 97511dfe6feSDouglas Gregor // If the module is a top-level framework, automatically link against the 97611dfe6feSDouglas Gregor // framework. 97711dfe6feSDouglas Gregor if (!Result->isSubFramework()) { 97811dfe6feSDouglas Gregor inferFrameworkLink(Result, FrameworkDir, FileMgr); 97911dfe6feSDouglas Gregor } 98011dfe6feSDouglas Gregor 98156c64013SDouglas Gregor return Result; 98256c64013SDouglas Gregor } 98356c64013SDouglas Gregor 9842b63d15fSRichard Smith void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader, 9852b63d15fSRichard Smith Twine NameAsWritten) { 98697da9178SDaniel Jasper Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader)); 98773141fa9SDouglas Gregor Mod->Umbrella = UmbrellaHeader; 9882b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 9897033127bSDouglas Gregor UmbrellaDirs[UmbrellaHeader->getDir()] = Mod; 990b3a0fa48SBruno Cardoso Lopes 991b3a0fa48SBruno Cardoso Lopes // Notify callbacks that we just added a new header. 992b3a0fa48SBruno Cardoso Lopes for (const auto &Cb : Callbacks) 993b3a0fa48SBruno Cardoso Lopes Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader); 994a89c5ac4SDouglas Gregor } 995a89c5ac4SDouglas Gregor 9962b63d15fSRichard Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, 9972b63d15fSRichard Smith Twine NameAsWritten) { 998524e33e1SDouglas Gregor Mod->Umbrella = UmbrellaDir; 9992b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 1000524e33e1SDouglas Gregor UmbrellaDirs[UmbrellaDir] = Mod; 1001524e33e1SDouglas Gregor } 1002524e33e1SDouglas Gregor 1003040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod, 1004040e1266SRichard Smith Module::UnresolvedHeaderDirective Header) { 1005040e1266SRichard Smith // If there is a builtin counterpart to this file, add it now so it can 1006040e1266SRichard Smith // wrap the system header. 1007040e1266SRichard Smith if (resolveAsBuiltinHeader(Mod, Header)) { 1008040e1266SRichard Smith // If we have both a builtin and system version of the file, the 1009040e1266SRichard Smith // builtin version may want to inject macros into the system header, so 1010040e1266SRichard Smith // force the system header to be treated as a textual header in this 1011040e1266SRichard Smith // case. 1012040e1266SRichard Smith Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole( 1013040e1266SRichard Smith headerKindToRole(Header.Kind) | ModuleMap::TextualHeader)); 1014040e1266SRichard Smith Header.HasBuiltinHeader = true; 10153c1a41adSRichard Smith } 1016040e1266SRichard Smith 1017040e1266SRichard Smith // If possible, don't stat the header until we need to. This requires the 1018040e1266SRichard Smith // user to have provided us with some stat information about the file. 1019040e1266SRichard Smith // FIXME: Add support for lazily stat'ing umbrella headers and excluded 1020040e1266SRichard Smith // headers. 1021040e1266SRichard Smith if ((Header.Size || Header.ModTime) && !Header.IsUmbrella && 1022040e1266SRichard Smith Header.Kind != Module::HK_Excluded) { 1023040e1266SRichard Smith // We expect more variation in mtime than size, so if we're given both, 1024040e1266SRichard Smith // use the mtime as the key. 1025040e1266SRichard Smith if (Header.ModTime) 1026040e1266SRichard Smith LazyHeadersByModTime[*Header.ModTime].push_back(Mod); 1027040e1266SRichard Smith else 1028040e1266SRichard Smith LazyHeadersBySize[*Header.Size].push_back(Mod); 1029040e1266SRichard Smith Mod->UnresolvedHeaders.push_back(Header); 1030040e1266SRichard Smith return; 1031040e1266SRichard Smith } 1032040e1266SRichard Smith 1033040e1266SRichard Smith // We don't have stat information or can't defer looking this file up. 1034040e1266SRichard Smith // Perform the lookup now. 1035040e1266SRichard Smith resolveHeader(Mod, Header); 1036040e1266SRichard Smith } 1037040e1266SRichard Smith 1038040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const { 1039040e1266SRichard Smith auto BySize = LazyHeadersBySize.find(File->getSize()); 1040040e1266SRichard Smith if (BySize != LazyHeadersBySize.end()) { 1041040e1266SRichard Smith for (auto *M : BySize->second) 1042040e1266SRichard Smith resolveHeaderDirectives(M); 1043040e1266SRichard Smith LazyHeadersBySize.erase(BySize); 1044040e1266SRichard Smith } 1045040e1266SRichard Smith 1046040e1266SRichard Smith auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime()); 1047040e1266SRichard Smith if (ByModTime != LazyHeadersByModTime.end()) { 1048040e1266SRichard Smith for (auto *M : ByModTime->second) 1049040e1266SRichard Smith resolveHeaderDirectives(M); 1050040e1266SRichard Smith LazyHeadersByModTime.erase(ByModTime); 1051040e1266SRichard Smith } 1052040e1266SRichard Smith } 1053040e1266SRichard Smith 1054040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(Module *Mod) const { 1055040e1266SRichard Smith for (auto &Header : Mod->UnresolvedHeaders) 1056040e1266SRichard Smith // This operation is logically const; we're just changing how we represent 1057040e1266SRichard Smith // the header information for this file. 1058040e1266SRichard Smith const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header); 1059040e1266SRichard Smith Mod->UnresolvedHeaders.clear(); 10600e98d938SNAKAMURA Takumi } 1061202210b3SRichard Smith 10623c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header, 1063d8879c85SRichard Smith ModuleHeaderRole Role, bool Imported) { 1064386bb073SRichard Smith KnownHeader KH(Mod, Role); 10653c1a41adSRichard Smith 1066386bb073SRichard Smith // Only add each header to the headers list once. 1067386bb073SRichard Smith // FIXME: Should we diagnose if a header is listed twice in the 1068386bb073SRichard Smith // same module definition? 1069386bb073SRichard Smith auto &HeaderList = Headers[Header.Entry]; 1070386bb073SRichard Smith for (auto H : HeaderList) 1071386bb073SRichard Smith if (H == KH) 1072386bb073SRichard Smith return; 1073386bb073SRichard Smith 1074386bb073SRichard Smith HeaderList.push_back(KH); 10751ec383c7SPiotr Padlewski Mod->Headers[headerRoleToKind(Role)].push_back(Header); 1076386bb073SRichard Smith 10777e82e019SRichard Smith bool isCompilingModuleHeader = 1078bbcc9f04SRichard Smith LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule; 1079d8879c85SRichard Smith if (!Imported || isCompilingModuleHeader) { 1080d8879c85SRichard Smith // When we import HeaderFileInfo, the external source is expected to 1081d8879c85SRichard Smith // set the isModuleHeader flag itself. 1082d8879c85SRichard Smith HeaderInfo.MarkFileModuleHeader(Header.Entry, Role, 1083d8879c85SRichard Smith isCompilingModuleHeader); 1084d8879c85SRichard Smith } 1085e62cfd7cSBruno Cardoso Lopes 1086e62cfd7cSBruno Cardoso Lopes // Notify callbacks that we just added a new header. 1087e62cfd7cSBruno Cardoso Lopes for (const auto &Cb : Callbacks) 1088f0841790SBruno Cardoso Lopes Cb->moduleMapAddHeader(Header.Entry->getName()); 1089a89c5ac4SDouglas Gregor } 1090a89c5ac4SDouglas Gregor 10913c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) { 1092feb54b6dSRichard Smith // Add this as a known header so we won't implicitly add it to any 1093feb54b6dSRichard Smith // umbrella directory module. 1094feb54b6dSRichard Smith // FIXME: Should we only exclude it from umbrella modules within the 1095feb54b6dSRichard Smith // specified module? 10963c1a41adSRichard Smith (void) Headers[Header.Entry]; 10973c1a41adSRichard Smith 10983c1a41adSRichard Smith Mod->Headers[Module::HK_Excluded].push_back(std::move(Header)); 1099feb54b6dSRichard Smith } 1100feb54b6dSRichard Smith 1101514b636aSDouglas Gregor const FileEntry * 11024b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const { 11031f76c4e8SManuel Klimek if (Module->DefinitionLoc.isInvalid()) 1104d2d442caSCraig Topper return nullptr; 1105514b636aSDouglas Gregor 11061f76c4e8SManuel Klimek return SourceMgr.getFileEntryForID( 11071f76c4e8SManuel Klimek SourceMgr.getFileID(Module->DefinitionLoc)); 1108514b636aSDouglas Gregor } 1109514b636aSDouglas Gregor 11104b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const { 11119d6448b1SBen Langmuir if (M->IsInferred) { 11129d6448b1SBen Langmuir assert(InferredModuleAllowedBy.count(M) && "missing inferred module map"); 11139d6448b1SBen Langmuir return InferredModuleAllowedBy.find(M)->second; 11149d6448b1SBen Langmuir } 11159d6448b1SBen Langmuir return getContainingModuleMapFile(M); 11169d6448b1SBen Langmuir } 11179d6448b1SBen Langmuir 11189d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) { 11199d6448b1SBen Langmuir assert(M->IsInferred && "module not inferred"); 11209d6448b1SBen Langmuir InferredModuleAllowedBy[M] = ModMap; 11219d6448b1SBen Langmuir } 11229d6448b1SBen Langmuir 1123cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() { 1124718292f2SDouglas Gregor llvm::errs() << "Modules:"; 1125718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 1126718292f2SDouglas Gregor MEnd = Modules.end(); 1127718292f2SDouglas Gregor M != MEnd; ++M) 1128d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 1129718292f2SDouglas Gregor 1130718292f2SDouglas Gregor llvm::errs() << "Headers:"; 113159527666SDouglas Gregor for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end(); 1132718292f2SDouglas Gregor H != HEnd; ++H) { 113397da9178SDaniel Jasper llvm::errs() << " \"" << H->first->getName() << "\" -> "; 113497da9178SDaniel Jasper for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(), 113597da9178SDaniel Jasper E = H->second.end(); 113697da9178SDaniel Jasper I != E; ++I) { 113797da9178SDaniel Jasper if (I != H->second.begin()) 113897da9178SDaniel Jasper llvm::errs() << ","; 113997da9178SDaniel Jasper llvm::errs() << I->getModule()->getFullModuleName(); 114097da9178SDaniel Jasper } 114197da9178SDaniel Jasper llvm::errs() << "\n"; 1142718292f2SDouglas Gregor } 1143718292f2SDouglas Gregor } 1144718292f2SDouglas Gregor 11452b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) { 114642413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedExports); 114742413141SRichard Smith Mod->UnresolvedExports.clear(); 114842413141SRichard Smith for (auto &UE : Unresolved) { 114942413141SRichard Smith Module::ExportDecl Export = resolveExport(Mod, UE, Complain); 1150f5eedd05SDouglas Gregor if (Export.getPointer() || Export.getInt()) 11512b82c2a5SDouglas Gregor Mod->Exports.push_back(Export); 11522b82c2a5SDouglas Gregor else 115342413141SRichard Smith Mod->UnresolvedExports.push_back(UE); 11542b82c2a5SDouglas Gregor } 115542413141SRichard Smith return !Mod->UnresolvedExports.empty(); 11562b82c2a5SDouglas Gregor } 11572b82c2a5SDouglas Gregor 1158ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) { 115942413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedDirectUses); 116042413141SRichard Smith Mod->UnresolvedDirectUses.clear(); 116142413141SRichard Smith for (auto &UDU : Unresolved) { 116242413141SRichard Smith Module *DirectUse = resolveModuleId(UDU, Mod, Complain); 1163ba7f2f71SDaniel Jasper if (DirectUse) 1164ba7f2f71SDaniel Jasper Mod->DirectUses.push_back(DirectUse); 1165ba7f2f71SDaniel Jasper else 116642413141SRichard Smith Mod->UnresolvedDirectUses.push_back(UDU); 1167ba7f2f71SDaniel Jasper } 116842413141SRichard Smith return !Mod->UnresolvedDirectUses.empty(); 1169ba7f2f71SDaniel Jasper } 1170ba7f2f71SDaniel Jasper 1171fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) { 117242413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedConflicts); 117342413141SRichard Smith Mod->UnresolvedConflicts.clear(); 117442413141SRichard Smith for (auto &UC : Unresolved) { 117542413141SRichard Smith if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) { 1176fb912657SDouglas Gregor Module::Conflict Conflict; 1177fb912657SDouglas Gregor Conflict.Other = OtherMod; 117842413141SRichard Smith Conflict.Message = UC.Message; 1179fb912657SDouglas Gregor Mod->Conflicts.push_back(Conflict); 118042413141SRichard Smith } else 118142413141SRichard Smith Mod->UnresolvedConflicts.push_back(UC); 1182fb912657SDouglas Gregor } 118342413141SRichard Smith return !Mod->UnresolvedConflicts.empty(); 1184fb912657SDouglas Gregor } 1185fb912657SDouglas Gregor 1186718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1187718292f2SDouglas Gregor // Module map file parser 1188718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1189718292f2SDouglas Gregor 1190718292f2SDouglas Gregor namespace clang { 1191718292f2SDouglas Gregor /// \brief A token in a module map file. 1192718292f2SDouglas Gregor struct MMToken { 1193718292f2SDouglas Gregor enum TokenKind { 11941fb5c3a6SDouglas Gregor Comma, 119535b13eceSDouglas Gregor ConfigMacros, 1196fb912657SDouglas Gregor Conflict, 1197718292f2SDouglas Gregor EndOfFile, 1198718292f2SDouglas Gregor HeaderKeyword, 1199718292f2SDouglas Gregor Identifier, 1200a3feee2aSRichard Smith Exclaim, 120159527666SDouglas Gregor ExcludeKeyword, 1202718292f2SDouglas Gregor ExplicitKeyword, 12032b82c2a5SDouglas Gregor ExportKeyword, 1204*f0b11de2SDouglas Gregor ExportAsKeyword, 120597292843SDaniel Jasper ExternKeyword, 1206755b2055SDouglas Gregor FrameworkKeyword, 12076ddfca91SDouglas Gregor LinkKeyword, 1208718292f2SDouglas Gregor ModuleKeyword, 12092b82c2a5SDouglas Gregor Period, 1210b53e5483SLawrence Crowl PrivateKeyword, 1211718292f2SDouglas Gregor UmbrellaKeyword, 1212ba7f2f71SDaniel Jasper UseKeyword, 12131fb5c3a6SDouglas Gregor RequiresKeyword, 12142b82c2a5SDouglas Gregor Star, 1215718292f2SDouglas Gregor StringLiteral, 1216040e1266SRichard Smith IntegerLiteral, 1217306d8920SRichard Smith TextualKeyword, 1218718292f2SDouglas Gregor LBrace, 1219a686e1b0SDouglas Gregor RBrace, 1220a686e1b0SDouglas Gregor LSquare, 1221a686e1b0SDouglas Gregor RSquare 1222718292f2SDouglas Gregor } Kind; 1223718292f2SDouglas Gregor 1224718292f2SDouglas Gregor unsigned Location; 1225718292f2SDouglas Gregor unsigned StringLength; 1226040e1266SRichard Smith union { 1227040e1266SRichard Smith // If Kind != IntegerLiteral. 1228718292f2SDouglas Gregor const char *StringData; 1229040e1266SRichard Smith // If Kind == IntegerLiteral. 1230040e1266SRichard Smith uint64_t IntegerValue; 1231040e1266SRichard Smith }; 1232718292f2SDouglas Gregor 1233718292f2SDouglas Gregor void clear() { 1234718292f2SDouglas Gregor Kind = EndOfFile; 1235718292f2SDouglas Gregor Location = 0; 1236718292f2SDouglas Gregor StringLength = 0; 1237d2d442caSCraig Topper StringData = nullptr; 1238718292f2SDouglas Gregor } 1239718292f2SDouglas Gregor 1240718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 1241718292f2SDouglas Gregor 1242718292f2SDouglas Gregor SourceLocation getLocation() const { 1243718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 1244718292f2SDouglas Gregor } 1245718292f2SDouglas Gregor 1246040e1266SRichard Smith uint64_t getInteger() const { 1247040e1266SRichard Smith return Kind == IntegerLiteral ? IntegerValue : 0; 1248040e1266SRichard Smith } 1249040e1266SRichard Smith 1250718292f2SDouglas Gregor StringRef getString() const { 1251040e1266SRichard Smith return Kind == IntegerLiteral ? StringRef() 1252040e1266SRichard Smith : StringRef(StringData, StringLength); 1253718292f2SDouglas Gregor } 1254718292f2SDouglas Gregor }; 1255718292f2SDouglas Gregor 1256718292f2SDouglas Gregor class ModuleMapParser { 1257718292f2SDouglas Gregor Lexer &L; 1258718292f2SDouglas Gregor SourceManager &SourceMgr; 1259bc10b9fbSDouglas Gregor 1260bc10b9fbSDouglas Gregor /// \brief Default target information, used only for string literal 1261bc10b9fbSDouglas Gregor /// parsing. 1262bc10b9fbSDouglas Gregor const TargetInfo *Target; 1263bc10b9fbSDouglas Gregor 1264718292f2SDouglas Gregor DiagnosticsEngine &Diags; 1265718292f2SDouglas Gregor ModuleMap ⤅ 1266718292f2SDouglas Gregor 1267beee15e7SBen Langmuir /// \brief The current module map file. 1268beee15e7SBen Langmuir const FileEntry *ModuleMapFile; 1269beee15e7SBen Langmuir 12709acb99e3SRichard Smith /// \brief The directory that file names in this module map file should 12719acb99e3SRichard Smith /// be resolved relative to. 12725257fc63SDouglas Gregor const DirectoryEntry *Directory; 12735257fc63SDouglas Gregor 1274963c5535SDouglas Gregor /// \brief Whether this module map is in a system header directory. 1275963c5535SDouglas Gregor bool IsSystem; 1276963c5535SDouglas Gregor 1277718292f2SDouglas Gregor /// \brief Whether an error occurred. 1278718292f2SDouglas Gregor bool HadError; 1279718292f2SDouglas Gregor 1280718292f2SDouglas Gregor /// \brief Stores string data for the various string literals referenced 1281718292f2SDouglas Gregor /// during parsing. 1282718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 1283718292f2SDouglas Gregor 1284718292f2SDouglas Gregor /// \brief The current token. 1285718292f2SDouglas Gregor MMToken Tok; 1286718292f2SDouglas Gregor 1287718292f2SDouglas Gregor /// \brief The active module. 1288de3ef502SDouglas Gregor Module *ActiveModule; 1289718292f2SDouglas Gregor 12907ff29148SBen Langmuir /// \brief Whether a module uses the 'requires excluded' hack to mark its 12917ff29148SBen Langmuir /// contents as 'textual'. 12927ff29148SBen Langmuir /// 12937ff29148SBen Langmuir /// On older Darwin SDK versions, 'requires excluded' is used to mark the 12947ff29148SBen Langmuir /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as 12957ff29148SBen Langmuir /// non-modular headers. For backwards compatibility, we continue to 12967ff29148SBen Langmuir /// support this idiom for just these modules, and map the headers to 12977ff29148SBen Langmuir /// 'textual' to match the original intent. 12987ff29148SBen Langmuir llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack; 12997ff29148SBen Langmuir 1300718292f2SDouglas Gregor /// \brief Consume the current token and return its location. 1301718292f2SDouglas Gregor SourceLocation consumeToken(); 1302718292f2SDouglas Gregor 1303718292f2SDouglas Gregor /// \brief Skip tokens until we reach the a token with the given kind 1304718292f2SDouglas Gregor /// (or the end of the file). 1305718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 1306718292f2SDouglas Gregor 1307f857950dSDmitri Gribenko typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId; 1308e7ab3669SDouglas Gregor bool parseModuleId(ModuleId &Id); 1309718292f2SDouglas Gregor void parseModuleDecl(); 131097292843SDaniel Jasper void parseExternModuleDecl(); 13111fb5c3a6SDouglas Gregor void parseRequiresDecl(); 1312b53e5483SLawrence Crowl void parseHeaderDecl(clang::MMToken::TokenKind, 1313b53e5483SLawrence Crowl SourceLocation LeadingLoc); 1314524e33e1SDouglas Gregor void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc); 13152b82c2a5SDouglas Gregor void parseExportDecl(); 1316*f0b11de2SDouglas Gregor void parseExportAsDecl(); 1317ba7f2f71SDaniel Jasper void parseUseDecl(); 13186ddfca91SDouglas Gregor void parseLinkDecl(); 131935b13eceSDouglas Gregor void parseConfigMacros(); 1320fb912657SDouglas Gregor void parseConflict(); 13219194a91dSDouglas Gregor void parseInferredModuleDecl(bool Framework, bool Explicit); 1322c1d88ea5SBen Langmuir 1323c1d88ea5SBen Langmuir typedef ModuleMap::Attributes Attributes; 13244442605fSBill Wendling bool parseOptionalAttributes(Attributes &Attrs); 1325718292f2SDouglas Gregor 1326718292f2SDouglas Gregor public: 1327718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 1328bc10b9fbSDouglas Gregor const TargetInfo *Target, 1329718292f2SDouglas Gregor DiagnosticsEngine &Diags, 13305257fc63SDouglas Gregor ModuleMap &Map, 1331beee15e7SBen Langmuir const FileEntry *ModuleMapFile, 13323ec6663bSDouglas Gregor const DirectoryEntry *Directory, 1333963c5535SDouglas Gregor bool IsSystem) 1334bc10b9fbSDouglas Gregor : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map), 1335beee15e7SBen Langmuir ModuleMapFile(ModuleMapFile), Directory(Directory), 13361d60987fSRichard Smith IsSystem(IsSystem), HadError(false), ActiveModule(nullptr) 1337718292f2SDouglas Gregor { 1338718292f2SDouglas Gregor Tok.clear(); 1339718292f2SDouglas Gregor consumeToken(); 1340718292f2SDouglas Gregor } 1341718292f2SDouglas Gregor 1342718292f2SDouglas Gregor bool parseModuleMapFile(); 13438128f332SRichard Smith 13448128f332SRichard Smith bool terminatedByDirective() { return false; } 13458128f332SRichard Smith SourceLocation getLocation() { return Tok.getLocation(); } 1346718292f2SDouglas Gregor }; 1347ab9db510SAlexander Kornienko } 1348718292f2SDouglas Gregor 1349718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 1350718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 1351718292f2SDouglas Gregor 13528128f332SRichard Smith retry: 13538128f332SRichard Smith Tok.clear(); 1354718292f2SDouglas Gregor Token LToken; 1355718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 1356718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 1357718292f2SDouglas Gregor switch (LToken.getKind()) { 13582d57cea2SAlp Toker case tok::raw_identifier: { 13592d57cea2SAlp Toker StringRef RI = LToken.getRawIdentifier(); 13602d57cea2SAlp Toker Tok.StringData = RI.data(); 13612d57cea2SAlp Toker Tok.StringLength = RI.size(); 13622d57cea2SAlp Toker Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI) 136335b13eceSDouglas Gregor .Case("config_macros", MMToken::ConfigMacros) 1364fb912657SDouglas Gregor .Case("conflict", MMToken::Conflict) 136559527666SDouglas Gregor .Case("exclude", MMToken::ExcludeKeyword) 1366718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 13672b82c2a5SDouglas Gregor .Case("export", MMToken::ExportKeyword) 1368*f0b11de2SDouglas Gregor .Case("export_as", MMToken::ExportAsKeyword) 136997292843SDaniel Jasper .Case("extern", MMToken::ExternKeyword) 1370755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 137135b13eceSDouglas Gregor .Case("header", MMToken::HeaderKeyword) 13726ddfca91SDouglas Gregor .Case("link", MMToken::LinkKeyword) 1373718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 1374b53e5483SLawrence Crowl .Case("private", MMToken::PrivateKeyword) 13751fb5c3a6SDouglas Gregor .Case("requires", MMToken::RequiresKeyword) 1376306d8920SRichard Smith .Case("textual", MMToken::TextualKeyword) 1377718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 1378ba7f2f71SDaniel Jasper .Case("use", MMToken::UseKeyword) 1379718292f2SDouglas Gregor .Default(MMToken::Identifier); 1380718292f2SDouglas Gregor break; 13812d57cea2SAlp Toker } 1382718292f2SDouglas Gregor 13831fb5c3a6SDouglas Gregor case tok::comma: 13841fb5c3a6SDouglas Gregor Tok.Kind = MMToken::Comma; 13851fb5c3a6SDouglas Gregor break; 13861fb5c3a6SDouglas Gregor 1387718292f2SDouglas Gregor case tok::eof: 1388718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 1389718292f2SDouglas Gregor break; 1390718292f2SDouglas Gregor 1391718292f2SDouglas Gregor case tok::l_brace: 1392718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 1393718292f2SDouglas Gregor break; 1394718292f2SDouglas Gregor 1395a686e1b0SDouglas Gregor case tok::l_square: 1396a686e1b0SDouglas Gregor Tok.Kind = MMToken::LSquare; 1397a686e1b0SDouglas Gregor break; 1398a686e1b0SDouglas Gregor 13992b82c2a5SDouglas Gregor case tok::period: 14002b82c2a5SDouglas Gregor Tok.Kind = MMToken::Period; 14012b82c2a5SDouglas Gregor break; 14022b82c2a5SDouglas Gregor 1403718292f2SDouglas Gregor case tok::r_brace: 1404718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 1405718292f2SDouglas Gregor break; 1406718292f2SDouglas Gregor 1407a686e1b0SDouglas Gregor case tok::r_square: 1408a686e1b0SDouglas Gregor Tok.Kind = MMToken::RSquare; 1409a686e1b0SDouglas Gregor break; 1410a686e1b0SDouglas Gregor 14112b82c2a5SDouglas Gregor case tok::star: 14122b82c2a5SDouglas Gregor Tok.Kind = MMToken::Star; 14132b82c2a5SDouglas Gregor break; 14142b82c2a5SDouglas Gregor 1415a3feee2aSRichard Smith case tok::exclaim: 1416a3feee2aSRichard Smith Tok.Kind = MMToken::Exclaim; 1417a3feee2aSRichard Smith break; 1418a3feee2aSRichard Smith 1419718292f2SDouglas Gregor case tok::string_literal: { 1420d67aea28SRichard Smith if (LToken.hasUDSuffix()) { 1421d67aea28SRichard Smith Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl); 1422d67aea28SRichard Smith HadError = true; 1423d67aea28SRichard Smith goto retry; 1424d67aea28SRichard Smith } 1425d67aea28SRichard Smith 1426718292f2SDouglas Gregor // Parse the string literal. 1427718292f2SDouglas Gregor LangOptions LangOpts; 14289d5583efSCraig Topper StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target); 1429718292f2SDouglas Gregor if (StringLiteral.hadError) 1430718292f2SDouglas Gregor goto retry; 1431718292f2SDouglas Gregor 1432718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 1433718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 1434718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 1435718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 1436718292f2SDouglas Gregor Saved[Length] = 0; 1437718292f2SDouglas Gregor 1438718292f2SDouglas Gregor // Form the token. 1439718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 1440718292f2SDouglas Gregor Tok.StringData = Saved; 1441718292f2SDouglas Gregor Tok.StringLength = Length; 1442718292f2SDouglas Gregor break; 1443718292f2SDouglas Gregor } 1444718292f2SDouglas Gregor 1445040e1266SRichard Smith case tok::numeric_constant: { 1446040e1266SRichard Smith // We don't support any suffixes or other complications. 1447040e1266SRichard Smith SmallString<32> SpellingBuffer; 1448040e1266SRichard Smith SpellingBuffer.resize(LToken.getLength() + 1); 1449040e1266SRichard Smith const char *Start = SpellingBuffer.data(); 1450040e1266SRichard Smith unsigned Length = 1451040e1266SRichard Smith Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts()); 1452040e1266SRichard Smith uint64_t Value; 1453040e1266SRichard Smith if (StringRef(Start, Length).getAsInteger(0, Value)) { 1454040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1455040e1266SRichard Smith HadError = true; 1456040e1266SRichard Smith goto retry; 1457040e1266SRichard Smith } 1458040e1266SRichard Smith 1459040e1266SRichard Smith Tok.Kind = MMToken::IntegerLiteral; 1460040e1266SRichard Smith Tok.IntegerValue = Value; 1461040e1266SRichard Smith break; 1462040e1266SRichard Smith } 1463040e1266SRichard Smith 1464718292f2SDouglas Gregor case tok::comment: 1465718292f2SDouglas Gregor goto retry; 1466718292f2SDouglas Gregor 14678128f332SRichard Smith case tok::hash: 14688128f332SRichard Smith // A module map can be terminated prematurely by 14698128f332SRichard Smith // #pragma clang module contents 14708128f332SRichard Smith // When building the module, we'll treat the rest of the file as the 14718128f332SRichard Smith // contents of the module. 14728128f332SRichard Smith { 14738128f332SRichard Smith auto NextIsIdent = [&](StringRef Str) -> bool { 14748128f332SRichard Smith L.LexFromRawLexer(LToken); 14758128f332SRichard Smith return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) && 14768128f332SRichard Smith LToken.getRawIdentifier() == Str; 14778128f332SRichard Smith }; 14788128f332SRichard Smith if (NextIsIdent("pragma") && NextIsIdent("clang") && 14798128f332SRichard Smith NextIsIdent("module") && NextIsIdent("contents")) { 14808128f332SRichard Smith Tok.Kind = MMToken::EndOfFile; 14818128f332SRichard Smith break; 14828128f332SRichard Smith } 14838128f332SRichard Smith } 14848128f332SRichard Smith LLVM_FALLTHROUGH; 14858128f332SRichard Smith 1486718292f2SDouglas Gregor default: 14878128f332SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1488718292f2SDouglas Gregor HadError = true; 1489718292f2SDouglas Gregor goto retry; 1490718292f2SDouglas Gregor } 1491718292f2SDouglas Gregor 1492718292f2SDouglas Gregor return Result; 1493718292f2SDouglas Gregor } 1494718292f2SDouglas Gregor 1495718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 1496718292f2SDouglas Gregor unsigned braceDepth = 0; 1497a686e1b0SDouglas Gregor unsigned squareDepth = 0; 1498718292f2SDouglas Gregor do { 1499718292f2SDouglas Gregor switch (Tok.Kind) { 1500718292f2SDouglas Gregor case MMToken::EndOfFile: 1501718292f2SDouglas Gregor return; 1502718292f2SDouglas Gregor 1503718292f2SDouglas Gregor case MMToken::LBrace: 1504a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1505718292f2SDouglas Gregor return; 1506718292f2SDouglas Gregor 1507718292f2SDouglas Gregor ++braceDepth; 1508718292f2SDouglas Gregor break; 1509718292f2SDouglas Gregor 1510a686e1b0SDouglas Gregor case MMToken::LSquare: 1511a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1512a686e1b0SDouglas Gregor return; 1513a686e1b0SDouglas Gregor 1514a686e1b0SDouglas Gregor ++squareDepth; 1515a686e1b0SDouglas Gregor break; 1516a686e1b0SDouglas Gregor 1517718292f2SDouglas Gregor case MMToken::RBrace: 1518718292f2SDouglas Gregor if (braceDepth > 0) 1519718292f2SDouglas Gregor --braceDepth; 1520718292f2SDouglas Gregor else if (Tok.is(K)) 1521718292f2SDouglas Gregor return; 1522718292f2SDouglas Gregor break; 1523718292f2SDouglas Gregor 1524a686e1b0SDouglas Gregor case MMToken::RSquare: 1525a686e1b0SDouglas Gregor if (squareDepth > 0) 1526a686e1b0SDouglas Gregor --squareDepth; 1527a686e1b0SDouglas Gregor else if (Tok.is(K)) 1528a686e1b0SDouglas Gregor return; 1529a686e1b0SDouglas Gregor break; 1530a686e1b0SDouglas Gregor 1531718292f2SDouglas Gregor default: 1532a686e1b0SDouglas Gregor if (braceDepth == 0 && squareDepth == 0 && Tok.is(K)) 1533718292f2SDouglas Gregor return; 1534718292f2SDouglas Gregor break; 1535718292f2SDouglas Gregor } 1536718292f2SDouglas Gregor 1537718292f2SDouglas Gregor consumeToken(); 1538718292f2SDouglas Gregor } while (true); 1539718292f2SDouglas Gregor } 1540718292f2SDouglas Gregor 1541e7ab3669SDouglas Gregor /// \brief Parse a module-id. 1542e7ab3669SDouglas Gregor /// 1543e7ab3669SDouglas Gregor /// module-id: 1544e7ab3669SDouglas Gregor /// identifier 1545e7ab3669SDouglas Gregor /// identifier '.' module-id 1546e7ab3669SDouglas Gregor /// 1547e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise. 1548e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) { 1549e7ab3669SDouglas Gregor Id.clear(); 1550e7ab3669SDouglas Gregor do { 15513cd34c76SDaniel Jasper if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) { 1552e7ab3669SDouglas Gregor Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation())); 1553e7ab3669SDouglas Gregor consumeToken(); 1554e7ab3669SDouglas Gregor } else { 1555e7ab3669SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 1556e7ab3669SDouglas Gregor return true; 1557e7ab3669SDouglas Gregor } 1558e7ab3669SDouglas Gregor 1559e7ab3669SDouglas Gregor if (!Tok.is(MMToken::Period)) 1560e7ab3669SDouglas Gregor break; 1561e7ab3669SDouglas Gregor 1562e7ab3669SDouglas Gregor consumeToken(); 1563e7ab3669SDouglas Gregor } while (true); 1564e7ab3669SDouglas Gregor 1565e7ab3669SDouglas Gregor return false; 1566e7ab3669SDouglas Gregor } 1567e7ab3669SDouglas Gregor 1568a686e1b0SDouglas Gregor namespace { 1569a686e1b0SDouglas Gregor /// \brief Enumerates the known attributes. 1570a686e1b0SDouglas Gregor enum AttributeKind { 1571a686e1b0SDouglas Gregor /// \brief An unknown attribute. 1572a686e1b0SDouglas Gregor AT_unknown, 1573a686e1b0SDouglas Gregor /// \brief The 'system' attribute. 157435b13eceSDouglas Gregor AT_system, 157577944868SRichard Smith /// \brief The 'extern_c' attribute. 157677944868SRichard Smith AT_extern_c, 157735b13eceSDouglas Gregor /// \brief The 'exhaustive' attribute. 1578ed84df00SBruno Cardoso Lopes AT_exhaustive, 1579ed84df00SBruno Cardoso Lopes /// \brief The 'no_undeclared_includes' attribute. 1580ed84df00SBruno Cardoso Lopes AT_no_undeclared_includes 1581a686e1b0SDouglas Gregor }; 1582ab9db510SAlexander Kornienko } 1583a686e1b0SDouglas Gregor 1584718292f2SDouglas Gregor /// \brief Parse a module declaration. 1585718292f2SDouglas Gregor /// 1586718292f2SDouglas Gregor /// module-declaration: 158797292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 1588a686e1b0SDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt] 1589a686e1b0SDouglas Gregor /// { module-member* } 1590a686e1b0SDouglas Gregor /// 1591718292f2SDouglas Gregor /// module-member: 15921fb5c3a6SDouglas Gregor /// requires-declaration 1593718292f2SDouglas Gregor /// header-declaration 1594e7ab3669SDouglas Gregor /// submodule-declaration 15952b82c2a5SDouglas Gregor /// export-declaration 1596*f0b11de2SDouglas Gregor /// export-as-declaration 15976ddfca91SDouglas Gregor /// link-declaration 159873441091SDouglas Gregor /// 159973441091SDouglas Gregor /// submodule-declaration: 160073441091SDouglas Gregor /// module-declaration 160173441091SDouglas Gregor /// inferred-submodule-declaration 1602718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 1603755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 160497292843SDaniel Jasper Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword)); 160597292843SDaniel Jasper if (Tok.is(MMToken::ExternKeyword)) { 160697292843SDaniel Jasper parseExternModuleDecl(); 160797292843SDaniel Jasper return; 160897292843SDaniel Jasper } 160997292843SDaniel Jasper 1610f2161a70SDouglas Gregor // Parse 'explicit' or 'framework' keyword, if present. 1611e7ab3669SDouglas Gregor SourceLocation ExplicitLoc; 1612718292f2SDouglas Gregor bool Explicit = false; 1613f2161a70SDouglas Gregor bool Framework = false; 1614755b2055SDouglas Gregor 1615f2161a70SDouglas Gregor // Parse 'explicit' keyword, if present. 1616f2161a70SDouglas Gregor if (Tok.is(MMToken::ExplicitKeyword)) { 1617e7ab3669SDouglas Gregor ExplicitLoc = consumeToken(); 1618f2161a70SDouglas Gregor Explicit = true; 1619f2161a70SDouglas Gregor } 1620f2161a70SDouglas Gregor 1621f2161a70SDouglas Gregor // Parse 'framework' keyword, if present. 1622755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 1623755b2055SDouglas Gregor consumeToken(); 1624755b2055SDouglas Gregor Framework = true; 1625755b2055SDouglas Gregor } 1626718292f2SDouglas Gregor 1627718292f2SDouglas Gregor // Parse 'module' keyword. 1628718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 1629d6343c99SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 1630718292f2SDouglas Gregor consumeToken(); 1631718292f2SDouglas Gregor HadError = true; 1632718292f2SDouglas Gregor return; 1633718292f2SDouglas Gregor } 1634718292f2SDouglas Gregor consumeToken(); // 'module' keyword 1635718292f2SDouglas Gregor 163673441091SDouglas Gregor // If we have a wildcard for the module name, this is an inferred submodule. 163773441091SDouglas Gregor // Parse it. 163873441091SDouglas Gregor if (Tok.is(MMToken::Star)) 16399194a91dSDouglas Gregor return parseInferredModuleDecl(Framework, Explicit); 164073441091SDouglas Gregor 1641718292f2SDouglas Gregor // Parse the module name. 1642e7ab3669SDouglas Gregor ModuleId Id; 1643e7ab3669SDouglas Gregor if (parseModuleId(Id)) { 1644718292f2SDouglas Gregor HadError = true; 1645718292f2SDouglas Gregor return; 1646718292f2SDouglas Gregor } 1647e7ab3669SDouglas Gregor 1648e7ab3669SDouglas Gregor if (ActiveModule) { 1649e7ab3669SDouglas Gregor if (Id.size() > 1) { 1650e7ab3669SDouglas Gregor Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id) 1651e7ab3669SDouglas Gregor << SourceRange(Id.front().second, Id.back().second); 1652e7ab3669SDouglas Gregor 1653e7ab3669SDouglas Gregor HadError = true; 1654e7ab3669SDouglas Gregor return; 1655e7ab3669SDouglas Gregor } 1656e7ab3669SDouglas Gregor } else if (Id.size() == 1 && Explicit) { 1657e7ab3669SDouglas Gregor // Top-level modules can't be explicit. 1658e7ab3669SDouglas Gregor Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level); 1659e7ab3669SDouglas Gregor Explicit = false; 1660e7ab3669SDouglas Gregor ExplicitLoc = SourceLocation(); 1661e7ab3669SDouglas Gregor HadError = true; 1662e7ab3669SDouglas Gregor } 1663e7ab3669SDouglas Gregor 1664e7ab3669SDouglas Gregor Module *PreviousActiveModule = ActiveModule; 1665e7ab3669SDouglas Gregor if (Id.size() > 1) { 1666e7ab3669SDouglas Gregor // This module map defines a submodule. Go find the module of which it 1667e7ab3669SDouglas Gregor // is a submodule. 1668d2d442caSCraig Topper ActiveModule = nullptr; 16694b8a9e95SBen Langmuir const Module *TopLevelModule = nullptr; 1670e7ab3669SDouglas Gregor for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) { 1671e7ab3669SDouglas Gregor if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) { 16724b8a9e95SBen Langmuir if (I == 0) 16734b8a9e95SBen Langmuir TopLevelModule = Next; 1674e7ab3669SDouglas Gregor ActiveModule = Next; 1675e7ab3669SDouglas Gregor continue; 1676e7ab3669SDouglas Gregor } 1677e7ab3669SDouglas Gregor 1678e7ab3669SDouglas Gregor if (ActiveModule) { 1679e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified) 16805b5d21eaSRichard Smith << Id[I].first 16815b5d21eaSRichard Smith << ActiveModule->getTopLevelModule()->getFullModuleName(); 1682e7ab3669SDouglas Gregor } else { 1683e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_expected_module_name); 1684e7ab3669SDouglas Gregor } 1685e7ab3669SDouglas Gregor HadError = true; 1686e7ab3669SDouglas Gregor return; 1687e7ab3669SDouglas Gregor } 16884b8a9e95SBen Langmuir 16894b8a9e95SBen Langmuir if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) { 16904b8a9e95SBen Langmuir assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) && 16914b8a9e95SBen Langmuir "submodule defined in same file as 'module *' that allowed its " 16924b8a9e95SBen Langmuir "top-level module"); 16934b8a9e95SBen Langmuir Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile); 16944b8a9e95SBen Langmuir } 1695e7ab3669SDouglas Gregor } 1696e7ab3669SDouglas Gregor 1697e7ab3669SDouglas Gregor StringRef ModuleName = Id.back().first; 1698e7ab3669SDouglas Gregor SourceLocation ModuleNameLoc = Id.back().second; 1699718292f2SDouglas Gregor 1700a686e1b0SDouglas Gregor // Parse the optional attribute list. 17014442605fSBill Wendling Attributes Attrs; 17025d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 17035d29dee0SDavide Italiano return; 17045d29dee0SDavide Italiano 1705a686e1b0SDouglas Gregor 1706718292f2SDouglas Gregor // Parse the opening brace. 1707718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 1708718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 1709718292f2SDouglas Gregor << ModuleName; 1710718292f2SDouglas Gregor HadError = true; 1711718292f2SDouglas Gregor return; 1712718292f2SDouglas Gregor } 1713718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 1714718292f2SDouglas Gregor 1715718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 1716eb90e830SDouglas Gregor if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { 17174a3751ffSRichard Smith // We might see a (re)definition of a module that we already have a 17184a3751ffSRichard Smith // definition for in two cases: 17194a3751ffSRichard Smith // - If we loaded one definition from an AST file and we've just found a 17204a3751ffSRichard Smith // corresponding definition in a module map file, or 17214a3751ffSRichard Smith bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid(); 17224a3751ffSRichard Smith // - If we're building a (preprocessed) module and we've just loaded the 17234a3751ffSRichard Smith // module map file from which it was created. 17244a3751ffSRichard Smith bool ParsedAsMainInput = 17254a3751ffSRichard Smith Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap && 17264a3751ffSRichard Smith Map.LangOpts.CurrentModule == ModuleName && 17274a3751ffSRichard Smith SourceMgr.getDecomposedLoc(ModuleNameLoc).first != 17284a3751ffSRichard Smith SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first; 17294a3751ffSRichard Smith if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) { 1730fcc54a3bSDouglas Gregor // Skip the module definition. 1731fcc54a3bSDouglas Gregor skipUntil(MMToken::RBrace); 1732fcc54a3bSDouglas Gregor if (Tok.is(MMToken::RBrace)) 1733fcc54a3bSDouglas Gregor consumeToken(); 1734fcc54a3bSDouglas Gregor else { 1735fcc54a3bSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 1736fcc54a3bSDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 1737fcc54a3bSDouglas Gregor HadError = true; 1738fcc54a3bSDouglas Gregor } 1739fcc54a3bSDouglas Gregor return; 1740fcc54a3bSDouglas Gregor } 1741fcc54a3bSDouglas Gregor 1742718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 1743718292f2SDouglas Gregor << ModuleName; 1744eb90e830SDouglas Gregor Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition); 1745718292f2SDouglas Gregor 1746718292f2SDouglas Gregor // Skip the module definition. 1747718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 1748718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 1749718292f2SDouglas Gregor consumeToken(); 1750718292f2SDouglas Gregor 1751718292f2SDouglas Gregor HadError = true; 1752718292f2SDouglas Gregor return; 1753718292f2SDouglas Gregor } 1754718292f2SDouglas Gregor 1755718292f2SDouglas Gregor // Start defining this module. 17569d6448b1SBen Langmuir ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework, 17579d6448b1SBen Langmuir Explicit).first; 1758eb90e830SDouglas Gregor ActiveModule->DefinitionLoc = ModuleNameLoc; 1759963c5535SDouglas Gregor if (Attrs.IsSystem || IsSystem) 1760a686e1b0SDouglas Gregor ActiveModule->IsSystem = true; 176177944868SRichard Smith if (Attrs.IsExternC) 176277944868SRichard Smith ActiveModule->IsExternC = true; 1763ed84df00SBruno Cardoso Lopes if (Attrs.NoUndeclaredIncludes || 1764ed84df00SBruno Cardoso Lopes (!ActiveModule->Parent && ModuleName == "Darwin")) 1765ed84df00SBruno Cardoso Lopes ActiveModule->NoUndeclaredIncludes = true; 17663c1a41adSRichard Smith ActiveModule->Directory = Directory; 1767718292f2SDouglas Gregor 17684d867640SGraydon Hoare if (!ActiveModule->Parent) { 17694d867640SGraydon Hoare StringRef MapFileName(ModuleMapFile->getName()); 17704d867640SGraydon Hoare if (MapFileName.endswith("module.private.modulemap") || 17714d867640SGraydon Hoare MapFileName.endswith("module_private.map")) { 17724d867640SGraydon Hoare // Adding a top-level module from a private modulemap is likely a 17734d867640SGraydon Hoare // user error; we check to see if there's another top-level module 17744d867640SGraydon Hoare // defined in the non-private map in the same dir, and if so emit a 17754d867640SGraydon Hoare // warning. 17764d867640SGraydon Hoare for (auto E = Map.module_begin(); E != Map.module_end(); ++E) { 17774d867640SGraydon Hoare auto const *M = E->getValue(); 17784d867640SGraydon Hoare if (!M->Parent && 17794d867640SGraydon Hoare M->Directory == ActiveModule->Directory && 17804d867640SGraydon Hoare M->Name != ActiveModule->Name) { 17814d867640SGraydon Hoare Diags.Report(ActiveModule->DefinitionLoc, 17824d867640SGraydon Hoare diag::warn_mmap_mismatched_top_level_private) 17834d867640SGraydon Hoare << ActiveModule->Name << M->Name; 17844d867640SGraydon Hoare // The pattern we're defending against here is typically due to 17854d867640SGraydon Hoare // a module named FooPrivate which is supposed to be a submodule 17864d867640SGraydon Hoare // called Foo.Private. Emit a fixit in that case. 17874d867640SGraydon Hoare auto D = 17884d867640SGraydon Hoare Diags.Report(ActiveModule->DefinitionLoc, 17894d867640SGraydon Hoare diag::note_mmap_rename_top_level_private_as_submodule); 17904d867640SGraydon Hoare D << ActiveModule->Name << M->Name; 17914d867640SGraydon Hoare StringRef Bad(ActiveModule->Name); 17924d867640SGraydon Hoare if (Bad.consume_back("Private")) { 17934d867640SGraydon Hoare SmallString<128> Fixed = Bad; 17944d867640SGraydon Hoare Fixed.append(".Private"); 17954d867640SGraydon Hoare D << FixItHint::CreateReplacement(ActiveModule->DefinitionLoc, 17964d867640SGraydon Hoare Fixed); 17974d867640SGraydon Hoare } 17984d867640SGraydon Hoare break; 17994d867640SGraydon Hoare } 18004d867640SGraydon Hoare } 18014d867640SGraydon Hoare } 18024d867640SGraydon Hoare } 18034d867640SGraydon Hoare 1804718292f2SDouglas Gregor bool Done = false; 1805718292f2SDouglas Gregor do { 1806718292f2SDouglas Gregor switch (Tok.Kind) { 1807718292f2SDouglas Gregor case MMToken::EndOfFile: 1808718292f2SDouglas Gregor case MMToken::RBrace: 1809718292f2SDouglas Gregor Done = true; 1810718292f2SDouglas Gregor break; 1811718292f2SDouglas Gregor 181235b13eceSDouglas Gregor case MMToken::ConfigMacros: 181335b13eceSDouglas Gregor parseConfigMacros(); 181435b13eceSDouglas Gregor break; 181535b13eceSDouglas Gregor 1816fb912657SDouglas Gregor case MMToken::Conflict: 1817fb912657SDouglas Gregor parseConflict(); 1818fb912657SDouglas Gregor break; 1819fb912657SDouglas Gregor 1820718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 182197292843SDaniel Jasper case MMToken::ExternKeyword: 1822f2161a70SDouglas Gregor case MMToken::FrameworkKeyword: 1823718292f2SDouglas Gregor case MMToken::ModuleKeyword: 1824718292f2SDouglas Gregor parseModuleDecl(); 1825718292f2SDouglas Gregor break; 1826718292f2SDouglas Gregor 18272b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 18282b82c2a5SDouglas Gregor parseExportDecl(); 18292b82c2a5SDouglas Gregor break; 18302b82c2a5SDouglas Gregor 1831*f0b11de2SDouglas Gregor case MMToken::ExportAsKeyword: 1832*f0b11de2SDouglas Gregor parseExportAsDecl(); 1833*f0b11de2SDouglas Gregor break; 1834*f0b11de2SDouglas Gregor 1835ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 1836ba7f2f71SDaniel Jasper parseUseDecl(); 1837ba7f2f71SDaniel Jasper break; 1838ba7f2f71SDaniel Jasper 18391fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 18401fb5c3a6SDouglas Gregor parseRequiresDecl(); 18411fb5c3a6SDouglas Gregor break; 18421fb5c3a6SDouglas Gregor 1843202210b3SRichard Smith case MMToken::TextualKeyword: 1844202210b3SRichard Smith parseHeaderDecl(MMToken::TextualKeyword, consumeToken()); 1845306d8920SRichard Smith break; 1846306d8920SRichard Smith 1847524e33e1SDouglas Gregor case MMToken::UmbrellaKeyword: { 1848524e33e1SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 1849524e33e1SDouglas Gregor if (Tok.is(MMToken::HeaderKeyword)) 1850b53e5483SLawrence Crowl parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc); 1851524e33e1SDouglas Gregor else 1852524e33e1SDouglas Gregor parseUmbrellaDirDecl(UmbrellaLoc); 1853718292f2SDouglas Gregor break; 1854524e33e1SDouglas Gregor } 1855718292f2SDouglas Gregor 1856202210b3SRichard Smith case MMToken::ExcludeKeyword: 1857202210b3SRichard Smith parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken()); 185859527666SDouglas Gregor break; 185959527666SDouglas Gregor 1860202210b3SRichard Smith case MMToken::PrivateKeyword: 1861202210b3SRichard Smith parseHeaderDecl(MMToken::PrivateKeyword, consumeToken()); 1862b53e5483SLawrence Crowl break; 1863b53e5483SLawrence Crowl 1864322f633cSDouglas Gregor case MMToken::HeaderKeyword: 1865202210b3SRichard Smith parseHeaderDecl(MMToken::HeaderKeyword, consumeToken()); 1866718292f2SDouglas Gregor break; 1867718292f2SDouglas Gregor 18686ddfca91SDouglas Gregor case MMToken::LinkKeyword: 18696ddfca91SDouglas Gregor parseLinkDecl(); 18706ddfca91SDouglas Gregor break; 18716ddfca91SDouglas Gregor 1872718292f2SDouglas Gregor default: 1873718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 1874718292f2SDouglas Gregor consumeToken(); 1875718292f2SDouglas Gregor break; 1876718292f2SDouglas Gregor } 1877718292f2SDouglas Gregor } while (!Done); 1878718292f2SDouglas Gregor 1879718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 1880718292f2SDouglas Gregor consumeToken(); 1881718292f2SDouglas Gregor else { 1882718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 1883718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 1884718292f2SDouglas Gregor HadError = true; 1885718292f2SDouglas Gregor } 1886718292f2SDouglas Gregor 188711dfe6feSDouglas Gregor // If the active module is a top-level framework, and there are no link 188811dfe6feSDouglas Gregor // libraries, automatically link against the framework. 188911dfe6feSDouglas Gregor if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() && 189011dfe6feSDouglas Gregor ActiveModule->LinkLibraries.empty()) { 189111dfe6feSDouglas Gregor inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager()); 189211dfe6feSDouglas Gregor } 189311dfe6feSDouglas Gregor 1894ec8c9752SBen Langmuir // If the module meets all requirements but is still unavailable, mark the 1895ec8c9752SBen Langmuir // whole tree as unavailable to prevent it from building. 1896ec8c9752SBen Langmuir if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement && 1897ec8c9752SBen Langmuir ActiveModule->Parent) { 1898ec8c9752SBen Langmuir ActiveModule->getTopLevelModule()->markUnavailable(); 1899ec8c9752SBen Langmuir ActiveModule->getTopLevelModule()->MissingHeaders.append( 1900ec8c9752SBen Langmuir ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end()); 1901ec8c9752SBen Langmuir } 1902ec8c9752SBen Langmuir 1903e7ab3669SDouglas Gregor // We're done parsing this module. Pop back to the previous module. 1904e7ab3669SDouglas Gregor ActiveModule = PreviousActiveModule; 1905718292f2SDouglas Gregor } 1906718292f2SDouglas Gregor 190797292843SDaniel Jasper /// \brief Parse an extern module declaration. 190897292843SDaniel Jasper /// 190997292843SDaniel Jasper /// extern module-declaration: 191097292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 191197292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() { 191297292843SDaniel Jasper assert(Tok.is(MMToken::ExternKeyword)); 1913ae6df27eSRichard Smith SourceLocation ExternLoc = consumeToken(); // 'extern' keyword 191497292843SDaniel Jasper 191597292843SDaniel Jasper // Parse 'module' keyword. 191697292843SDaniel Jasper if (!Tok.is(MMToken::ModuleKeyword)) { 191797292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 191897292843SDaniel Jasper consumeToken(); 191997292843SDaniel Jasper HadError = true; 192097292843SDaniel Jasper return; 192197292843SDaniel Jasper } 192297292843SDaniel Jasper consumeToken(); // 'module' keyword 192397292843SDaniel Jasper 192497292843SDaniel Jasper // Parse the module name. 192597292843SDaniel Jasper ModuleId Id; 192697292843SDaniel Jasper if (parseModuleId(Id)) { 192797292843SDaniel Jasper HadError = true; 192897292843SDaniel Jasper return; 192997292843SDaniel Jasper } 193097292843SDaniel Jasper 193197292843SDaniel Jasper // Parse the referenced module map file name. 193297292843SDaniel Jasper if (!Tok.is(MMToken::StringLiteral)) { 193397292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file); 193497292843SDaniel Jasper HadError = true; 193597292843SDaniel Jasper return; 193697292843SDaniel Jasper } 193797292843SDaniel Jasper std::string FileName = Tok.getString(); 193897292843SDaniel Jasper consumeToken(); // filename 193997292843SDaniel Jasper 194097292843SDaniel Jasper StringRef FileNameRef = FileName; 194197292843SDaniel Jasper SmallString<128> ModuleMapFileName; 194297292843SDaniel Jasper if (llvm::sys::path::is_relative(FileNameRef)) { 194397292843SDaniel Jasper ModuleMapFileName += Directory->getName(); 194497292843SDaniel Jasper llvm::sys::path::append(ModuleMapFileName, FileName); 194592e1b62dSYaron Keren FileNameRef = ModuleMapFileName; 194697292843SDaniel Jasper } 194797292843SDaniel Jasper if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef)) 19489acb99e3SRichard Smith Map.parseModuleMapFile( 19499acb99e3SRichard Smith File, /*IsSystem=*/false, 19509acb99e3SRichard Smith Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd 19519acb99e3SRichard Smith ? Directory 19528128f332SRichard Smith : File->getDir(), 19538128f332SRichard Smith FileID(), nullptr, ExternLoc); 195497292843SDaniel Jasper } 195597292843SDaniel Jasper 19567ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M. 19577ff29148SBen Langmuir /// 19587ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system 19597ff29148SBen Langmuir /// module map files: 19607ff29148SBen Langmuir /// 19617ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which 19627ff29148SBen Langmuir /// should really be mapped to 'textual' now that we have this feature. We 19637ff29148SBen Langmuir /// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to 19647ff29148SBen Langmuir /// true. Later, this bit will be used to map all the headers inside this 19657ff29148SBen Langmuir /// module to 'textual'. 19667ff29148SBen Langmuir /// 19677ff29148SBen Langmuir /// This affects Darwin.C.excluded (for assert.h) and Tcl.Private. 19687ff29148SBen Langmuir /// 19697ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement 19707ff29148SBen Langmuir /// was never correct and causes issues now that we check it, so drop it. 19717ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature, 19727ff29148SBen Langmuir bool &IsRequiresExcludedHack) { 19738013e81dSBenjamin Kramer if (Feature == "excluded" && 19748013e81dSBenjamin Kramer (M->fullModuleNameIs({"Darwin", "C", "excluded"}) || 19758013e81dSBenjamin Kramer M->fullModuleNameIs({"Tcl", "Private"}))) { 19767ff29148SBen Langmuir IsRequiresExcludedHack = true; 19777ff29148SBen Langmuir return false; 19788013e81dSBenjamin Kramer } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) { 19797ff29148SBen Langmuir return false; 19807ff29148SBen Langmuir } 19817ff29148SBen Langmuir 19827ff29148SBen Langmuir return true; 19837ff29148SBen Langmuir } 19847ff29148SBen Langmuir 19851fb5c3a6SDouglas Gregor /// \brief Parse a requires declaration. 19861fb5c3a6SDouglas Gregor /// 19871fb5c3a6SDouglas Gregor /// requires-declaration: 19881fb5c3a6SDouglas Gregor /// 'requires' feature-list 19891fb5c3a6SDouglas Gregor /// 19901fb5c3a6SDouglas Gregor /// feature-list: 1991a3feee2aSRichard Smith /// feature ',' feature-list 1992a3feee2aSRichard Smith /// feature 1993a3feee2aSRichard Smith /// 1994a3feee2aSRichard Smith /// feature: 1995a3feee2aSRichard Smith /// '!'[opt] identifier 19961fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() { 19971fb5c3a6SDouglas Gregor assert(Tok.is(MMToken::RequiresKeyword)); 19981fb5c3a6SDouglas Gregor 19991fb5c3a6SDouglas Gregor // Parse 'requires' keyword. 20001fb5c3a6SDouglas Gregor consumeToken(); 20011fb5c3a6SDouglas Gregor 20021fb5c3a6SDouglas Gregor // Parse the feature-list. 20031fb5c3a6SDouglas Gregor do { 2004a3feee2aSRichard Smith bool RequiredState = true; 2005a3feee2aSRichard Smith if (Tok.is(MMToken::Exclaim)) { 2006a3feee2aSRichard Smith RequiredState = false; 2007a3feee2aSRichard Smith consumeToken(); 2008a3feee2aSRichard Smith } 2009a3feee2aSRichard Smith 20101fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 20111fb5c3a6SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature); 20121fb5c3a6SDouglas Gregor HadError = true; 20131fb5c3a6SDouglas Gregor return; 20141fb5c3a6SDouglas Gregor } 20151fb5c3a6SDouglas Gregor 20161fb5c3a6SDouglas Gregor // Consume the feature name. 20171fb5c3a6SDouglas Gregor std::string Feature = Tok.getString(); 20181fb5c3a6SDouglas Gregor consumeToken(); 20191fb5c3a6SDouglas Gregor 20207ff29148SBen Langmuir bool IsRequiresExcludedHack = false; 20217ff29148SBen Langmuir bool ShouldAddRequirement = 20227ff29148SBen Langmuir shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack); 20237ff29148SBen Langmuir 20247ff29148SBen Langmuir if (IsRequiresExcludedHack) 20257ff29148SBen Langmuir UsesRequiresExcludedHack.insert(ActiveModule); 20267ff29148SBen Langmuir 20277ff29148SBen Langmuir if (ShouldAddRequirement) { 20281fb5c3a6SDouglas Gregor // Add this feature. 20297ff29148SBen Langmuir ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts, 20307ff29148SBen Langmuir *Map.Target); 20317ff29148SBen Langmuir } 20321fb5c3a6SDouglas Gregor 20331fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Comma)) 20341fb5c3a6SDouglas Gregor break; 20351fb5c3a6SDouglas Gregor 20361fb5c3a6SDouglas Gregor // Consume the comma. 20371fb5c3a6SDouglas Gregor consumeToken(); 20381fb5c3a6SDouglas Gregor } while (true); 20391fb5c3a6SDouglas Gregor } 20401fb5c3a6SDouglas Gregor 2041718292f2SDouglas Gregor /// \brief Parse a header declaration. 2042718292f2SDouglas Gregor /// 2043718292f2SDouglas Gregor /// header-declaration: 2044306d8920SRichard Smith /// 'textual'[opt] 'header' string-literal 2045202210b3SRichard Smith /// 'private' 'textual'[opt] 'header' string-literal 2046202210b3SRichard Smith /// 'exclude' 'header' string-literal 2047202210b3SRichard Smith /// 'umbrella' 'header' string-literal 2048306d8920SRichard Smith /// 2049306d8920SRichard Smith /// FIXME: Support 'private textual header'. 2050b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, 2051b53e5483SLawrence Crowl SourceLocation LeadingLoc) { 2052202210b3SRichard Smith // We've already consumed the first token. 2053202210b3SRichard Smith ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader; 2054202210b3SRichard Smith if (LeadingToken == MMToken::PrivateKeyword) { 2055202210b3SRichard Smith Role = ModuleMap::PrivateHeader; 2056202210b3SRichard Smith // 'private' may optionally be followed by 'textual'. 2057202210b3SRichard Smith if (Tok.is(MMToken::TextualKeyword)) { 2058202210b3SRichard Smith LeadingToken = Tok.Kind; 20591871ed3dSBenjamin Kramer consumeToken(); 2060202210b3SRichard Smith } 2061202210b3SRichard Smith } 20627ff29148SBen Langmuir 2063202210b3SRichard Smith if (LeadingToken == MMToken::TextualKeyword) 2064202210b3SRichard Smith Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 2065202210b3SRichard Smith 20667ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 20677ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 20687ff29148SBen Langmuir // Module::UsesRequiresExcludedHack). 20697ff29148SBen Langmuir Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 20707ff29148SBen Langmuir } 20717ff29148SBen Langmuir 2072202210b3SRichard Smith if (LeadingToken != MMToken::HeaderKeyword) { 2073202210b3SRichard Smith if (!Tok.is(MMToken::HeaderKeyword)) { 2074202210b3SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2075202210b3SRichard Smith << (LeadingToken == MMToken::PrivateKeyword ? "private" : 2076202210b3SRichard Smith LeadingToken == MMToken::ExcludeKeyword ? "exclude" : 2077202210b3SRichard Smith LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella"); 2078202210b3SRichard Smith return; 2079202210b3SRichard Smith } 2080202210b3SRichard Smith consumeToken(); 2081202210b3SRichard Smith } 2082718292f2SDouglas Gregor 2083718292f2SDouglas Gregor // Parse the header name. 2084718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2085718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2086718292f2SDouglas Gregor << "header"; 2087718292f2SDouglas Gregor HadError = true; 2088718292f2SDouglas Gregor return; 2089718292f2SDouglas Gregor } 20903c1a41adSRichard Smith Module::UnresolvedHeaderDirective Header; 20910761a8a0SDaniel Jasper Header.FileName = Tok.getString(); 20920761a8a0SDaniel Jasper Header.FileNameLoc = consumeToken(); 20931d60987fSRichard Smith Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword; 2094040e1266SRichard Smith Header.Kind = 2095040e1266SRichard Smith (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded 2096040e1266SRichard Smith : Map.headerRoleToKind(Role)); 2097718292f2SDouglas Gregor 2098524e33e1SDouglas Gregor // Check whether we already have an umbrella. 20991d60987fSRichard Smith if (Header.IsUmbrella && ActiveModule->Umbrella) { 21000761a8a0SDaniel Jasper Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) 2101524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2102322f633cSDouglas Gregor HadError = true; 2103322f633cSDouglas Gregor return; 2104322f633cSDouglas Gregor } 2105322f633cSDouglas Gregor 2106040e1266SRichard Smith // If we were given stat information, parse it so we can skip looking for 2107040e1266SRichard Smith // the file. 2108040e1266SRichard Smith if (Tok.is(MMToken::LBrace)) { 2109040e1266SRichard Smith SourceLocation LBraceLoc = consumeToken(); 21103ec6663bSDouglas Gregor 2111040e1266SRichard Smith while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) { 2112040e1266SRichard Smith enum Attribute { Size, ModTime, Unknown }; 2113040e1266SRichard Smith StringRef Str = Tok.getString(); 2114040e1266SRichard Smith SourceLocation Loc = consumeToken(); 2115040e1266SRichard Smith switch (llvm::StringSwitch<Attribute>(Str) 2116040e1266SRichard Smith .Case("size", Size) 2117040e1266SRichard Smith .Case("mtime", ModTime) 2118040e1266SRichard Smith .Default(Unknown)) { 2119040e1266SRichard Smith case Size: 2120040e1266SRichard Smith if (Header.Size) 2121040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2122040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2123040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2124040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2125040e1266SRichard Smith skipUntil(MMToken::RBrace); 2126040e1266SRichard Smith break; 2127040e1266SRichard Smith } 2128040e1266SRichard Smith Header.Size = Tok.getInteger(); 2129040e1266SRichard Smith consumeToken(); 2130040e1266SRichard Smith break; 2131040e1266SRichard Smith 2132040e1266SRichard Smith case ModTime: 2133040e1266SRichard Smith if (Header.ModTime) 2134040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2135040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2136040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2137040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2138040e1266SRichard Smith skipUntil(MMToken::RBrace); 2139040e1266SRichard Smith break; 2140040e1266SRichard Smith } 2141040e1266SRichard Smith Header.ModTime = Tok.getInteger(); 2142040e1266SRichard Smith consumeToken(); 2143040e1266SRichard Smith break; 2144040e1266SRichard Smith 2145040e1266SRichard Smith case Unknown: 2146040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_expected_header_attribute); 2147040e1266SRichard Smith skipUntil(MMToken::RBrace); 2148040e1266SRichard Smith break; 2149040e1266SRichard Smith } 21503ec6663bSDouglas Gregor } 21515257fc63SDouglas Gregor 2152040e1266SRichard Smith if (Tok.is(MMToken::RBrace)) 2153040e1266SRichard Smith consumeToken(); 2154040e1266SRichard Smith else { 2155040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 2156040e1266SRichard Smith Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 2157322f633cSDouglas Gregor HadError = true; 2158322f633cSDouglas Gregor } 21590101b540SHans Wennborg } 216025d50758SRichard Smith 2161040e1266SRichard Smith Map.addUnresolvedHeader(ActiveModule, std::move(Header)); 2162718292f2SDouglas Gregor } 2163718292f2SDouglas Gregor 216441f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A, 216541f81994SBen Langmuir const Module::Header *B) { 216641f81994SBen Langmuir return A->NameAsWritten.compare(B->NameAsWritten); 216741f81994SBen Langmuir } 216841f81994SBen Langmuir 2169524e33e1SDouglas Gregor /// \brief Parse an umbrella directory declaration. 2170524e33e1SDouglas Gregor /// 2171524e33e1SDouglas Gregor /// umbrella-dir-declaration: 2172524e33e1SDouglas Gregor /// umbrella string-literal 2173524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { 2174524e33e1SDouglas Gregor // Parse the directory name. 2175524e33e1SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2176524e33e1SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2177524e33e1SDouglas Gregor << "umbrella"; 2178524e33e1SDouglas Gregor HadError = true; 2179524e33e1SDouglas Gregor return; 2180524e33e1SDouglas Gregor } 2181524e33e1SDouglas Gregor 2182524e33e1SDouglas Gregor std::string DirName = Tok.getString(); 2183524e33e1SDouglas Gregor SourceLocation DirNameLoc = consumeToken(); 2184524e33e1SDouglas Gregor 2185524e33e1SDouglas Gregor // Check whether we already have an umbrella. 2186524e33e1SDouglas Gregor if (ActiveModule->Umbrella) { 2187524e33e1SDouglas Gregor Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash) 2188524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2189524e33e1SDouglas Gregor HadError = true; 2190524e33e1SDouglas Gregor return; 2191524e33e1SDouglas Gregor } 2192524e33e1SDouglas Gregor 2193524e33e1SDouglas Gregor // Look for this file. 2194d2d442caSCraig Topper const DirectoryEntry *Dir = nullptr; 2195524e33e1SDouglas Gregor if (llvm::sys::path::is_absolute(DirName)) 2196524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(DirName); 2197524e33e1SDouglas Gregor else { 21982c1dd271SDylan Noblesmith SmallString<128> PathName; 2199524e33e1SDouglas Gregor PathName = Directory->getName(); 2200524e33e1SDouglas Gregor llvm::sys::path::append(PathName, DirName); 2201524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(PathName); 2202524e33e1SDouglas Gregor } 2203524e33e1SDouglas Gregor 2204524e33e1SDouglas Gregor if (!Dir) { 2205a0320b97SVassil Vassilev Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found) 2206524e33e1SDouglas Gregor << DirName; 2207524e33e1SDouglas Gregor return; 2208524e33e1SDouglas Gregor } 2209524e33e1SDouglas Gregor 22107ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 22117ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 22127ff29148SBen Langmuir // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the 22137ff29148SBen Langmuir // directory is relatively expensive, in practice this only applies to the 22147ff29148SBen Langmuir // uncommonly used Tcl module on Darwin platforms. 22157ff29148SBen Langmuir std::error_code EC; 22167ff29148SBen Langmuir SmallVector<Module::Header, 6> Headers; 2217b171a59bSBruno Cardoso Lopes vfs::FileSystem &FS = *SourceMgr.getFileManager().getVirtualFileSystem(); 2218b171a59bSBruno Cardoso Lopes for (vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E; 22197ff29148SBen Langmuir I != E && !EC; I.increment(EC)) { 2220b171a59bSBruno Cardoso Lopes if (const FileEntry *FE = 2221b171a59bSBruno Cardoso Lopes SourceMgr.getFileManager().getFile(I->getName())) { 22227ff29148SBen Langmuir 2223b171a59bSBruno Cardoso Lopes Module::Header Header = {I->getName(), FE}; 22247ff29148SBen Langmuir Headers.push_back(std::move(Header)); 22257ff29148SBen Langmuir } 22267ff29148SBen Langmuir } 22277ff29148SBen Langmuir 22287ff29148SBen Langmuir // Sort header paths so that the pcm doesn't depend on iteration order. 222941f81994SBen Langmuir llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders); 223041f81994SBen Langmuir 22317ff29148SBen Langmuir for (auto &Header : Headers) 22327ff29148SBen Langmuir Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader); 22337ff29148SBen Langmuir return; 22347ff29148SBen Langmuir } 22357ff29148SBen Langmuir 2236524e33e1SDouglas Gregor if (Module *OwningModule = Map.UmbrellaDirs[Dir]) { 2237524e33e1SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 2238524e33e1SDouglas Gregor << OwningModule->getFullModuleName(); 2239524e33e1SDouglas Gregor HadError = true; 2240524e33e1SDouglas Gregor return; 2241524e33e1SDouglas Gregor } 2242524e33e1SDouglas Gregor 2243524e33e1SDouglas Gregor // Record this umbrella directory. 22442b63d15fSRichard Smith Map.setUmbrellaDir(ActiveModule, Dir, DirName); 2245524e33e1SDouglas Gregor } 2246524e33e1SDouglas Gregor 22472b82c2a5SDouglas Gregor /// \brief Parse a module export declaration. 22482b82c2a5SDouglas Gregor /// 22492b82c2a5SDouglas Gregor /// export-declaration: 22502b82c2a5SDouglas Gregor /// 'export' wildcard-module-id 22512b82c2a5SDouglas Gregor /// 22522b82c2a5SDouglas Gregor /// wildcard-module-id: 22532b82c2a5SDouglas Gregor /// identifier 22542b82c2a5SDouglas Gregor /// '*' 22552b82c2a5SDouglas Gregor /// identifier '.' wildcard-module-id 22562b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() { 22572b82c2a5SDouglas Gregor assert(Tok.is(MMToken::ExportKeyword)); 22582b82c2a5SDouglas Gregor SourceLocation ExportLoc = consumeToken(); 22592b82c2a5SDouglas Gregor 22602b82c2a5SDouglas Gregor // Parse the module-id with an optional wildcard at the end. 22612b82c2a5SDouglas Gregor ModuleId ParsedModuleId; 22622b82c2a5SDouglas Gregor bool Wildcard = false; 22632b82c2a5SDouglas Gregor do { 2264306d8920SRichard Smith // FIXME: Support string-literal module names here. 22652b82c2a5SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 22662b82c2a5SDouglas Gregor ParsedModuleId.push_back(std::make_pair(Tok.getString(), 22672b82c2a5SDouglas Gregor Tok.getLocation())); 22682b82c2a5SDouglas Gregor consumeToken(); 22692b82c2a5SDouglas Gregor 22702b82c2a5SDouglas Gregor if (Tok.is(MMToken::Period)) { 22712b82c2a5SDouglas Gregor consumeToken(); 22722b82c2a5SDouglas Gregor continue; 22732b82c2a5SDouglas Gregor } 22742b82c2a5SDouglas Gregor 22752b82c2a5SDouglas Gregor break; 22762b82c2a5SDouglas Gregor } 22772b82c2a5SDouglas Gregor 22782b82c2a5SDouglas Gregor if(Tok.is(MMToken::Star)) { 22792b82c2a5SDouglas Gregor Wildcard = true; 2280f5eedd05SDouglas Gregor consumeToken(); 22812b82c2a5SDouglas Gregor break; 22822b82c2a5SDouglas Gregor } 22832b82c2a5SDouglas Gregor 2284ba7f2f71SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_module_id); 22852b82c2a5SDouglas Gregor HadError = true; 22862b82c2a5SDouglas Gregor return; 22872b82c2a5SDouglas Gregor } while (true); 22882b82c2a5SDouglas Gregor 22892b82c2a5SDouglas Gregor Module::UnresolvedExportDecl Unresolved = { 22902b82c2a5SDouglas Gregor ExportLoc, ParsedModuleId, Wildcard 22912b82c2a5SDouglas Gregor }; 22922b82c2a5SDouglas Gregor ActiveModule->UnresolvedExports.push_back(Unresolved); 22932b82c2a5SDouglas Gregor } 22942b82c2a5SDouglas Gregor 2295*f0b11de2SDouglas Gregor /// \brief Parse a module export_as declaration. 2296*f0b11de2SDouglas Gregor /// 2297*f0b11de2SDouglas Gregor /// export-as-declaration: 2298*f0b11de2SDouglas Gregor /// 'export_as' identifier 2299*f0b11de2SDouglas Gregor void ModuleMapParser::parseExportAsDecl() { 2300*f0b11de2SDouglas Gregor assert(Tok.is(MMToken::ExportAsKeyword)); 2301*f0b11de2SDouglas Gregor consumeToken(); 2302*f0b11de2SDouglas Gregor 2303*f0b11de2SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 2304*f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_module_id); 2305*f0b11de2SDouglas Gregor HadError = true; 2306*f0b11de2SDouglas Gregor return; 2307*f0b11de2SDouglas Gregor } 2308*f0b11de2SDouglas Gregor 2309*f0b11de2SDouglas Gregor if (ActiveModule->Parent) { 2310*f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_submodule_export_as); 2311*f0b11de2SDouglas Gregor consumeToken(); 2312*f0b11de2SDouglas Gregor return; 2313*f0b11de2SDouglas Gregor } 2314*f0b11de2SDouglas Gregor 2315*f0b11de2SDouglas Gregor if (!ActiveModule->ExportAsModule.empty()) { 2316*f0b11de2SDouglas Gregor if (ActiveModule->ExportAsModule == Tok.getString()) { 2317*f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_redundant_export_as) 2318*f0b11de2SDouglas Gregor << ActiveModule->Name << Tok.getString(); 2319*f0b11de2SDouglas Gregor } else { 2320*f0b11de2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_conflicting_export_as) 2321*f0b11de2SDouglas Gregor << ActiveModule->Name << ActiveModule->ExportAsModule 2322*f0b11de2SDouglas Gregor << Tok.getString(); 2323*f0b11de2SDouglas Gregor } 2324*f0b11de2SDouglas Gregor } 2325*f0b11de2SDouglas Gregor 2326*f0b11de2SDouglas Gregor ActiveModule->ExportAsModule = Tok.getString(); 2327*f0b11de2SDouglas Gregor consumeToken(); 2328*f0b11de2SDouglas Gregor } 2329*f0b11de2SDouglas Gregor 23308f4d3ff1SRichard Smith /// \brief Parse a module use declaration. 2331ba7f2f71SDaniel Jasper /// 23328f4d3ff1SRichard Smith /// use-declaration: 23338f4d3ff1SRichard Smith /// 'use' wildcard-module-id 2334ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() { 2335ba7f2f71SDaniel Jasper assert(Tok.is(MMToken::UseKeyword)); 23368f4d3ff1SRichard Smith auto KWLoc = consumeToken(); 2337ba7f2f71SDaniel Jasper // Parse the module-id. 2338ba7f2f71SDaniel Jasper ModuleId ParsedModuleId; 23393cd34c76SDaniel Jasper parseModuleId(ParsedModuleId); 2340ba7f2f71SDaniel Jasper 23418f4d3ff1SRichard Smith if (ActiveModule->Parent) 23428f4d3ff1SRichard Smith Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule); 23438f4d3ff1SRichard Smith else 2344ba7f2f71SDaniel Jasper ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId); 2345ba7f2f71SDaniel Jasper } 2346ba7f2f71SDaniel Jasper 23476ddfca91SDouglas Gregor /// \brief Parse a link declaration. 23486ddfca91SDouglas Gregor /// 23496ddfca91SDouglas Gregor /// module-declaration: 23506ddfca91SDouglas Gregor /// 'link' 'framework'[opt] string-literal 23516ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() { 23526ddfca91SDouglas Gregor assert(Tok.is(MMToken::LinkKeyword)); 23536ddfca91SDouglas Gregor SourceLocation LinkLoc = consumeToken(); 23546ddfca91SDouglas Gregor 23556ddfca91SDouglas Gregor // Parse the optional 'framework' keyword. 23566ddfca91SDouglas Gregor bool IsFramework = false; 23576ddfca91SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 23586ddfca91SDouglas Gregor consumeToken(); 23596ddfca91SDouglas Gregor IsFramework = true; 23606ddfca91SDouglas Gregor } 23616ddfca91SDouglas Gregor 23626ddfca91SDouglas Gregor // Parse the library name 23636ddfca91SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 23646ddfca91SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name) 23656ddfca91SDouglas Gregor << IsFramework << SourceRange(LinkLoc); 23666ddfca91SDouglas Gregor HadError = true; 23676ddfca91SDouglas Gregor return; 23686ddfca91SDouglas Gregor } 23696ddfca91SDouglas Gregor 23706ddfca91SDouglas Gregor std::string LibraryName = Tok.getString(); 23716ddfca91SDouglas Gregor consumeToken(); 23726ddfca91SDouglas Gregor ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName, 23736ddfca91SDouglas Gregor IsFramework)); 23746ddfca91SDouglas Gregor } 23756ddfca91SDouglas Gregor 237635b13eceSDouglas Gregor /// \brief Parse a configuration macro declaration. 237735b13eceSDouglas Gregor /// 237835b13eceSDouglas Gregor /// module-declaration: 237935b13eceSDouglas Gregor /// 'config_macros' attributes[opt] config-macro-list? 238035b13eceSDouglas Gregor /// 238135b13eceSDouglas Gregor /// config-macro-list: 238235b13eceSDouglas Gregor /// identifier (',' identifier)? 238335b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() { 238435b13eceSDouglas Gregor assert(Tok.is(MMToken::ConfigMacros)); 238535b13eceSDouglas Gregor SourceLocation ConfigMacrosLoc = consumeToken(); 238635b13eceSDouglas Gregor 238735b13eceSDouglas Gregor // Only top-level modules can have configuration macros. 238835b13eceSDouglas Gregor if (ActiveModule->Parent) { 238935b13eceSDouglas Gregor Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule); 239035b13eceSDouglas Gregor } 239135b13eceSDouglas Gregor 239235b13eceSDouglas Gregor // Parse the optional attributes. 239335b13eceSDouglas Gregor Attributes Attrs; 23945d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 23955d29dee0SDavide Italiano return; 23965d29dee0SDavide Italiano 239735b13eceSDouglas Gregor if (Attrs.IsExhaustive && !ActiveModule->Parent) { 239835b13eceSDouglas Gregor ActiveModule->ConfigMacrosExhaustive = true; 239935b13eceSDouglas Gregor } 240035b13eceSDouglas Gregor 240135b13eceSDouglas Gregor // If we don't have an identifier, we're done. 2402306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 240335b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) 240435b13eceSDouglas Gregor return; 240535b13eceSDouglas Gregor 240635b13eceSDouglas Gregor // Consume the first identifier. 240735b13eceSDouglas Gregor if (!ActiveModule->Parent) { 240835b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 240935b13eceSDouglas Gregor } 241035b13eceSDouglas Gregor consumeToken(); 241135b13eceSDouglas Gregor 241235b13eceSDouglas Gregor do { 241335b13eceSDouglas Gregor // If there's a comma, consume it. 241435b13eceSDouglas Gregor if (!Tok.is(MMToken::Comma)) 241535b13eceSDouglas Gregor break; 241635b13eceSDouglas Gregor consumeToken(); 241735b13eceSDouglas Gregor 241835b13eceSDouglas Gregor // We expect to see a macro name here. 2419306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 242035b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 242135b13eceSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro); 242235b13eceSDouglas Gregor break; 242335b13eceSDouglas Gregor } 242435b13eceSDouglas Gregor 242535b13eceSDouglas Gregor // Consume the macro name. 242635b13eceSDouglas Gregor if (!ActiveModule->Parent) { 242735b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 242835b13eceSDouglas Gregor } 242935b13eceSDouglas Gregor consumeToken(); 243035b13eceSDouglas Gregor } while (true); 243135b13eceSDouglas Gregor } 243235b13eceSDouglas Gregor 2433fb912657SDouglas Gregor /// \brief Format a module-id into a string. 2434fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) { 2435fb912657SDouglas Gregor std::string result; 2436fb912657SDouglas Gregor { 2437fb912657SDouglas Gregor llvm::raw_string_ostream OS(result); 2438fb912657SDouglas Gregor 2439fb912657SDouglas Gregor for (unsigned I = 0, N = Id.size(); I != N; ++I) { 2440fb912657SDouglas Gregor if (I) 2441fb912657SDouglas Gregor OS << "."; 2442fb912657SDouglas Gregor OS << Id[I].first; 2443fb912657SDouglas Gregor } 2444fb912657SDouglas Gregor } 2445fb912657SDouglas Gregor 2446fb912657SDouglas Gregor return result; 2447fb912657SDouglas Gregor } 2448fb912657SDouglas Gregor 2449fb912657SDouglas Gregor /// \brief Parse a conflict declaration. 2450fb912657SDouglas Gregor /// 2451fb912657SDouglas Gregor /// module-declaration: 2452fb912657SDouglas Gregor /// 'conflict' module-id ',' string-literal 2453fb912657SDouglas Gregor void ModuleMapParser::parseConflict() { 2454fb912657SDouglas Gregor assert(Tok.is(MMToken::Conflict)); 2455fb912657SDouglas Gregor SourceLocation ConflictLoc = consumeToken(); 2456fb912657SDouglas Gregor Module::UnresolvedConflict Conflict; 2457fb912657SDouglas Gregor 2458fb912657SDouglas Gregor // Parse the module-id. 2459fb912657SDouglas Gregor if (parseModuleId(Conflict.Id)) 2460fb912657SDouglas Gregor return; 2461fb912657SDouglas Gregor 2462fb912657SDouglas Gregor // Parse the ','. 2463fb912657SDouglas Gregor if (!Tok.is(MMToken::Comma)) { 2464fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma) 2465fb912657SDouglas Gregor << SourceRange(ConflictLoc); 2466fb912657SDouglas Gregor return; 2467fb912657SDouglas Gregor } 2468fb912657SDouglas Gregor consumeToken(); 2469fb912657SDouglas Gregor 2470fb912657SDouglas Gregor // Parse the message. 2471fb912657SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2472fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message) 2473fb912657SDouglas Gregor << formatModuleId(Conflict.Id); 2474fb912657SDouglas Gregor return; 2475fb912657SDouglas Gregor } 2476fb912657SDouglas Gregor Conflict.Message = Tok.getString().str(); 2477fb912657SDouglas Gregor consumeToken(); 2478fb912657SDouglas Gregor 2479fb912657SDouglas Gregor // Add this unresolved conflict. 2480fb912657SDouglas Gregor ActiveModule->UnresolvedConflicts.push_back(Conflict); 2481fb912657SDouglas Gregor } 2482fb912657SDouglas Gregor 24836ddfca91SDouglas Gregor /// \brief Parse an inferred module declaration (wildcard modules). 24849194a91dSDouglas Gregor /// 24859194a91dSDouglas Gregor /// module-declaration: 24869194a91dSDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt] 24879194a91dSDouglas Gregor /// { inferred-module-member* } 24889194a91dSDouglas Gregor /// 24899194a91dSDouglas Gregor /// inferred-module-member: 24909194a91dSDouglas Gregor /// 'export' '*' 24919194a91dSDouglas Gregor /// 'exclude' identifier 24929194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { 249373441091SDouglas Gregor assert(Tok.is(MMToken::Star)); 249473441091SDouglas Gregor SourceLocation StarLoc = consumeToken(); 249573441091SDouglas Gregor bool Failed = false; 249673441091SDouglas Gregor 249773441091SDouglas Gregor // Inferred modules must be submodules. 24989194a91dSDouglas Gregor if (!ActiveModule && !Framework) { 249973441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule); 250073441091SDouglas Gregor Failed = true; 250173441091SDouglas Gregor } 250273441091SDouglas Gregor 25039194a91dSDouglas Gregor if (ActiveModule) { 2504524e33e1SDouglas Gregor // Inferred modules must have umbrella directories. 25054898cde4SBen Langmuir if (!Failed && ActiveModule->IsAvailable && 25064898cde4SBen Langmuir !ActiveModule->getUmbrellaDir()) { 250773441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); 250873441091SDouglas Gregor Failed = true; 250973441091SDouglas Gregor } 251073441091SDouglas Gregor 251173441091SDouglas Gregor // Check for redefinition of an inferred module. 2512dd005f69SDouglas Gregor if (!Failed && ActiveModule->InferSubmodules) { 251373441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_redef); 2514dd005f69SDouglas Gregor if (ActiveModule->InferredSubmoduleLoc.isValid()) 2515dd005f69SDouglas Gregor Diags.Report(ActiveModule->InferredSubmoduleLoc, 251673441091SDouglas Gregor diag::note_mmap_prev_definition); 251773441091SDouglas Gregor Failed = true; 251873441091SDouglas Gregor } 251973441091SDouglas Gregor 25209194a91dSDouglas Gregor // Check for the 'framework' keyword, which is not permitted here. 25219194a91dSDouglas Gregor if (Framework) { 25229194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule); 25239194a91dSDouglas Gregor Framework = false; 25249194a91dSDouglas Gregor } 25259194a91dSDouglas Gregor } else if (Explicit) { 25269194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework); 25279194a91dSDouglas Gregor Explicit = false; 25289194a91dSDouglas Gregor } 25299194a91dSDouglas Gregor 253073441091SDouglas Gregor // If there were any problems with this inferred submodule, skip its body. 253173441091SDouglas Gregor if (Failed) { 253273441091SDouglas Gregor if (Tok.is(MMToken::LBrace)) { 253373441091SDouglas Gregor consumeToken(); 253473441091SDouglas Gregor skipUntil(MMToken::RBrace); 253573441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 253673441091SDouglas Gregor consumeToken(); 253773441091SDouglas Gregor } 253873441091SDouglas Gregor HadError = true; 253973441091SDouglas Gregor return; 254073441091SDouglas Gregor } 254173441091SDouglas Gregor 25429194a91dSDouglas Gregor // Parse optional attributes. 25434442605fSBill Wendling Attributes Attrs; 25445d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 25455d29dee0SDavide Italiano return; 25469194a91dSDouglas Gregor 25479194a91dSDouglas Gregor if (ActiveModule) { 254873441091SDouglas Gregor // Note that we have an inferred submodule. 2549dd005f69SDouglas Gregor ActiveModule->InferSubmodules = true; 2550dd005f69SDouglas Gregor ActiveModule->InferredSubmoduleLoc = StarLoc; 2551dd005f69SDouglas Gregor ActiveModule->InferExplicitSubmodules = Explicit; 25529194a91dSDouglas Gregor } else { 25539194a91dSDouglas Gregor // We'll be inferring framework modules for this directory. 25549194a91dSDouglas Gregor Map.InferredDirectories[Directory].InferModules = true; 2555c1d88ea5SBen Langmuir Map.InferredDirectories[Directory].Attrs = Attrs; 2556beee15e7SBen Langmuir Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile; 2557131daca0SRichard Smith // FIXME: Handle the 'framework' keyword. 25589194a91dSDouglas Gregor } 255973441091SDouglas Gregor 256073441091SDouglas Gregor // Parse the opening brace. 256173441091SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 256273441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard); 256373441091SDouglas Gregor HadError = true; 256473441091SDouglas Gregor return; 256573441091SDouglas Gregor } 256673441091SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 256773441091SDouglas Gregor 256873441091SDouglas Gregor // Parse the body of the inferred submodule. 256973441091SDouglas Gregor bool Done = false; 257073441091SDouglas Gregor do { 257173441091SDouglas Gregor switch (Tok.Kind) { 257273441091SDouglas Gregor case MMToken::EndOfFile: 257373441091SDouglas Gregor case MMToken::RBrace: 257473441091SDouglas Gregor Done = true; 257573441091SDouglas Gregor break; 257673441091SDouglas Gregor 25779194a91dSDouglas Gregor case MMToken::ExcludeKeyword: { 25789194a91dSDouglas Gregor if (ActiveModule) { 25799194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2580d2d442caSCraig Topper << (ActiveModule != nullptr); 25819194a91dSDouglas Gregor consumeToken(); 25829194a91dSDouglas Gregor break; 25839194a91dSDouglas Gregor } 25849194a91dSDouglas Gregor 25859194a91dSDouglas Gregor consumeToken(); 2586306d8920SRichard Smith // FIXME: Support string-literal module names here. 25879194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 25889194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name); 25899194a91dSDouglas Gregor break; 25909194a91dSDouglas Gregor } 25919194a91dSDouglas Gregor 25929194a91dSDouglas Gregor Map.InferredDirectories[Directory].ExcludedModules 25939194a91dSDouglas Gregor .push_back(Tok.getString()); 25949194a91dSDouglas Gregor consumeToken(); 25959194a91dSDouglas Gregor break; 25969194a91dSDouglas Gregor } 25979194a91dSDouglas Gregor 25989194a91dSDouglas Gregor case MMToken::ExportKeyword: 25999194a91dSDouglas Gregor if (!ActiveModule) { 26009194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2601d2d442caSCraig Topper << (ActiveModule != nullptr); 26029194a91dSDouglas Gregor consumeToken(); 26039194a91dSDouglas Gregor break; 26049194a91dSDouglas Gregor } 26059194a91dSDouglas Gregor 260673441091SDouglas Gregor consumeToken(); 260773441091SDouglas Gregor if (Tok.is(MMToken::Star)) 2608dd005f69SDouglas Gregor ActiveModule->InferExportWildcard = true; 260973441091SDouglas Gregor else 261073441091SDouglas Gregor Diags.Report(Tok.getLocation(), 261173441091SDouglas Gregor diag::err_mmap_expected_export_wildcard); 261273441091SDouglas Gregor consumeToken(); 261373441091SDouglas Gregor break; 261473441091SDouglas Gregor 261573441091SDouglas Gregor case MMToken::ExplicitKeyword: 261673441091SDouglas Gregor case MMToken::ModuleKeyword: 261773441091SDouglas Gregor case MMToken::HeaderKeyword: 2618b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 261973441091SDouglas Gregor case MMToken::UmbrellaKeyword: 262073441091SDouglas Gregor default: 26219194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2622d2d442caSCraig Topper << (ActiveModule != nullptr); 262373441091SDouglas Gregor consumeToken(); 262473441091SDouglas Gregor break; 262573441091SDouglas Gregor } 262673441091SDouglas Gregor } while (!Done); 262773441091SDouglas Gregor 262873441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 262973441091SDouglas Gregor consumeToken(); 263073441091SDouglas Gregor else { 263173441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 263273441091SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 263373441091SDouglas Gregor HadError = true; 263473441091SDouglas Gregor } 263573441091SDouglas Gregor } 263673441091SDouglas Gregor 26379194a91dSDouglas Gregor /// \brief Parse optional attributes. 26389194a91dSDouglas Gregor /// 26399194a91dSDouglas Gregor /// attributes: 26409194a91dSDouglas Gregor /// attribute attributes 26419194a91dSDouglas Gregor /// attribute 26429194a91dSDouglas Gregor /// 26439194a91dSDouglas Gregor /// attribute: 26449194a91dSDouglas Gregor /// [ identifier ] 26459194a91dSDouglas Gregor /// 26469194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes. 26479194a91dSDouglas Gregor /// 26489194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise. 26494442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { 26509194a91dSDouglas Gregor bool HadError = false; 26519194a91dSDouglas Gregor 26529194a91dSDouglas Gregor while (Tok.is(MMToken::LSquare)) { 26539194a91dSDouglas Gregor // Consume the '['. 26549194a91dSDouglas Gregor SourceLocation LSquareLoc = consumeToken(); 26559194a91dSDouglas Gregor 26569194a91dSDouglas Gregor // Check whether we have an attribute name here. 26579194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 26589194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute); 26599194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 26609194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 26619194a91dSDouglas Gregor consumeToken(); 26629194a91dSDouglas Gregor HadError = true; 26639194a91dSDouglas Gregor } 26649194a91dSDouglas Gregor 26659194a91dSDouglas Gregor // Decode the attribute name. 26669194a91dSDouglas Gregor AttributeKind Attribute 26679194a91dSDouglas Gregor = llvm::StringSwitch<AttributeKind>(Tok.getString()) 266835b13eceSDouglas Gregor .Case("exhaustive", AT_exhaustive) 266977944868SRichard Smith .Case("extern_c", AT_extern_c) 2670ed84df00SBruno Cardoso Lopes .Case("no_undeclared_includes", AT_no_undeclared_includes) 26719194a91dSDouglas Gregor .Case("system", AT_system) 26729194a91dSDouglas Gregor .Default(AT_unknown); 26739194a91dSDouglas Gregor switch (Attribute) { 26749194a91dSDouglas Gregor case AT_unknown: 26759194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute) 26769194a91dSDouglas Gregor << Tok.getString(); 26779194a91dSDouglas Gregor break; 26789194a91dSDouglas Gregor 26799194a91dSDouglas Gregor case AT_system: 26809194a91dSDouglas Gregor Attrs.IsSystem = true; 26819194a91dSDouglas Gregor break; 268235b13eceSDouglas Gregor 268377944868SRichard Smith case AT_extern_c: 268477944868SRichard Smith Attrs.IsExternC = true; 268577944868SRichard Smith break; 268677944868SRichard Smith 268735b13eceSDouglas Gregor case AT_exhaustive: 268835b13eceSDouglas Gregor Attrs.IsExhaustive = true; 268935b13eceSDouglas Gregor break; 2690ed84df00SBruno Cardoso Lopes 2691ed84df00SBruno Cardoso Lopes case AT_no_undeclared_includes: 2692ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes = true; 2693ed84df00SBruno Cardoso Lopes break; 26949194a91dSDouglas Gregor } 26959194a91dSDouglas Gregor consumeToken(); 26969194a91dSDouglas Gregor 26979194a91dSDouglas Gregor // Consume the ']'. 26989194a91dSDouglas Gregor if (!Tok.is(MMToken::RSquare)) { 26999194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare); 27009194a91dSDouglas Gregor Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match); 27019194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 27029194a91dSDouglas Gregor HadError = true; 27039194a91dSDouglas Gregor } 27049194a91dSDouglas Gregor 27059194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 27069194a91dSDouglas Gregor consumeToken(); 27079194a91dSDouglas Gregor } 27089194a91dSDouglas Gregor 27099194a91dSDouglas Gregor return HadError; 27109194a91dSDouglas Gregor } 27119194a91dSDouglas Gregor 2712718292f2SDouglas Gregor /// \brief Parse a module map file. 2713718292f2SDouglas Gregor /// 2714718292f2SDouglas Gregor /// module-map-file: 2715718292f2SDouglas Gregor /// module-declaration* 2716718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 2717718292f2SDouglas Gregor do { 2718718292f2SDouglas Gregor switch (Tok.Kind) { 2719718292f2SDouglas Gregor case MMToken::EndOfFile: 2720718292f2SDouglas Gregor return HadError; 2721718292f2SDouglas Gregor 2722e7ab3669SDouglas Gregor case MMToken::ExplicitKeyword: 272397292843SDaniel Jasper case MMToken::ExternKeyword: 2724718292f2SDouglas Gregor case MMToken::ModuleKeyword: 2725755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 2726718292f2SDouglas Gregor parseModuleDecl(); 2727718292f2SDouglas Gregor break; 2728718292f2SDouglas Gregor 27291fb5c3a6SDouglas Gregor case MMToken::Comma: 273035b13eceSDouglas Gregor case MMToken::ConfigMacros: 2731fb912657SDouglas Gregor case MMToken::Conflict: 2732a3feee2aSRichard Smith case MMToken::Exclaim: 273359527666SDouglas Gregor case MMToken::ExcludeKeyword: 27342b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 2735*f0b11de2SDouglas Gregor case MMToken::ExportAsKeyword: 2736718292f2SDouglas Gregor case MMToken::HeaderKeyword: 2737718292f2SDouglas Gregor case MMToken::Identifier: 2738718292f2SDouglas Gregor case MMToken::LBrace: 27396ddfca91SDouglas Gregor case MMToken::LinkKeyword: 2740a686e1b0SDouglas Gregor case MMToken::LSquare: 27412b82c2a5SDouglas Gregor case MMToken::Period: 2742b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 2743718292f2SDouglas Gregor case MMToken::RBrace: 2744a686e1b0SDouglas Gregor case MMToken::RSquare: 27451fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 27462b82c2a5SDouglas Gregor case MMToken::Star: 2747718292f2SDouglas Gregor case MMToken::StringLiteral: 2748040e1266SRichard Smith case MMToken::IntegerLiteral: 2749b8afebe2SRichard Smith case MMToken::TextualKeyword: 2750718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 2751ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 2752718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 2753718292f2SDouglas Gregor HadError = true; 2754718292f2SDouglas Gregor consumeToken(); 2755718292f2SDouglas Gregor break; 2756718292f2SDouglas Gregor } 2757718292f2SDouglas Gregor } while (true); 2758718292f2SDouglas Gregor } 2759718292f2SDouglas Gregor 27609acb99e3SRichard Smith bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem, 27618128f332SRichard Smith const DirectoryEntry *Dir, FileID ID, 27628128f332SRichard Smith unsigned *Offset, 2763ae6df27eSRichard Smith SourceLocation ExternModuleLoc) { 27648128f332SRichard Smith assert(Target && "Missing target information"); 27654ddf2221SDouglas Gregor llvm::DenseMap<const FileEntry *, bool>::iterator Known 27664ddf2221SDouglas Gregor = ParsedModuleMap.find(File); 27674ddf2221SDouglas Gregor if (Known != ParsedModuleMap.end()) 27684ddf2221SDouglas Gregor return Known->second; 27694ddf2221SDouglas Gregor 27708128f332SRichard Smith // If the module map file wasn't already entered, do so now. 27718128f332SRichard Smith if (ID.isInvalid()) { 2772f3f84616SRichard Smith auto FileCharacter = 2773f3f84616SRichard Smith IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap; 27748128f332SRichard Smith ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter); 27758128f332SRichard Smith } 27768128f332SRichard Smith 27778128f332SRichard Smith assert(Target && "Missing target information"); 27781f76c4e8SManuel Klimek const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID); 2779718292f2SDouglas Gregor if (!Buffer) 27804ddf2221SDouglas Gregor return ParsedModuleMap[File] = true; 27818128f332SRichard Smith assert((!Offset || *Offset <= Buffer->getBufferSize()) && 27828128f332SRichard Smith "invalid buffer offset"); 2783718292f2SDouglas Gregor 2784718292f2SDouglas Gregor // Parse this module map file. 27858128f332SRichard Smith Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts, 27868128f332SRichard Smith Buffer->getBufferStart(), 27878128f332SRichard Smith Buffer->getBufferStart() + (Offset ? *Offset : 0), 27888128f332SRichard Smith Buffer->getBufferEnd()); 27892a6edb30SRichard Smith SourceLocation Start = L.getSourceLocation(); 2790beee15e7SBen Langmuir ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir, 27911d60987fSRichard Smith IsSystem); 2792718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 27934ddf2221SDouglas Gregor ParsedModuleMap[File] = Result; 27942a6edb30SRichard Smith 27958128f332SRichard Smith if (Offset) { 27968128f332SRichard Smith auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation()); 27978128f332SRichard Smith assert(Loc.first == ID && "stopped in a different file?"); 27988128f332SRichard Smith *Offset = Loc.second; 27998128f332SRichard Smith } 28008128f332SRichard Smith 28012a6edb30SRichard Smith // Notify callbacks that we parsed it. 28022a6edb30SRichard Smith for (const auto &Cb : Callbacks) 28032a6edb30SRichard Smith Cb->moduleMapFileRead(Start, *File, IsSystem); 2804718292f2SDouglas Gregor return Result; 2805718292f2SDouglas Gregor } 2806