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), 259d2d442caSCraig Topper HeaderInfo(HeaderInfo), BuiltinIncludeDir(nullptr), 2607e82e019SRichard Smith SourceModule(nullptr), NumCreatedModules(0) { 2610414b857SRichard Smith MMapLangOpts.LineComment = true; 2620414b857SRichard Smith } 263718292f2SDouglas Gregor 264718292f2SDouglas Gregor ModuleMap::~ModuleMap() { 26521668754SDavide Italiano for (auto &M : Modules) 26621668754SDavide Italiano delete M.getValue(); 267718292f2SDouglas Gregor } 268718292f2SDouglas Gregor 26989929282SDouglas Gregor void ModuleMap::setTarget(const TargetInfo &Target) { 27089929282SDouglas Gregor assert((!this->Target || this->Target == &Target) && 27189929282SDouglas Gregor "Improper target override"); 27289929282SDouglas Gregor this->Target = &Target; 27389929282SDouglas Gregor } 27489929282SDouglas Gregor 275056396aeSDouglas Gregor /// \brief "Sanitize" a filename so that it can be used as an identifier. 276056396aeSDouglas Gregor static StringRef sanitizeFilenameAsIdentifier(StringRef Name, 277056396aeSDouglas Gregor SmallVectorImpl<char> &Buffer) { 278056396aeSDouglas Gregor if (Name.empty()) 279056396aeSDouglas Gregor return Name; 280056396aeSDouglas Gregor 281a7d03840SJordan Rose if (!isValidIdentifier(Name)) { 282056396aeSDouglas Gregor // If we don't already have something with the form of an identifier, 283056396aeSDouglas Gregor // create a buffer with the sanitized name. 284056396aeSDouglas Gregor Buffer.clear(); 285a7d03840SJordan Rose if (isDigit(Name[0])) 286056396aeSDouglas Gregor Buffer.push_back('_'); 287056396aeSDouglas Gregor Buffer.reserve(Buffer.size() + Name.size()); 288056396aeSDouglas Gregor for (unsigned I = 0, N = Name.size(); I != N; ++I) { 289a7d03840SJordan Rose if (isIdentifierBody(Name[I])) 290056396aeSDouglas Gregor Buffer.push_back(Name[I]); 291056396aeSDouglas Gregor else 292056396aeSDouglas Gregor Buffer.push_back('_'); 293056396aeSDouglas Gregor } 294056396aeSDouglas Gregor 295056396aeSDouglas Gregor Name = StringRef(Buffer.data(), Buffer.size()); 296056396aeSDouglas Gregor } 297056396aeSDouglas Gregor 298056396aeSDouglas Gregor while (llvm::StringSwitch<bool>(Name) 299056396aeSDouglas Gregor #define KEYWORD(Keyword,Conditions) .Case(#Keyword, true) 300056396aeSDouglas Gregor #define ALIAS(Keyword, AliasOf, Conditions) .Case(Keyword, true) 301056396aeSDouglas Gregor #include "clang/Basic/TokenKinds.def" 302056396aeSDouglas Gregor .Default(false)) { 303056396aeSDouglas Gregor if (Name.data() != Buffer.data()) 304056396aeSDouglas Gregor Buffer.append(Name.begin(), Name.end()); 305056396aeSDouglas Gregor Buffer.push_back('_'); 306056396aeSDouglas Gregor Name = StringRef(Buffer.data(), Buffer.size()); 307056396aeSDouglas Gregor } 308056396aeSDouglas Gregor 309056396aeSDouglas Gregor return Name; 310056396aeSDouglas Gregor } 311056396aeSDouglas Gregor 31234d52749SDouglas Gregor /// \brief Determine whether the given file name is the name of a builtin 31334d52749SDouglas Gregor /// header, supplied by Clang to replace, override, or augment existing system 31434d52749SDouglas Gregor /// headers. 315ba1b5c98SBruno Cardoso Lopes bool ModuleMap::isBuiltinHeader(StringRef FileName) { 31634d52749SDouglas Gregor return llvm::StringSwitch<bool>(FileName) 31734d52749SDouglas Gregor .Case("float.h", true) 31834d52749SDouglas Gregor .Case("iso646.h", true) 31934d52749SDouglas Gregor .Case("limits.h", true) 32034d52749SDouglas Gregor .Case("stdalign.h", true) 32134d52749SDouglas Gregor .Case("stdarg.h", true) 3223c4b1290SBen Langmuir .Case("stdatomic.h", true) 32334d52749SDouglas Gregor .Case("stdbool.h", true) 32434d52749SDouglas Gregor .Case("stddef.h", true) 32534d52749SDouglas Gregor .Case("stdint.h", true) 32634d52749SDouglas Gregor .Case("tgmath.h", true) 32734d52749SDouglas Gregor .Case("unwind.h", true) 32834d52749SDouglas Gregor .Default(false); 32934d52749SDouglas Gregor } 33034d52749SDouglas Gregor 33192669ee4SDaniel Jasper ModuleMap::HeadersMap::iterator 33292669ee4SDaniel Jasper ModuleMap::findKnownHeader(const FileEntry *File) { 333040e1266SRichard Smith resolveHeaderDirectives(File); 33459527666SDouglas Gregor HeadersMap::iterator Known = Headers.find(File); 33547972afdSRichard Smith if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && 33647972afdSRichard Smith Known == Headers.end() && File->getDir() == BuiltinIncludeDir && 337ba1b5c98SBruno Cardoso Lopes ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()))) { 3384eaf0a6cSDaniel Jasper HeaderInfo.loadTopLevelSystemModules(); 33992669ee4SDaniel Jasper return Headers.find(File); 3404eaf0a6cSDaniel Jasper } 34192669ee4SDaniel Jasper return Known; 34292669ee4SDaniel Jasper } 34392669ee4SDaniel Jasper 3444469138eSBen Langmuir ModuleMap::KnownHeader 3454469138eSBen Langmuir ModuleMap::findHeaderInUmbrellaDirs(const FileEntry *File, 3464469138eSBen Langmuir SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs) { 34747972afdSRichard Smith if (UmbrellaDirs.empty()) 34847972afdSRichard Smith return KnownHeader(); 34947972afdSRichard Smith 3504469138eSBen Langmuir const DirectoryEntry *Dir = File->getDir(); 3514469138eSBen Langmuir assert(Dir && "file in no directory"); 3524469138eSBen Langmuir 3534469138eSBen Langmuir // Note: as an egregious but useful hack we use the real path here, because 3544469138eSBen Langmuir // frameworks moving from top-level frameworks to embedded frameworks tend 3554469138eSBen Langmuir // to be symlinked from the top-level location to the embedded location, 3564469138eSBen Langmuir // and we need to resolve lookups as if we had found the embedded location. 3574469138eSBen Langmuir StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir); 3584469138eSBen Langmuir 3594469138eSBen Langmuir // Keep walking up the directory hierarchy, looking for a directory with 3604469138eSBen Langmuir // an umbrella header. 3614469138eSBen Langmuir do { 3624469138eSBen Langmuir auto KnownDir = UmbrellaDirs.find(Dir); 3634469138eSBen Langmuir if (KnownDir != UmbrellaDirs.end()) 3644469138eSBen Langmuir return KnownHeader(KnownDir->second, NormalHeader); 3654469138eSBen Langmuir 3664469138eSBen Langmuir IntermediateDirs.push_back(Dir); 3674469138eSBen Langmuir 3684469138eSBen Langmuir // Retrieve our parent path. 3694469138eSBen Langmuir DirName = llvm::sys::path::parent_path(DirName); 3704469138eSBen Langmuir if (DirName.empty()) 3714469138eSBen Langmuir break; 3724469138eSBen Langmuir 3734469138eSBen Langmuir // Resolve the parent path to a directory entry. 3744469138eSBen Langmuir Dir = SourceMgr.getFileManager().getDirectory(DirName); 3754469138eSBen Langmuir } while (Dir); 3764469138eSBen Langmuir return KnownHeader(); 3774469138eSBen Langmuir } 3784469138eSBen Langmuir 37992669ee4SDaniel Jasper static bool violatesPrivateInclude(Module *RequestingModule, 38092669ee4SDaniel Jasper const FileEntry *IncFileEnt, 3814eb8393cSRichard Smith ModuleMap::KnownHeader Header) { 38292669ee4SDaniel Jasper #ifndef NDEBUG 3834eb8393cSRichard Smith if (Header.getRole() & ModuleMap::PrivateHeader) { 38492669ee4SDaniel Jasper // Check for consistency between the module header role 38592669ee4SDaniel Jasper // as obtained from the lookup and as obtained from the module. 38692669ee4SDaniel Jasper // This check is not cheap, so enable it only for debugging. 3872708e520SRichard Smith bool IsPrivate = false; 3882708e520SRichard Smith SmallVectorImpl<Module::Header> *HeaderList[] = { 3894eb8393cSRichard Smith &Header.getModule()->Headers[Module::HK_Private], 3904eb8393cSRichard Smith &Header.getModule()->Headers[Module::HK_PrivateTextual]}; 3912708e520SRichard Smith for (auto *Hs : HeaderList) 3922708e520SRichard Smith IsPrivate |= 3932708e520SRichard Smith std::find_if(Hs->begin(), Hs->end(), [&](const Module::Header &H) { 3943c1a41adSRichard Smith return H.Entry == IncFileEnt; 3952708e520SRichard Smith }) != Hs->end(); 3964eb8393cSRichard Smith assert(IsPrivate && "inconsistent headers and roles"); 39700bc95ecSRichard Smith } 39892669ee4SDaniel Jasper #endif 3994eb8393cSRichard Smith return !Header.isAccessibleFrom(RequestingModule); 40092669ee4SDaniel Jasper } 40192669ee4SDaniel Jasper 40271e1a64fSBen Langmuir static Module *getTopLevelOrNull(Module *M) { 40371e1a64fSBen Langmuir return M ? M->getTopLevelModule() : nullptr; 40471e1a64fSBen Langmuir } 40571e1a64fSBen Langmuir 40692669ee4SDaniel Jasper void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, 4078d4e90b3SRichard Smith bool RequestingModuleIsModuleInterface, 40892669ee4SDaniel Jasper SourceLocation FilenameLoc, 40992669ee4SDaniel Jasper StringRef Filename, 41092669ee4SDaniel Jasper const FileEntry *File) { 41192669ee4SDaniel Jasper // No errors for indirect modules. This may be a bit of a problem for modules 41292669ee4SDaniel Jasper // with no source files. 41371e1a64fSBen Langmuir if (getTopLevelOrNull(RequestingModule) != getTopLevelOrNull(SourceModule)) 41492669ee4SDaniel Jasper return; 41592669ee4SDaniel Jasper 416040e1266SRichard Smith if (RequestingModule) { 41792669ee4SDaniel Jasper resolveUses(RequestingModule, /*Complain=*/false); 418040e1266SRichard Smith resolveHeaderDirectives(RequestingModule); 419040e1266SRichard Smith } 42092669ee4SDaniel Jasper 42171e1a64fSBen Langmuir bool Excluded = false; 422d2d442caSCraig Topper Module *Private = nullptr; 423d2d442caSCraig Topper Module *NotUsed = nullptr; 42471e1a64fSBen Langmuir 42571e1a64fSBen Langmuir HeadersMap::iterator Known = findKnownHeader(File); 42671e1a64fSBen Langmuir if (Known != Headers.end()) { 42771e1a64fSBen Langmuir for (const KnownHeader &Header : Known->second) { 42892669ee4SDaniel Jasper // Remember private headers for later printing of a diagnostic. 4294eb8393cSRichard Smith if (violatesPrivateInclude(RequestingModule, File, Header)) { 43071e1a64fSBen Langmuir Private = Header.getModule(); 43192669ee4SDaniel Jasper continue; 43292669ee4SDaniel Jasper } 43392669ee4SDaniel Jasper 43492669ee4SDaniel Jasper // If uses need to be specified explicitly, we are only allowed to return 43592669ee4SDaniel Jasper // modules that are explicitly used by the requesting module. 43692669ee4SDaniel Jasper if (RequestingModule && LangOpts.ModulesDeclUse && 4378f4d3ff1SRichard Smith !RequestingModule->directlyUses(Header.getModule())) { 43871e1a64fSBen Langmuir NotUsed = Header.getModule(); 43992669ee4SDaniel Jasper continue; 44092669ee4SDaniel Jasper } 44192669ee4SDaniel Jasper 44292669ee4SDaniel Jasper // We have found a module that we can happily use. 44392669ee4SDaniel Jasper return; 44492669ee4SDaniel Jasper } 445feb54b6dSRichard Smith 446feb54b6dSRichard Smith Excluded = true; 44771e1a64fSBen Langmuir } 44892669ee4SDaniel Jasper 44992669ee4SDaniel Jasper // We have found a header, but it is private. 450d2d442caSCraig Topper if (Private) { 45111152dd5SRichard Smith Diags.Report(FilenameLoc, diag::warn_use_of_private_header_outside_module) 45292669ee4SDaniel Jasper << Filename; 45392669ee4SDaniel Jasper return; 45492669ee4SDaniel Jasper } 45592669ee4SDaniel Jasper 45692669ee4SDaniel Jasper // We have found a module, but we don't use it. 457d2d442caSCraig Topper if (NotUsed) { 45811152dd5SRichard Smith Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) 45992669ee4SDaniel Jasper << RequestingModule->getFullModuleName() << Filename; 46092669ee4SDaniel Jasper return; 46192669ee4SDaniel Jasper } 46292669ee4SDaniel Jasper 46371e1a64fSBen Langmuir if (Excluded || isHeaderInUmbrellaDirs(File)) 46471e1a64fSBen Langmuir return; 46571e1a64fSBen Langmuir 46671e1a64fSBen Langmuir // At this point, only non-modular includes remain. 46771e1a64fSBen Langmuir 46871e1a64fSBen Langmuir if (LangOpts.ModulesStrictDeclUse) { 46911152dd5SRichard Smith Diags.Report(FilenameLoc, diag::err_undeclared_use_of_module) 47071e1a64fSBen Langmuir << RequestingModule->getFullModuleName() << Filename; 471a67e4d32SManman Ren } else if (RequestingModule && RequestingModuleIsModuleInterface && 472a67e4d32SManman Ren LangOpts.isCompilingModule()) { 473a67e4d32SManman Ren // Do not diagnose when we are not compiling a module. 47471e1a64fSBen Langmuir diag::kind DiagID = RequestingModule->getTopLevelModule()->IsFramework ? 47571e1a64fSBen Langmuir diag::warn_non_modular_include_in_framework_module : 47671e1a64fSBen Langmuir diag::warn_non_modular_include_in_module; 47770a7738fSManman Ren Diags.Report(FilenameLoc, DiagID) << RequestingModule->getFullModuleName() 47870a7738fSManman Ren << File->getName(); 47971e1a64fSBen Langmuir } 48092669ee4SDaniel Jasper } 48192669ee4SDaniel Jasper 482ec87a50aSRichard Smith static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New, 483ec87a50aSRichard Smith const ModuleMap::KnownHeader &Old) { 4848b7c0398SSean Silva // Prefer available modules. 4858b7c0398SSean Silva if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable()) 4868b7c0398SSean Silva return true; 4878b7c0398SSean Silva 488ec87a50aSRichard Smith // Prefer a public header over a private header. 489ec87a50aSRichard Smith if ((New.getRole() & ModuleMap::PrivateHeader) != 490ec87a50aSRichard Smith (Old.getRole() & ModuleMap::PrivateHeader)) 491ec87a50aSRichard Smith return !(New.getRole() & ModuleMap::PrivateHeader); 492ec87a50aSRichard Smith 493ec87a50aSRichard Smith // Prefer a non-textual header over a textual header. 494ec87a50aSRichard Smith if ((New.getRole() & ModuleMap::TextualHeader) != 495ec87a50aSRichard Smith (Old.getRole() & ModuleMap::TextualHeader)) 496ec87a50aSRichard Smith return !(New.getRole() & ModuleMap::TextualHeader); 497ec87a50aSRichard Smith 498ec87a50aSRichard Smith // Don't have a reason to choose between these. Just keep the first one. 499ec87a50aSRichard Smith return false; 500ec87a50aSRichard Smith } 501ec87a50aSRichard Smith 502ed84df00SBruno Cardoso Lopes ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File, 503ed84df00SBruno Cardoso Lopes bool AllowTextual) { 504306d8920SRichard Smith auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader { 505ed84df00SBruno Cardoso Lopes if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader) 506306d8920SRichard Smith return ModuleMap::KnownHeader(); 507306d8920SRichard Smith return R; 508306d8920SRichard Smith }; 509306d8920SRichard Smith 5104881e8b2SSean Silva HeadersMap::iterator Known = findKnownHeader(File); 5111fb5c3a6SDouglas Gregor if (Known != Headers.end()) { 512202210b3SRichard Smith ModuleMap::KnownHeader Result; 51397da9178SDaniel Jasper // Iterate over all modules that 'File' is part of to find the best fit. 5144881e8b2SSean Silva for (KnownHeader &H : Known->second) { 5157e82e019SRichard Smith // Prefer a header from the source module over all others. 5167e82e019SRichard Smith if (H.getModule()->getTopLevelModule() == SourceModule) 5172f633e7cSRichard Smith return MakeResult(H); 5184881e8b2SSean Silva if (!Result || isBetterKnownHeader(H, Result)) 5194881e8b2SSean Silva Result = H; 52097da9178SDaniel Jasper } 521306d8920SRichard Smith return MakeResult(Result); 5221fb5c3a6SDouglas Gregor } 523ab0c8a84SDouglas Gregor 524386bb073SRichard Smith return MakeResult(findOrCreateModuleForHeaderInUmbrellaDir(File)); 525386bb073SRichard Smith } 526386bb073SRichard Smith 527386bb073SRichard Smith ModuleMap::KnownHeader 528386bb073SRichard Smith ModuleMap::findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File) { 529386bb073SRichard Smith assert(!Headers.count(File) && "already have a module for this header"); 530386bb073SRichard Smith 531f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs; 5324469138eSBen Langmuir KnownHeader H = findHeaderInUmbrellaDirs(File, SkippedDirs); 5334469138eSBen Langmuir if (H) { 5344469138eSBen Langmuir Module *Result = H.getModule(); 535930a85ccSDouglas Gregor 536930a85ccSDouglas Gregor // Search up the module stack until we find a module with an umbrella 53773141fa9SDouglas Gregor // directory. 538930a85ccSDouglas Gregor Module *UmbrellaModule = Result; 53973141fa9SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 540930a85ccSDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 541930a85ccSDouglas Gregor 542930a85ccSDouglas Gregor if (UmbrellaModule->InferSubmodules) { 5439d6448b1SBen Langmuir const FileEntry *UmbrellaModuleMap = 5449d6448b1SBen Langmuir getModuleMapFileForUniquing(UmbrellaModule); 5459d6448b1SBen Langmuir 546a89c5ac4SDouglas Gregor // Infer submodules for each of the directories we found between 547a89c5ac4SDouglas Gregor // the directory of the umbrella header and the directory where 548a89c5ac4SDouglas Gregor // the actual header is located. 5499458f82dSDouglas Gregor bool Explicit = UmbrellaModule->InferExplicitSubmodules; 5509458f82dSDouglas Gregor 5517033127bSDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 552a89c5ac4SDouglas Gregor // Find or create the module that corresponds to this directory name. 553056396aeSDouglas Gregor SmallString<32> NameBuf; 554056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 5554469138eSBen Langmuir llvm::sys::path::stem(SkippedDirs[I-1]->getName()), NameBuf); 5569d6448b1SBen Langmuir Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 5579d6448b1SBen Langmuir Explicit).first; 5589d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = UmbrellaModuleMap; 559ffbafa2aSBen Langmuir Result->IsInferred = true; 560a89c5ac4SDouglas Gregor 561a89c5ac4SDouglas Gregor // Associate the module and the directory. 562a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I-1]] = Result; 563a89c5ac4SDouglas Gregor 564a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 565a89c5ac4SDouglas Gregor // wildcard to the set of exports. 566930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 567d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 568a89c5ac4SDouglas Gregor } 569a89c5ac4SDouglas Gregor 570a89c5ac4SDouglas Gregor // Infer a submodule with the same name as this header file. 571056396aeSDouglas Gregor SmallString<32> NameBuf; 572056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 573056396aeSDouglas Gregor llvm::sys::path::stem(File->getName()), NameBuf); 5749d6448b1SBen Langmuir Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 5759d6448b1SBen Langmuir Explicit).first; 5769d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = UmbrellaModuleMap; 577ffbafa2aSBen Langmuir Result->IsInferred = true; 5783c5305c1SArgyrios Kyrtzidis Result->addTopHeader(File); 579a89c5ac4SDouglas Gregor 580a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 581a89c5ac4SDouglas Gregor // wildcard to the set of exports. 582930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 583d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 584a89c5ac4SDouglas Gregor } else { 585a89c5ac4SDouglas Gregor // Record each of the directories we stepped through as being part of 586a89c5ac4SDouglas Gregor // the module we found, since the umbrella header covers them all. 587a89c5ac4SDouglas Gregor for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I) 588a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I]] = Result; 589a89c5ac4SDouglas Gregor } 590a89c5ac4SDouglas Gregor 591386bb073SRichard Smith KnownHeader Header(Result, NormalHeader); 592386bb073SRichard Smith Headers[File].push_back(Header); 593386bb073SRichard Smith return Header; 594a89c5ac4SDouglas Gregor } 595a89c5ac4SDouglas Gregor 596b53e5483SLawrence Crowl return KnownHeader(); 597ab0c8a84SDouglas Gregor } 598ab0c8a84SDouglas Gregor 599386bb073SRichard Smith ArrayRef<ModuleMap::KnownHeader> 600386bb073SRichard Smith ModuleMap::findAllModulesForHeader(const FileEntry *File) const { 601040e1266SRichard Smith resolveHeaderDirectives(File); 602386bb073SRichard Smith auto It = Headers.find(File); 603386bb073SRichard Smith if (It == Headers.end()) 604386bb073SRichard Smith return None; 605386bb073SRichard Smith return It->second; 606386bb073SRichard Smith } 607386bb073SRichard Smith 608e4412640SArgyrios Kyrtzidis bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const { 609d2d442caSCraig Topper return isHeaderUnavailableInModule(Header, nullptr); 61050996ce1SRichard Smith } 61150996ce1SRichard Smith 61262bcd925SDmitri Gribenko bool 61362bcd925SDmitri Gribenko ModuleMap::isHeaderUnavailableInModule(const FileEntry *Header, 61462bcd925SDmitri Gribenko const Module *RequestingModule) const { 615040e1266SRichard Smith resolveHeaderDirectives(Header); 616e4412640SArgyrios Kyrtzidis HeadersMap::const_iterator Known = Headers.find(Header); 61797da9178SDaniel Jasper if (Known != Headers.end()) { 61897da9178SDaniel Jasper for (SmallVectorImpl<KnownHeader>::const_iterator 61997da9178SDaniel Jasper I = Known->second.begin(), 62097da9178SDaniel Jasper E = Known->second.end(); 62197da9178SDaniel Jasper I != E; ++I) { 622052d95a6SBruno Cardoso Lopes 623052d95a6SBruno Cardoso Lopes if (I->isAvailable() && 624052d95a6SBruno Cardoso Lopes (!RequestingModule || 625052d95a6SBruno Cardoso Lopes I->getModule()->isSubModuleOf(RequestingModule))) { 626052d95a6SBruno Cardoso Lopes // When no requesting module is available, the caller is looking if a 627052d95a6SBruno Cardoso Lopes // header is part a module by only looking into the module map. This is 628052d95a6SBruno Cardoso Lopes // done by warn_uncovered_module_header checks; don't consider textual 629052d95a6SBruno Cardoso Lopes // headers part of it in this mode, otherwise we get misleading warnings 630052d95a6SBruno Cardoso Lopes // that a umbrella header is not including a textual header. 631052d95a6SBruno Cardoso Lopes if (!RequestingModule && I->getRole() == ModuleMap::TextualHeader) 632052d95a6SBruno Cardoso Lopes continue; 63397da9178SDaniel Jasper return false; 63497da9178SDaniel Jasper } 635052d95a6SBruno Cardoso Lopes } 63697da9178SDaniel Jasper return true; 63797da9178SDaniel Jasper } 6381fb5c3a6SDouglas Gregor 6391fb5c3a6SDouglas Gregor const DirectoryEntry *Dir = Header->getDir(); 640f857950dSDmitri Gribenko SmallVector<const DirectoryEntry *, 2> SkippedDirs; 6411fb5c3a6SDouglas Gregor StringRef DirName = Dir->getName(); 6421fb5c3a6SDouglas Gregor 64350996ce1SRichard Smith auto IsUnavailable = [&](const Module *M) { 64450996ce1SRichard Smith return !M->isAvailable() && (!RequestingModule || 64550996ce1SRichard Smith M->isSubModuleOf(RequestingModule)); 64650996ce1SRichard Smith }; 64750996ce1SRichard Smith 6481fb5c3a6SDouglas Gregor // Keep walking up the directory hierarchy, looking for a directory with 6491fb5c3a6SDouglas Gregor // an umbrella header. 6501fb5c3a6SDouglas Gregor do { 651e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, Module *>::const_iterator KnownDir 6521fb5c3a6SDouglas Gregor = UmbrellaDirs.find(Dir); 6531fb5c3a6SDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 6541fb5c3a6SDouglas Gregor Module *Found = KnownDir->second; 65550996ce1SRichard Smith if (IsUnavailable(Found)) 6561fb5c3a6SDouglas Gregor return true; 6571fb5c3a6SDouglas Gregor 6581fb5c3a6SDouglas Gregor // Search up the module stack until we find a module with an umbrella 6591fb5c3a6SDouglas Gregor // directory. 6601fb5c3a6SDouglas Gregor Module *UmbrellaModule = Found; 6611fb5c3a6SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 6621fb5c3a6SDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 6631fb5c3a6SDouglas Gregor 6641fb5c3a6SDouglas Gregor if (UmbrellaModule->InferSubmodules) { 6651fb5c3a6SDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 6661fb5c3a6SDouglas Gregor // Find or create the module that corresponds to this directory name. 667056396aeSDouglas Gregor SmallString<32> NameBuf; 668056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 669056396aeSDouglas Gregor llvm::sys::path::stem(SkippedDirs[I-1]->getName()), 670056396aeSDouglas Gregor NameBuf); 6711fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 6721fb5c3a6SDouglas Gregor if (!Found) 6731fb5c3a6SDouglas Gregor return false; 67450996ce1SRichard Smith if (IsUnavailable(Found)) 6751fb5c3a6SDouglas Gregor return true; 6761fb5c3a6SDouglas Gregor } 6771fb5c3a6SDouglas Gregor 6781fb5c3a6SDouglas Gregor // Infer a submodule with the same name as this header file. 679056396aeSDouglas Gregor SmallString<32> NameBuf; 680056396aeSDouglas Gregor StringRef Name = sanitizeFilenameAsIdentifier( 681056396aeSDouglas Gregor llvm::sys::path::stem(Header->getName()), 682056396aeSDouglas Gregor NameBuf); 6831fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 6841fb5c3a6SDouglas Gregor if (!Found) 6851fb5c3a6SDouglas Gregor return false; 6861fb5c3a6SDouglas Gregor } 6871fb5c3a6SDouglas Gregor 68850996ce1SRichard Smith return IsUnavailable(Found); 6891fb5c3a6SDouglas Gregor } 6901fb5c3a6SDouglas Gregor 6911fb5c3a6SDouglas Gregor SkippedDirs.push_back(Dir); 6921fb5c3a6SDouglas Gregor 6931fb5c3a6SDouglas Gregor // Retrieve our parent path. 6941fb5c3a6SDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 6951fb5c3a6SDouglas Gregor if (DirName.empty()) 6961fb5c3a6SDouglas Gregor break; 6971fb5c3a6SDouglas Gregor 6981fb5c3a6SDouglas Gregor // Resolve the parent path to a directory entry. 6991f76c4e8SManuel Klimek Dir = SourceMgr.getFileManager().getDirectory(DirName); 7001fb5c3a6SDouglas Gregor } while (Dir); 7011fb5c3a6SDouglas Gregor 7021fb5c3a6SDouglas Gregor return false; 7031fb5c3a6SDouglas Gregor } 7041fb5c3a6SDouglas Gregor 705e4412640SArgyrios Kyrtzidis Module *ModuleMap::findModule(StringRef Name) const { 706e4412640SArgyrios Kyrtzidis llvm::StringMap<Module *>::const_iterator Known = Modules.find(Name); 70788bdfb0eSDouglas Gregor if (Known != Modules.end()) 70888bdfb0eSDouglas Gregor return Known->getValue(); 70988bdfb0eSDouglas Gregor 710d2d442caSCraig Topper return nullptr; 71188bdfb0eSDouglas Gregor } 71288bdfb0eSDouglas Gregor 713e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleUnqualified(StringRef Name, 714e4412640SArgyrios Kyrtzidis Module *Context) const { 7152b82c2a5SDouglas Gregor for(; Context; Context = Context->Parent) { 7162b82c2a5SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Context)) 7172b82c2a5SDouglas Gregor return Sub; 7182b82c2a5SDouglas Gregor } 7192b82c2a5SDouglas Gregor 7202b82c2a5SDouglas Gregor return findModule(Name); 7212b82c2a5SDouglas Gregor } 7222b82c2a5SDouglas Gregor 723e4412640SArgyrios Kyrtzidis Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) const{ 7242b82c2a5SDouglas Gregor if (!Context) 7252b82c2a5SDouglas Gregor return findModule(Name); 7262b82c2a5SDouglas Gregor 727eb90e830SDouglas Gregor return Context->findSubmodule(Name); 7282b82c2a5SDouglas Gregor } 7292b82c2a5SDouglas Gregor 7309ffe5a35SDavid Blaikie std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name, 7319ffe5a35SDavid Blaikie Module *Parent, 7329ffe5a35SDavid Blaikie bool IsFramework, 73369021974SDouglas Gregor bool IsExplicit) { 73469021974SDouglas Gregor // Try to find an existing module with this name. 735eb90e830SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Parent)) 736eb90e830SDouglas Gregor return std::make_pair(Sub, false); 73769021974SDouglas Gregor 73869021974SDouglas Gregor // Create a new module with this name. 7399ffe5a35SDavid Blaikie Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, 7409ffe5a35SDavid Blaikie IsExplicit, NumCreatedModules++); 7416f722b4eSArgyrios Kyrtzidis if (!Parent) { 7427e82e019SRichard Smith if (LangOpts.CurrentModule == Name) 7437e82e019SRichard Smith SourceModule = Result; 74469021974SDouglas Gregor Modules[Name] = Result; 7456f722b4eSArgyrios Kyrtzidis } 74669021974SDouglas Gregor return std::make_pair(Result, true); 74769021974SDouglas Gregor } 74869021974SDouglas Gregor 749*dd8b5337SRichard Smith Module *ModuleMap::createGlobalModuleForInterfaceUnit(SourceLocation Loc) { 750*dd8b5337SRichard Smith auto *Result = new Module("<global>", Loc, nullptr, /*IsFramework*/ false, 751*dd8b5337SRichard Smith /*IsExplicit*/ true, NumCreatedModules++); 752*dd8b5337SRichard Smith Result->Kind = Module::GlobalModuleFragment; 753*dd8b5337SRichard Smith return Result; 754*dd8b5337SRichard Smith } 755*dd8b5337SRichard Smith 756bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc, 757*dd8b5337SRichard Smith StringRef Name, 758*dd8b5337SRichard Smith Module *GlobalModule) { 759bbcc9f04SRichard Smith assert(LangOpts.CurrentModule == Name && "module name mismatch"); 760bbcc9f04SRichard Smith assert(!Modules[Name] && "redefining existing module"); 761bbcc9f04SRichard Smith 762bbcc9f04SRichard Smith auto *Result = 763bbcc9f04SRichard Smith new Module(Name, Loc, nullptr, /*IsFramework*/ false, 764bbcc9f04SRichard Smith /*IsExplicit*/ false, NumCreatedModules++); 765145e15a3SRichard Smith Result->Kind = Module::ModuleInterfaceUnit; 766bbcc9f04SRichard Smith Modules[Name] = SourceModule = Result; 767bbcc9f04SRichard Smith 768*dd8b5337SRichard Smith // Reparent the current global module fragment as a submodule of this module. 769*dd8b5337SRichard Smith GlobalModule->setParent(Result); 770*dd8b5337SRichard Smith 771bbcc9f04SRichard Smith // Mark the main source file as being within the newly-created module so that 772bbcc9f04SRichard Smith // declarations and macros are properly visibility-restricted to it. 773bbcc9f04SRichard Smith auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()); 774bbcc9f04SRichard Smith assert(MainFile && "no input file for module interface"); 775bbcc9f04SRichard Smith Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader)); 776bbcc9f04SRichard Smith 777bbcc9f04SRichard Smith return Result; 778bbcc9f04SRichard Smith } 779bbcc9f04SRichard Smith 78011dfe6feSDouglas Gregor /// \brief For a framework module, infer the framework against which we 78111dfe6feSDouglas Gregor /// should link. 78211dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir, 78311dfe6feSDouglas Gregor FileManager &FileMgr) { 78411dfe6feSDouglas Gregor assert(Mod->IsFramework && "Can only infer linking for framework modules"); 78511dfe6feSDouglas Gregor assert(!Mod->isSubFramework() && 78611dfe6feSDouglas Gregor "Can only infer linking for top-level frameworks"); 78711dfe6feSDouglas Gregor 78811dfe6feSDouglas Gregor SmallString<128> LibName; 78911dfe6feSDouglas Gregor LibName += FrameworkDir->getName(); 79011dfe6feSDouglas Gregor llvm::sys::path::append(LibName, Mod->Name); 7918aaae5a9SJuergen Ributzka 7928aaae5a9SJuergen Ributzka // The library name of a framework has more than one possible extension since 7938aaae5a9SJuergen Ributzka // the introduction of the text-based dynamic library format. We need to check 7948aaae5a9SJuergen Ributzka // for both before we give up. 7958013e81dSBenjamin Kramer for (const char *extension : {"", ".tbd"}) { 7968aaae5a9SJuergen Ributzka llvm::sys::path::replace_extension(LibName, extension); 79711dfe6feSDouglas Gregor if (FileMgr.getFile(LibName)) { 79811dfe6feSDouglas Gregor Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name, 79911dfe6feSDouglas Gregor /*IsFramework=*/true)); 8008aaae5a9SJuergen Ributzka return; 8018aaae5a9SJuergen Ributzka } 80211dfe6feSDouglas Gregor } 80311dfe6feSDouglas Gregor } 80411dfe6feSDouglas Gregor 805a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 806a525400dSBen Langmuir bool IsSystem, Module *Parent) { 807c1d88ea5SBen Langmuir Attributes Attrs; 808c1d88ea5SBen Langmuir Attrs.IsSystem = IsSystem; 809a525400dSBen Langmuir return inferFrameworkModule(FrameworkDir, Attrs, Parent); 810c1d88ea5SBen Langmuir } 811c1d88ea5SBen Langmuir 812a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 813c1d88ea5SBen Langmuir Attributes Attrs, Module *Parent) { 814a525400dSBen Langmuir // Note: as an egregious but useful hack we use the real path here, because 815a525400dSBen Langmuir // we might be looking at an embedded framework that symlinks out to a 816a525400dSBen Langmuir // top-level framework, and we need to infer as if we were naming the 817a525400dSBen Langmuir // top-level framework. 818a525400dSBen Langmuir StringRef FrameworkDirName = 819a525400dSBen Langmuir SourceMgr.getFileManager().getCanonicalName(FrameworkDir); 820a525400dSBen Langmuir 821a525400dSBen Langmuir // In case this is a case-insensitive filesystem, use the canonical 822a525400dSBen Langmuir // directory name as the ModuleName, since modules are case-sensitive. 823a525400dSBen Langmuir // FIXME: we should be able to give a fix-it hint for the correct spelling. 824a525400dSBen Langmuir SmallString<32> ModuleNameStorage; 825a525400dSBen Langmuir StringRef ModuleName = sanitizeFilenameAsIdentifier( 826a525400dSBen Langmuir llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage); 827c1d88ea5SBen Langmuir 82856c64013SDouglas Gregor // Check whether we've already found this module. 829e89dbc1dSDouglas Gregor if (Module *Mod = lookupModuleQualified(ModuleName, Parent)) 830e89dbc1dSDouglas Gregor return Mod; 831e89dbc1dSDouglas Gregor 8321f76c4e8SManuel Klimek FileManager &FileMgr = SourceMgr.getFileManager(); 83356c64013SDouglas Gregor 8349194a91dSDouglas Gregor // If the framework has a parent path from which we're allowed to infer 8359194a91dSDouglas Gregor // a framework module, do so. 836beee15e7SBen Langmuir const FileEntry *ModuleMapFile = nullptr; 8379194a91dSDouglas Gregor if (!Parent) { 8384ddf2221SDouglas Gregor // Determine whether we're allowed to infer a module map. 8399194a91dSDouglas Gregor bool canInfer = false; 8404ddf2221SDouglas Gregor if (llvm::sys::path::has_parent_path(FrameworkDirName)) { 8419194a91dSDouglas Gregor // Figure out the parent path. 8424ddf2221SDouglas Gregor StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName); 8439194a91dSDouglas Gregor if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) { 8449194a91dSDouglas Gregor // Check whether we have already looked into the parent directory 8459194a91dSDouglas Gregor // for a module map. 846e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator 8479194a91dSDouglas Gregor inferred = InferredDirectories.find(ParentDir); 8489194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) { 8499194a91dSDouglas Gregor // We haven't looked here before. Load a module map, if there is 8509194a91dSDouglas Gregor // one. 851984e1df7SBen Langmuir bool IsFrameworkDir = Parent.endswith(".framework"); 852984e1df7SBen Langmuir if (const FileEntry *ModMapFile = 853984e1df7SBen Langmuir HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) { 854c1d88ea5SBen Langmuir parseModuleMapFile(ModMapFile, Attrs.IsSystem, ParentDir); 8559194a91dSDouglas Gregor inferred = InferredDirectories.find(ParentDir); 8569194a91dSDouglas Gregor } 8579194a91dSDouglas Gregor 8589194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) 8599194a91dSDouglas Gregor inferred = InferredDirectories.insert( 8609194a91dSDouglas Gregor std::make_pair(ParentDir, InferredDirectory())).first; 8619194a91dSDouglas Gregor } 8629194a91dSDouglas Gregor 8639194a91dSDouglas Gregor if (inferred->second.InferModules) { 8649194a91dSDouglas Gregor // We're allowed to infer for this directory, but make sure it's okay 8659194a91dSDouglas Gregor // to infer this particular module. 8664ddf2221SDouglas Gregor StringRef Name = llvm::sys::path::stem(FrameworkDirName); 8679194a91dSDouglas Gregor canInfer = std::find(inferred->second.ExcludedModules.begin(), 8689194a91dSDouglas Gregor inferred->second.ExcludedModules.end(), 8699194a91dSDouglas Gregor Name) == inferred->second.ExcludedModules.end(); 8709194a91dSDouglas Gregor 871c1d88ea5SBen Langmuir Attrs.IsSystem |= inferred->second.Attrs.IsSystem; 872c1d88ea5SBen Langmuir Attrs.IsExternC |= inferred->second.Attrs.IsExternC; 873c1d88ea5SBen Langmuir Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive; 874ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes |= 875ed84df00SBruno Cardoso Lopes inferred->second.Attrs.NoUndeclaredIncludes; 876beee15e7SBen Langmuir ModuleMapFile = inferred->second.ModuleMapFile; 8779194a91dSDouglas Gregor } 8789194a91dSDouglas Gregor } 8799194a91dSDouglas Gregor } 8809194a91dSDouglas Gregor 8819194a91dSDouglas Gregor // If we're not allowed to infer a framework module, don't. 8829194a91dSDouglas Gregor if (!canInfer) 883d2d442caSCraig Topper return nullptr; 884beee15e7SBen Langmuir } else 8859d6448b1SBen Langmuir ModuleMapFile = getModuleMapFileForUniquing(Parent); 8869194a91dSDouglas Gregor 8879194a91dSDouglas Gregor 88856c64013SDouglas Gregor // Look for an umbrella header. 8892c1dd271SDylan Noblesmith SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 89017381a06SBenjamin Kramer llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h"); 891e89dbc1dSDouglas Gregor const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName); 89256c64013SDouglas Gregor 89356c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the 89456c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good 89556c64013SDouglas Gregor // idea. 89656c64013SDouglas Gregor if (!UmbrellaHeader) 897d2d442caSCraig Topper return nullptr; 89856c64013SDouglas Gregor 8999d6448b1SBen Langmuir Module *Result = new Module(ModuleName, SourceLocation(), Parent, 900a7e2cc68SRichard Smith /*IsFramework=*/true, /*IsExplicit=*/false, 901a7e2cc68SRichard Smith NumCreatedModules++); 9029d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = ModuleMapFile; 9039d6448b1SBen Langmuir Result->IsInferred = true; 9047e82e019SRichard Smith if (!Parent) { 9057e82e019SRichard Smith if (LangOpts.CurrentModule == ModuleName) 906ba7f2f71SDaniel Jasper SourceModule = Result; 9077e82e019SRichard Smith Modules[ModuleName] = Result; 908ba7f2f71SDaniel Jasper } 909c1d88ea5SBen Langmuir 910c1d88ea5SBen Langmuir Result->IsSystem |= Attrs.IsSystem; 911c1d88ea5SBen Langmuir Result->IsExternC |= Attrs.IsExternC; 912c1d88ea5SBen Langmuir Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive; 913ed84df00SBruno Cardoso Lopes Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes; 9142b63d15fSRichard Smith Result->Directory = FrameworkDir; 915a686e1b0SDouglas Gregor 916322f633cSDouglas Gregor // umbrella header "umbrella-header-name" 9172b63d15fSRichard Smith // 9182b63d15fSRichard Smith // The "Headers/" component of the name is implied because this is 9192b63d15fSRichard Smith // a framework module. 9202b63d15fSRichard Smith setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h"); 921d8bd7537SDouglas Gregor 922d8bd7537SDouglas Gregor // export * 923d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 924d8bd7537SDouglas Gregor 925a89c5ac4SDouglas Gregor // module * { export * } 926a89c5ac4SDouglas Gregor Result->InferSubmodules = true; 927a89c5ac4SDouglas Gregor Result->InferExportWildcard = true; 928a89c5ac4SDouglas Gregor 929e89dbc1dSDouglas Gregor // Look for subframeworks. 930c080917eSRafael Espindola std::error_code EC; 9312c1dd271SDylan Noblesmith SmallString<128> SubframeworksDirName 932ddaa69cbSDouglas Gregor = StringRef(FrameworkDir->getName()); 933e89dbc1dSDouglas Gregor llvm::sys::path::append(SubframeworksDirName, "Frameworks"); 9342d4d8cb3SBenjamin Kramer llvm::sys::path::native(SubframeworksDirName); 935b171a59bSBruno Cardoso Lopes vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); 936b171a59bSBruno Cardoso Lopes for (vfs::directory_iterator Dir = FS.dir_begin(SubframeworksDirName, EC), 937b171a59bSBruno Cardoso Lopes DirEnd; 938e89dbc1dSDouglas Gregor Dir != DirEnd && !EC; Dir.increment(EC)) { 939b171a59bSBruno Cardoso Lopes if (!StringRef(Dir->getName()).endswith(".framework")) 940e89dbc1dSDouglas Gregor continue; 941f2161a70SDouglas Gregor 942b171a59bSBruno Cardoso Lopes if (const DirectoryEntry *SubframeworkDir = 943b171a59bSBruno Cardoso Lopes FileMgr.getDirectory(Dir->getName())) { 94407c22b78SDouglas Gregor // Note: as an egregious but useful hack, we use the real path here and 94507c22b78SDouglas Gregor // check whether it is actually a subdirectory of the parent directory. 94607c22b78SDouglas Gregor // This will not be the case if the 'subframework' is actually a symlink 94707c22b78SDouglas Gregor // out to a top-level framework. 948e00c8b20SDouglas Gregor StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir); 94907c22b78SDouglas Gregor bool FoundParent = false; 95007c22b78SDouglas Gregor do { 95107c22b78SDouglas Gregor // Get the parent directory name. 95207c22b78SDouglas Gregor SubframeworkDirName 95307c22b78SDouglas Gregor = llvm::sys::path::parent_path(SubframeworkDirName); 95407c22b78SDouglas Gregor if (SubframeworkDirName.empty()) 95507c22b78SDouglas Gregor break; 95607c22b78SDouglas Gregor 95707c22b78SDouglas Gregor if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) { 95807c22b78SDouglas Gregor FoundParent = true; 95907c22b78SDouglas Gregor break; 96007c22b78SDouglas Gregor } 96107c22b78SDouglas Gregor } while (true); 96207c22b78SDouglas Gregor 96307c22b78SDouglas Gregor if (!FoundParent) 96407c22b78SDouglas Gregor continue; 96507c22b78SDouglas Gregor 966e89dbc1dSDouglas Gregor // FIXME: Do we want to warn about subframeworks without umbrella headers? 967a525400dSBen Langmuir inferFrameworkModule(SubframeworkDir, Attrs, Result); 968e89dbc1dSDouglas Gregor } 969e89dbc1dSDouglas Gregor } 970e89dbc1dSDouglas Gregor 97111dfe6feSDouglas Gregor // If the module is a top-level framework, automatically link against the 97211dfe6feSDouglas Gregor // framework. 97311dfe6feSDouglas Gregor if (!Result->isSubFramework()) { 97411dfe6feSDouglas Gregor inferFrameworkLink(Result, FrameworkDir, FileMgr); 97511dfe6feSDouglas Gregor } 97611dfe6feSDouglas Gregor 97756c64013SDouglas Gregor return Result; 97856c64013SDouglas Gregor } 97956c64013SDouglas Gregor 9802b63d15fSRichard Smith void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader, 9812b63d15fSRichard Smith Twine NameAsWritten) { 98297da9178SDaniel Jasper Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader)); 98373141fa9SDouglas Gregor Mod->Umbrella = UmbrellaHeader; 9842b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 9857033127bSDouglas Gregor UmbrellaDirs[UmbrellaHeader->getDir()] = Mod; 986b3a0fa48SBruno Cardoso Lopes 987b3a0fa48SBruno Cardoso Lopes // Notify callbacks that we just added a new header. 988b3a0fa48SBruno Cardoso Lopes for (const auto &Cb : Callbacks) 989b3a0fa48SBruno Cardoso Lopes Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader); 990a89c5ac4SDouglas Gregor } 991a89c5ac4SDouglas Gregor 9922b63d15fSRichard Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, 9932b63d15fSRichard Smith Twine NameAsWritten) { 994524e33e1SDouglas Gregor Mod->Umbrella = UmbrellaDir; 9952b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 996524e33e1SDouglas Gregor UmbrellaDirs[UmbrellaDir] = Mod; 997524e33e1SDouglas Gregor } 998524e33e1SDouglas Gregor 999040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod, 1000040e1266SRichard Smith Module::UnresolvedHeaderDirective Header) { 1001040e1266SRichard Smith // If there is a builtin counterpart to this file, add it now so it can 1002040e1266SRichard Smith // wrap the system header. 1003040e1266SRichard Smith if (resolveAsBuiltinHeader(Mod, Header)) { 1004040e1266SRichard Smith // If we have both a builtin and system version of the file, the 1005040e1266SRichard Smith // builtin version may want to inject macros into the system header, so 1006040e1266SRichard Smith // force the system header to be treated as a textual header in this 1007040e1266SRichard Smith // case. 1008040e1266SRichard Smith Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole( 1009040e1266SRichard Smith headerKindToRole(Header.Kind) | ModuleMap::TextualHeader)); 1010040e1266SRichard Smith Header.HasBuiltinHeader = true; 10113c1a41adSRichard Smith } 1012040e1266SRichard Smith 1013040e1266SRichard Smith // If possible, don't stat the header until we need to. This requires the 1014040e1266SRichard Smith // user to have provided us with some stat information about the file. 1015040e1266SRichard Smith // FIXME: Add support for lazily stat'ing umbrella headers and excluded 1016040e1266SRichard Smith // headers. 1017040e1266SRichard Smith if ((Header.Size || Header.ModTime) && !Header.IsUmbrella && 1018040e1266SRichard Smith Header.Kind != Module::HK_Excluded) { 1019040e1266SRichard Smith // We expect more variation in mtime than size, so if we're given both, 1020040e1266SRichard Smith // use the mtime as the key. 1021040e1266SRichard Smith if (Header.ModTime) 1022040e1266SRichard Smith LazyHeadersByModTime[*Header.ModTime].push_back(Mod); 1023040e1266SRichard Smith else 1024040e1266SRichard Smith LazyHeadersBySize[*Header.Size].push_back(Mod); 1025040e1266SRichard Smith Mod->UnresolvedHeaders.push_back(Header); 1026040e1266SRichard Smith return; 1027040e1266SRichard Smith } 1028040e1266SRichard Smith 1029040e1266SRichard Smith // We don't have stat information or can't defer looking this file up. 1030040e1266SRichard Smith // Perform the lookup now. 1031040e1266SRichard Smith resolveHeader(Mod, Header); 1032040e1266SRichard Smith } 1033040e1266SRichard Smith 1034040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const { 1035040e1266SRichard Smith auto BySize = LazyHeadersBySize.find(File->getSize()); 1036040e1266SRichard Smith if (BySize != LazyHeadersBySize.end()) { 1037040e1266SRichard Smith for (auto *M : BySize->second) 1038040e1266SRichard Smith resolveHeaderDirectives(M); 1039040e1266SRichard Smith LazyHeadersBySize.erase(BySize); 1040040e1266SRichard Smith } 1041040e1266SRichard Smith 1042040e1266SRichard Smith auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime()); 1043040e1266SRichard Smith if (ByModTime != LazyHeadersByModTime.end()) { 1044040e1266SRichard Smith for (auto *M : ByModTime->second) 1045040e1266SRichard Smith resolveHeaderDirectives(M); 1046040e1266SRichard Smith LazyHeadersByModTime.erase(ByModTime); 1047040e1266SRichard Smith } 1048040e1266SRichard Smith } 1049040e1266SRichard Smith 1050040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(Module *Mod) const { 1051040e1266SRichard Smith for (auto &Header : Mod->UnresolvedHeaders) 1052040e1266SRichard Smith // This operation is logically const; we're just changing how we represent 1053040e1266SRichard Smith // the header information for this file. 1054040e1266SRichard Smith const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header); 1055040e1266SRichard Smith Mod->UnresolvedHeaders.clear(); 10560e98d938SNAKAMURA Takumi } 1057202210b3SRichard Smith 10583c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header, 1059d8879c85SRichard Smith ModuleHeaderRole Role, bool Imported) { 1060386bb073SRichard Smith KnownHeader KH(Mod, Role); 10613c1a41adSRichard Smith 1062386bb073SRichard Smith // Only add each header to the headers list once. 1063386bb073SRichard Smith // FIXME: Should we diagnose if a header is listed twice in the 1064386bb073SRichard Smith // same module definition? 1065386bb073SRichard Smith auto &HeaderList = Headers[Header.Entry]; 1066386bb073SRichard Smith for (auto H : HeaderList) 1067386bb073SRichard Smith if (H == KH) 1068386bb073SRichard Smith return; 1069386bb073SRichard Smith 1070386bb073SRichard Smith HeaderList.push_back(KH); 10711ec383c7SPiotr Padlewski Mod->Headers[headerRoleToKind(Role)].push_back(Header); 1072386bb073SRichard Smith 10737e82e019SRichard Smith bool isCompilingModuleHeader = 1074bbcc9f04SRichard Smith LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule; 1075d8879c85SRichard Smith if (!Imported || isCompilingModuleHeader) { 1076d8879c85SRichard Smith // When we import HeaderFileInfo, the external source is expected to 1077d8879c85SRichard Smith // set the isModuleHeader flag itself. 1078d8879c85SRichard Smith HeaderInfo.MarkFileModuleHeader(Header.Entry, Role, 1079d8879c85SRichard Smith isCompilingModuleHeader); 1080d8879c85SRichard Smith } 1081e62cfd7cSBruno Cardoso Lopes 1082e62cfd7cSBruno Cardoso Lopes // Notify callbacks that we just added a new header. 1083e62cfd7cSBruno Cardoso Lopes for (const auto &Cb : Callbacks) 1084f0841790SBruno Cardoso Lopes Cb->moduleMapAddHeader(Header.Entry->getName()); 1085a89c5ac4SDouglas Gregor } 1086a89c5ac4SDouglas Gregor 10873c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) { 1088feb54b6dSRichard Smith // Add this as a known header so we won't implicitly add it to any 1089feb54b6dSRichard Smith // umbrella directory module. 1090feb54b6dSRichard Smith // FIXME: Should we only exclude it from umbrella modules within the 1091feb54b6dSRichard Smith // specified module? 10923c1a41adSRichard Smith (void) Headers[Header.Entry]; 10933c1a41adSRichard Smith 10943c1a41adSRichard Smith Mod->Headers[Module::HK_Excluded].push_back(std::move(Header)); 1095feb54b6dSRichard Smith } 1096feb54b6dSRichard Smith 1097514b636aSDouglas Gregor const FileEntry * 10984b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const { 10991f76c4e8SManuel Klimek if (Module->DefinitionLoc.isInvalid()) 1100d2d442caSCraig Topper return nullptr; 1101514b636aSDouglas Gregor 11021f76c4e8SManuel Klimek return SourceMgr.getFileEntryForID( 11031f76c4e8SManuel Klimek SourceMgr.getFileID(Module->DefinitionLoc)); 1104514b636aSDouglas Gregor } 1105514b636aSDouglas Gregor 11064b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const { 11079d6448b1SBen Langmuir if (M->IsInferred) { 11089d6448b1SBen Langmuir assert(InferredModuleAllowedBy.count(M) && "missing inferred module map"); 11099d6448b1SBen Langmuir return InferredModuleAllowedBy.find(M)->second; 11109d6448b1SBen Langmuir } 11119d6448b1SBen Langmuir return getContainingModuleMapFile(M); 11129d6448b1SBen Langmuir } 11139d6448b1SBen Langmuir 11149d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) { 11159d6448b1SBen Langmuir assert(M->IsInferred && "module not inferred"); 11169d6448b1SBen Langmuir InferredModuleAllowedBy[M] = ModMap; 11179d6448b1SBen Langmuir } 11189d6448b1SBen Langmuir 1119cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() { 1120718292f2SDouglas Gregor llvm::errs() << "Modules:"; 1121718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 1122718292f2SDouglas Gregor MEnd = Modules.end(); 1123718292f2SDouglas Gregor M != MEnd; ++M) 1124d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 1125718292f2SDouglas Gregor 1126718292f2SDouglas Gregor llvm::errs() << "Headers:"; 112759527666SDouglas Gregor for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end(); 1128718292f2SDouglas Gregor H != HEnd; ++H) { 112997da9178SDaniel Jasper llvm::errs() << " \"" << H->first->getName() << "\" -> "; 113097da9178SDaniel Jasper for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(), 113197da9178SDaniel Jasper E = H->second.end(); 113297da9178SDaniel Jasper I != E; ++I) { 113397da9178SDaniel Jasper if (I != H->second.begin()) 113497da9178SDaniel Jasper llvm::errs() << ","; 113597da9178SDaniel Jasper llvm::errs() << I->getModule()->getFullModuleName(); 113697da9178SDaniel Jasper } 113797da9178SDaniel Jasper llvm::errs() << "\n"; 1138718292f2SDouglas Gregor } 1139718292f2SDouglas Gregor } 1140718292f2SDouglas Gregor 11412b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) { 114242413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedExports); 114342413141SRichard Smith Mod->UnresolvedExports.clear(); 114442413141SRichard Smith for (auto &UE : Unresolved) { 114542413141SRichard Smith Module::ExportDecl Export = resolveExport(Mod, UE, Complain); 1146f5eedd05SDouglas Gregor if (Export.getPointer() || Export.getInt()) 11472b82c2a5SDouglas Gregor Mod->Exports.push_back(Export); 11482b82c2a5SDouglas Gregor else 114942413141SRichard Smith Mod->UnresolvedExports.push_back(UE); 11502b82c2a5SDouglas Gregor } 115142413141SRichard Smith return !Mod->UnresolvedExports.empty(); 11522b82c2a5SDouglas Gregor } 11532b82c2a5SDouglas Gregor 1154ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) { 115542413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedDirectUses); 115642413141SRichard Smith Mod->UnresolvedDirectUses.clear(); 115742413141SRichard Smith for (auto &UDU : Unresolved) { 115842413141SRichard Smith Module *DirectUse = resolveModuleId(UDU, Mod, Complain); 1159ba7f2f71SDaniel Jasper if (DirectUse) 1160ba7f2f71SDaniel Jasper Mod->DirectUses.push_back(DirectUse); 1161ba7f2f71SDaniel Jasper else 116242413141SRichard Smith Mod->UnresolvedDirectUses.push_back(UDU); 1163ba7f2f71SDaniel Jasper } 116442413141SRichard Smith return !Mod->UnresolvedDirectUses.empty(); 1165ba7f2f71SDaniel Jasper } 1166ba7f2f71SDaniel Jasper 1167fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) { 116842413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedConflicts); 116942413141SRichard Smith Mod->UnresolvedConflicts.clear(); 117042413141SRichard Smith for (auto &UC : Unresolved) { 117142413141SRichard Smith if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) { 1172fb912657SDouglas Gregor Module::Conflict Conflict; 1173fb912657SDouglas Gregor Conflict.Other = OtherMod; 117442413141SRichard Smith Conflict.Message = UC.Message; 1175fb912657SDouglas Gregor Mod->Conflicts.push_back(Conflict); 117642413141SRichard Smith } else 117742413141SRichard Smith Mod->UnresolvedConflicts.push_back(UC); 1178fb912657SDouglas Gregor } 117942413141SRichard Smith return !Mod->UnresolvedConflicts.empty(); 1180fb912657SDouglas Gregor } 1181fb912657SDouglas Gregor 1182718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1183718292f2SDouglas Gregor // Module map file parser 1184718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1185718292f2SDouglas Gregor 1186718292f2SDouglas Gregor namespace clang { 1187718292f2SDouglas Gregor /// \brief A token in a module map file. 1188718292f2SDouglas Gregor struct MMToken { 1189718292f2SDouglas Gregor enum TokenKind { 11901fb5c3a6SDouglas Gregor Comma, 119135b13eceSDouglas Gregor ConfigMacros, 1192fb912657SDouglas Gregor Conflict, 1193718292f2SDouglas Gregor EndOfFile, 1194718292f2SDouglas Gregor HeaderKeyword, 1195718292f2SDouglas Gregor Identifier, 1196a3feee2aSRichard Smith Exclaim, 119759527666SDouglas Gregor ExcludeKeyword, 1198718292f2SDouglas Gregor ExplicitKeyword, 11992b82c2a5SDouglas Gregor ExportKeyword, 120097292843SDaniel Jasper ExternKeyword, 1201755b2055SDouglas Gregor FrameworkKeyword, 12026ddfca91SDouglas Gregor LinkKeyword, 1203718292f2SDouglas Gregor ModuleKeyword, 12042b82c2a5SDouglas Gregor Period, 1205b53e5483SLawrence Crowl PrivateKeyword, 1206718292f2SDouglas Gregor UmbrellaKeyword, 1207ba7f2f71SDaniel Jasper UseKeyword, 12081fb5c3a6SDouglas Gregor RequiresKeyword, 12092b82c2a5SDouglas Gregor Star, 1210718292f2SDouglas Gregor StringLiteral, 1211040e1266SRichard Smith IntegerLiteral, 1212306d8920SRichard Smith TextualKeyword, 1213718292f2SDouglas Gregor LBrace, 1214a686e1b0SDouglas Gregor RBrace, 1215a686e1b0SDouglas Gregor LSquare, 1216a686e1b0SDouglas Gregor RSquare 1217718292f2SDouglas Gregor } Kind; 1218718292f2SDouglas Gregor 1219718292f2SDouglas Gregor unsigned Location; 1220718292f2SDouglas Gregor unsigned StringLength; 1221040e1266SRichard Smith union { 1222040e1266SRichard Smith // If Kind != IntegerLiteral. 1223718292f2SDouglas Gregor const char *StringData; 1224040e1266SRichard Smith // If Kind == IntegerLiteral. 1225040e1266SRichard Smith uint64_t IntegerValue; 1226040e1266SRichard Smith }; 1227718292f2SDouglas Gregor 1228718292f2SDouglas Gregor void clear() { 1229718292f2SDouglas Gregor Kind = EndOfFile; 1230718292f2SDouglas Gregor Location = 0; 1231718292f2SDouglas Gregor StringLength = 0; 1232d2d442caSCraig Topper StringData = nullptr; 1233718292f2SDouglas Gregor } 1234718292f2SDouglas Gregor 1235718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 1236718292f2SDouglas Gregor 1237718292f2SDouglas Gregor SourceLocation getLocation() const { 1238718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 1239718292f2SDouglas Gregor } 1240718292f2SDouglas Gregor 1241040e1266SRichard Smith uint64_t getInteger() const { 1242040e1266SRichard Smith return Kind == IntegerLiteral ? IntegerValue : 0; 1243040e1266SRichard Smith } 1244040e1266SRichard Smith 1245718292f2SDouglas Gregor StringRef getString() const { 1246040e1266SRichard Smith return Kind == IntegerLiteral ? StringRef() 1247040e1266SRichard Smith : StringRef(StringData, StringLength); 1248718292f2SDouglas Gregor } 1249718292f2SDouglas Gregor }; 1250718292f2SDouglas Gregor 1251718292f2SDouglas Gregor class ModuleMapParser { 1252718292f2SDouglas Gregor Lexer &L; 1253718292f2SDouglas Gregor SourceManager &SourceMgr; 1254bc10b9fbSDouglas Gregor 1255bc10b9fbSDouglas Gregor /// \brief Default target information, used only for string literal 1256bc10b9fbSDouglas Gregor /// parsing. 1257bc10b9fbSDouglas Gregor const TargetInfo *Target; 1258bc10b9fbSDouglas Gregor 1259718292f2SDouglas Gregor DiagnosticsEngine &Diags; 1260718292f2SDouglas Gregor ModuleMap ⤅ 1261718292f2SDouglas Gregor 1262beee15e7SBen Langmuir /// \brief The current module map file. 1263beee15e7SBen Langmuir const FileEntry *ModuleMapFile; 1264beee15e7SBen Langmuir 12659acb99e3SRichard Smith /// \brief The directory that file names in this module map file should 12669acb99e3SRichard Smith /// be resolved relative to. 12675257fc63SDouglas Gregor const DirectoryEntry *Directory; 12685257fc63SDouglas Gregor 1269963c5535SDouglas Gregor /// \brief Whether this module map is in a system header directory. 1270963c5535SDouglas Gregor bool IsSystem; 1271963c5535SDouglas Gregor 1272718292f2SDouglas Gregor /// \brief Whether an error occurred. 1273718292f2SDouglas Gregor bool HadError; 1274718292f2SDouglas Gregor 1275718292f2SDouglas Gregor /// \brief Stores string data for the various string literals referenced 1276718292f2SDouglas Gregor /// during parsing. 1277718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 1278718292f2SDouglas Gregor 1279718292f2SDouglas Gregor /// \brief The current token. 1280718292f2SDouglas Gregor MMToken Tok; 1281718292f2SDouglas Gregor 1282718292f2SDouglas Gregor /// \brief The active module. 1283de3ef502SDouglas Gregor Module *ActiveModule; 1284718292f2SDouglas Gregor 12857ff29148SBen Langmuir /// \brief Whether a module uses the 'requires excluded' hack to mark its 12867ff29148SBen Langmuir /// contents as 'textual'. 12877ff29148SBen Langmuir /// 12887ff29148SBen Langmuir /// On older Darwin SDK versions, 'requires excluded' is used to mark the 12897ff29148SBen Langmuir /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as 12907ff29148SBen Langmuir /// non-modular headers. For backwards compatibility, we continue to 12917ff29148SBen Langmuir /// support this idiom for just these modules, and map the headers to 12927ff29148SBen Langmuir /// 'textual' to match the original intent. 12937ff29148SBen Langmuir llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack; 12947ff29148SBen Langmuir 1295718292f2SDouglas Gregor /// \brief Consume the current token and return its location. 1296718292f2SDouglas Gregor SourceLocation consumeToken(); 1297718292f2SDouglas Gregor 1298718292f2SDouglas Gregor /// \brief Skip tokens until we reach the a token with the given kind 1299718292f2SDouglas Gregor /// (or the end of the file). 1300718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 1301718292f2SDouglas Gregor 1302f857950dSDmitri Gribenko typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId; 1303e7ab3669SDouglas Gregor bool parseModuleId(ModuleId &Id); 1304718292f2SDouglas Gregor void parseModuleDecl(); 130597292843SDaniel Jasper void parseExternModuleDecl(); 13061fb5c3a6SDouglas Gregor void parseRequiresDecl(); 1307b53e5483SLawrence Crowl void parseHeaderDecl(clang::MMToken::TokenKind, 1308b53e5483SLawrence Crowl SourceLocation LeadingLoc); 1309524e33e1SDouglas Gregor void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc); 13102b82c2a5SDouglas Gregor void parseExportDecl(); 1311ba7f2f71SDaniel Jasper void parseUseDecl(); 13126ddfca91SDouglas Gregor void parseLinkDecl(); 131335b13eceSDouglas Gregor void parseConfigMacros(); 1314fb912657SDouglas Gregor void parseConflict(); 13159194a91dSDouglas Gregor void parseInferredModuleDecl(bool Framework, bool Explicit); 1316c1d88ea5SBen Langmuir 1317c1d88ea5SBen Langmuir typedef ModuleMap::Attributes Attributes; 13184442605fSBill Wendling bool parseOptionalAttributes(Attributes &Attrs); 1319718292f2SDouglas Gregor 1320718292f2SDouglas Gregor public: 1321718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 1322bc10b9fbSDouglas Gregor const TargetInfo *Target, 1323718292f2SDouglas Gregor DiagnosticsEngine &Diags, 13245257fc63SDouglas Gregor ModuleMap &Map, 1325beee15e7SBen Langmuir const FileEntry *ModuleMapFile, 13263ec6663bSDouglas Gregor const DirectoryEntry *Directory, 1327963c5535SDouglas Gregor bool IsSystem) 1328bc10b9fbSDouglas Gregor : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map), 1329beee15e7SBen Langmuir ModuleMapFile(ModuleMapFile), Directory(Directory), 13301d60987fSRichard Smith IsSystem(IsSystem), HadError(false), ActiveModule(nullptr) 1331718292f2SDouglas Gregor { 1332718292f2SDouglas Gregor Tok.clear(); 1333718292f2SDouglas Gregor consumeToken(); 1334718292f2SDouglas Gregor } 1335718292f2SDouglas Gregor 1336718292f2SDouglas Gregor bool parseModuleMapFile(); 13378128f332SRichard Smith 13388128f332SRichard Smith bool terminatedByDirective() { return false; } 13398128f332SRichard Smith SourceLocation getLocation() { return Tok.getLocation(); } 1340718292f2SDouglas Gregor }; 1341ab9db510SAlexander Kornienko } 1342718292f2SDouglas Gregor 1343718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 1344718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 1345718292f2SDouglas Gregor 13468128f332SRichard Smith retry: 13478128f332SRichard Smith Tok.clear(); 1348718292f2SDouglas Gregor Token LToken; 1349718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 1350718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 1351718292f2SDouglas Gregor switch (LToken.getKind()) { 13522d57cea2SAlp Toker case tok::raw_identifier: { 13532d57cea2SAlp Toker StringRef RI = LToken.getRawIdentifier(); 13542d57cea2SAlp Toker Tok.StringData = RI.data(); 13552d57cea2SAlp Toker Tok.StringLength = RI.size(); 13562d57cea2SAlp Toker Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI) 135735b13eceSDouglas Gregor .Case("config_macros", MMToken::ConfigMacros) 1358fb912657SDouglas Gregor .Case("conflict", MMToken::Conflict) 135959527666SDouglas Gregor .Case("exclude", MMToken::ExcludeKeyword) 1360718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 13612b82c2a5SDouglas Gregor .Case("export", MMToken::ExportKeyword) 136297292843SDaniel Jasper .Case("extern", MMToken::ExternKeyword) 1363755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 136435b13eceSDouglas Gregor .Case("header", MMToken::HeaderKeyword) 13656ddfca91SDouglas Gregor .Case("link", MMToken::LinkKeyword) 1366718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 1367b53e5483SLawrence Crowl .Case("private", MMToken::PrivateKeyword) 13681fb5c3a6SDouglas Gregor .Case("requires", MMToken::RequiresKeyword) 1369306d8920SRichard Smith .Case("textual", MMToken::TextualKeyword) 1370718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 1371ba7f2f71SDaniel Jasper .Case("use", MMToken::UseKeyword) 1372718292f2SDouglas Gregor .Default(MMToken::Identifier); 1373718292f2SDouglas Gregor break; 13742d57cea2SAlp Toker } 1375718292f2SDouglas Gregor 13761fb5c3a6SDouglas Gregor case tok::comma: 13771fb5c3a6SDouglas Gregor Tok.Kind = MMToken::Comma; 13781fb5c3a6SDouglas Gregor break; 13791fb5c3a6SDouglas Gregor 1380718292f2SDouglas Gregor case tok::eof: 1381718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 1382718292f2SDouglas Gregor break; 1383718292f2SDouglas Gregor 1384718292f2SDouglas Gregor case tok::l_brace: 1385718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 1386718292f2SDouglas Gregor break; 1387718292f2SDouglas Gregor 1388a686e1b0SDouglas Gregor case tok::l_square: 1389a686e1b0SDouglas Gregor Tok.Kind = MMToken::LSquare; 1390a686e1b0SDouglas Gregor break; 1391a686e1b0SDouglas Gregor 13922b82c2a5SDouglas Gregor case tok::period: 13932b82c2a5SDouglas Gregor Tok.Kind = MMToken::Period; 13942b82c2a5SDouglas Gregor break; 13952b82c2a5SDouglas Gregor 1396718292f2SDouglas Gregor case tok::r_brace: 1397718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 1398718292f2SDouglas Gregor break; 1399718292f2SDouglas Gregor 1400a686e1b0SDouglas Gregor case tok::r_square: 1401a686e1b0SDouglas Gregor Tok.Kind = MMToken::RSquare; 1402a686e1b0SDouglas Gregor break; 1403a686e1b0SDouglas Gregor 14042b82c2a5SDouglas Gregor case tok::star: 14052b82c2a5SDouglas Gregor Tok.Kind = MMToken::Star; 14062b82c2a5SDouglas Gregor break; 14072b82c2a5SDouglas Gregor 1408a3feee2aSRichard Smith case tok::exclaim: 1409a3feee2aSRichard Smith Tok.Kind = MMToken::Exclaim; 1410a3feee2aSRichard Smith break; 1411a3feee2aSRichard Smith 1412718292f2SDouglas Gregor case tok::string_literal: { 1413d67aea28SRichard Smith if (LToken.hasUDSuffix()) { 1414d67aea28SRichard Smith Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl); 1415d67aea28SRichard Smith HadError = true; 1416d67aea28SRichard Smith goto retry; 1417d67aea28SRichard Smith } 1418d67aea28SRichard Smith 1419718292f2SDouglas Gregor // Parse the string literal. 1420718292f2SDouglas Gregor LangOptions LangOpts; 14219d5583efSCraig Topper StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target); 1422718292f2SDouglas Gregor if (StringLiteral.hadError) 1423718292f2SDouglas Gregor goto retry; 1424718292f2SDouglas Gregor 1425718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 1426718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 1427718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 1428718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 1429718292f2SDouglas Gregor Saved[Length] = 0; 1430718292f2SDouglas Gregor 1431718292f2SDouglas Gregor // Form the token. 1432718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 1433718292f2SDouglas Gregor Tok.StringData = Saved; 1434718292f2SDouglas Gregor Tok.StringLength = Length; 1435718292f2SDouglas Gregor break; 1436718292f2SDouglas Gregor } 1437718292f2SDouglas Gregor 1438040e1266SRichard Smith case tok::numeric_constant: { 1439040e1266SRichard Smith // We don't support any suffixes or other complications. 1440040e1266SRichard Smith SmallString<32> SpellingBuffer; 1441040e1266SRichard Smith SpellingBuffer.resize(LToken.getLength() + 1); 1442040e1266SRichard Smith const char *Start = SpellingBuffer.data(); 1443040e1266SRichard Smith unsigned Length = 1444040e1266SRichard Smith Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts()); 1445040e1266SRichard Smith uint64_t Value; 1446040e1266SRichard Smith if (StringRef(Start, Length).getAsInteger(0, Value)) { 1447040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1448040e1266SRichard Smith HadError = true; 1449040e1266SRichard Smith goto retry; 1450040e1266SRichard Smith } 1451040e1266SRichard Smith 1452040e1266SRichard Smith Tok.Kind = MMToken::IntegerLiteral; 1453040e1266SRichard Smith Tok.IntegerValue = Value; 1454040e1266SRichard Smith break; 1455040e1266SRichard Smith } 1456040e1266SRichard Smith 1457718292f2SDouglas Gregor case tok::comment: 1458718292f2SDouglas Gregor goto retry; 1459718292f2SDouglas Gregor 14608128f332SRichard Smith case tok::hash: 14618128f332SRichard Smith // A module map can be terminated prematurely by 14628128f332SRichard Smith // #pragma clang module contents 14638128f332SRichard Smith // When building the module, we'll treat the rest of the file as the 14648128f332SRichard Smith // contents of the module. 14658128f332SRichard Smith { 14668128f332SRichard Smith auto NextIsIdent = [&](StringRef Str) -> bool { 14678128f332SRichard Smith L.LexFromRawLexer(LToken); 14688128f332SRichard Smith return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) && 14698128f332SRichard Smith LToken.getRawIdentifier() == Str; 14708128f332SRichard Smith }; 14718128f332SRichard Smith if (NextIsIdent("pragma") && NextIsIdent("clang") && 14728128f332SRichard Smith NextIsIdent("module") && NextIsIdent("contents")) { 14738128f332SRichard Smith Tok.Kind = MMToken::EndOfFile; 14748128f332SRichard Smith break; 14758128f332SRichard Smith } 14768128f332SRichard Smith } 14778128f332SRichard Smith LLVM_FALLTHROUGH; 14788128f332SRichard Smith 1479718292f2SDouglas Gregor default: 14808128f332SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1481718292f2SDouglas Gregor HadError = true; 1482718292f2SDouglas Gregor goto retry; 1483718292f2SDouglas Gregor } 1484718292f2SDouglas Gregor 1485718292f2SDouglas Gregor return Result; 1486718292f2SDouglas Gregor } 1487718292f2SDouglas Gregor 1488718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 1489718292f2SDouglas Gregor unsigned braceDepth = 0; 1490a686e1b0SDouglas Gregor unsigned squareDepth = 0; 1491718292f2SDouglas Gregor do { 1492718292f2SDouglas Gregor switch (Tok.Kind) { 1493718292f2SDouglas Gregor case MMToken::EndOfFile: 1494718292f2SDouglas Gregor return; 1495718292f2SDouglas Gregor 1496718292f2SDouglas Gregor case MMToken::LBrace: 1497a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1498718292f2SDouglas Gregor return; 1499718292f2SDouglas Gregor 1500718292f2SDouglas Gregor ++braceDepth; 1501718292f2SDouglas Gregor break; 1502718292f2SDouglas Gregor 1503a686e1b0SDouglas Gregor case MMToken::LSquare: 1504a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1505a686e1b0SDouglas Gregor return; 1506a686e1b0SDouglas Gregor 1507a686e1b0SDouglas Gregor ++squareDepth; 1508a686e1b0SDouglas Gregor break; 1509a686e1b0SDouglas Gregor 1510718292f2SDouglas Gregor case MMToken::RBrace: 1511718292f2SDouglas Gregor if (braceDepth > 0) 1512718292f2SDouglas Gregor --braceDepth; 1513718292f2SDouglas Gregor else if (Tok.is(K)) 1514718292f2SDouglas Gregor return; 1515718292f2SDouglas Gregor break; 1516718292f2SDouglas Gregor 1517a686e1b0SDouglas Gregor case MMToken::RSquare: 1518a686e1b0SDouglas Gregor if (squareDepth > 0) 1519a686e1b0SDouglas Gregor --squareDepth; 1520a686e1b0SDouglas Gregor else if (Tok.is(K)) 1521a686e1b0SDouglas Gregor return; 1522a686e1b0SDouglas Gregor break; 1523a686e1b0SDouglas Gregor 1524718292f2SDouglas Gregor default: 1525a686e1b0SDouglas Gregor if (braceDepth == 0 && squareDepth == 0 && Tok.is(K)) 1526718292f2SDouglas Gregor return; 1527718292f2SDouglas Gregor break; 1528718292f2SDouglas Gregor } 1529718292f2SDouglas Gregor 1530718292f2SDouglas Gregor consumeToken(); 1531718292f2SDouglas Gregor } while (true); 1532718292f2SDouglas Gregor } 1533718292f2SDouglas Gregor 1534e7ab3669SDouglas Gregor /// \brief Parse a module-id. 1535e7ab3669SDouglas Gregor /// 1536e7ab3669SDouglas Gregor /// module-id: 1537e7ab3669SDouglas Gregor /// identifier 1538e7ab3669SDouglas Gregor /// identifier '.' module-id 1539e7ab3669SDouglas Gregor /// 1540e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise. 1541e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) { 1542e7ab3669SDouglas Gregor Id.clear(); 1543e7ab3669SDouglas Gregor do { 15443cd34c76SDaniel Jasper if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) { 1545e7ab3669SDouglas Gregor Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation())); 1546e7ab3669SDouglas Gregor consumeToken(); 1547e7ab3669SDouglas Gregor } else { 1548e7ab3669SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 1549e7ab3669SDouglas Gregor return true; 1550e7ab3669SDouglas Gregor } 1551e7ab3669SDouglas Gregor 1552e7ab3669SDouglas Gregor if (!Tok.is(MMToken::Period)) 1553e7ab3669SDouglas Gregor break; 1554e7ab3669SDouglas Gregor 1555e7ab3669SDouglas Gregor consumeToken(); 1556e7ab3669SDouglas Gregor } while (true); 1557e7ab3669SDouglas Gregor 1558e7ab3669SDouglas Gregor return false; 1559e7ab3669SDouglas Gregor } 1560e7ab3669SDouglas Gregor 1561a686e1b0SDouglas Gregor namespace { 1562a686e1b0SDouglas Gregor /// \brief Enumerates the known attributes. 1563a686e1b0SDouglas Gregor enum AttributeKind { 1564a686e1b0SDouglas Gregor /// \brief An unknown attribute. 1565a686e1b0SDouglas Gregor AT_unknown, 1566a686e1b0SDouglas Gregor /// \brief The 'system' attribute. 156735b13eceSDouglas Gregor AT_system, 156877944868SRichard Smith /// \brief The 'extern_c' attribute. 156977944868SRichard Smith AT_extern_c, 157035b13eceSDouglas Gregor /// \brief The 'exhaustive' attribute. 1571ed84df00SBruno Cardoso Lopes AT_exhaustive, 1572ed84df00SBruno Cardoso Lopes /// \brief The 'no_undeclared_includes' attribute. 1573ed84df00SBruno Cardoso Lopes AT_no_undeclared_includes 1574a686e1b0SDouglas Gregor }; 1575ab9db510SAlexander Kornienko } 1576a686e1b0SDouglas Gregor 1577718292f2SDouglas Gregor /// \brief Parse a module declaration. 1578718292f2SDouglas Gregor /// 1579718292f2SDouglas Gregor /// module-declaration: 158097292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 1581a686e1b0SDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt] 1582a686e1b0SDouglas Gregor /// { module-member* } 1583a686e1b0SDouglas Gregor /// 1584718292f2SDouglas Gregor /// module-member: 15851fb5c3a6SDouglas Gregor /// requires-declaration 1586718292f2SDouglas Gregor /// header-declaration 1587e7ab3669SDouglas Gregor /// submodule-declaration 15882b82c2a5SDouglas Gregor /// export-declaration 15896ddfca91SDouglas Gregor /// link-declaration 159073441091SDouglas Gregor /// 159173441091SDouglas Gregor /// submodule-declaration: 159273441091SDouglas Gregor /// module-declaration 159373441091SDouglas Gregor /// inferred-submodule-declaration 1594718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 1595755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 159697292843SDaniel Jasper Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword)); 159797292843SDaniel Jasper if (Tok.is(MMToken::ExternKeyword)) { 159897292843SDaniel Jasper parseExternModuleDecl(); 159997292843SDaniel Jasper return; 160097292843SDaniel Jasper } 160197292843SDaniel Jasper 1602f2161a70SDouglas Gregor // Parse 'explicit' or 'framework' keyword, if present. 1603e7ab3669SDouglas Gregor SourceLocation ExplicitLoc; 1604718292f2SDouglas Gregor bool Explicit = false; 1605f2161a70SDouglas Gregor bool Framework = false; 1606755b2055SDouglas Gregor 1607f2161a70SDouglas Gregor // Parse 'explicit' keyword, if present. 1608f2161a70SDouglas Gregor if (Tok.is(MMToken::ExplicitKeyword)) { 1609e7ab3669SDouglas Gregor ExplicitLoc = consumeToken(); 1610f2161a70SDouglas Gregor Explicit = true; 1611f2161a70SDouglas Gregor } 1612f2161a70SDouglas Gregor 1613f2161a70SDouglas Gregor // Parse 'framework' keyword, if present. 1614755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 1615755b2055SDouglas Gregor consumeToken(); 1616755b2055SDouglas Gregor Framework = true; 1617755b2055SDouglas Gregor } 1618718292f2SDouglas Gregor 1619718292f2SDouglas Gregor // Parse 'module' keyword. 1620718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 1621d6343c99SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 1622718292f2SDouglas Gregor consumeToken(); 1623718292f2SDouglas Gregor HadError = true; 1624718292f2SDouglas Gregor return; 1625718292f2SDouglas Gregor } 1626718292f2SDouglas Gregor consumeToken(); // 'module' keyword 1627718292f2SDouglas Gregor 162873441091SDouglas Gregor // If we have a wildcard for the module name, this is an inferred submodule. 162973441091SDouglas Gregor // Parse it. 163073441091SDouglas Gregor if (Tok.is(MMToken::Star)) 16319194a91dSDouglas Gregor return parseInferredModuleDecl(Framework, Explicit); 163273441091SDouglas Gregor 1633718292f2SDouglas Gregor // Parse the module name. 1634e7ab3669SDouglas Gregor ModuleId Id; 1635e7ab3669SDouglas Gregor if (parseModuleId(Id)) { 1636718292f2SDouglas Gregor HadError = true; 1637718292f2SDouglas Gregor return; 1638718292f2SDouglas Gregor } 1639e7ab3669SDouglas Gregor 1640e7ab3669SDouglas Gregor if (ActiveModule) { 1641e7ab3669SDouglas Gregor if (Id.size() > 1) { 1642e7ab3669SDouglas Gregor Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id) 1643e7ab3669SDouglas Gregor << SourceRange(Id.front().second, Id.back().second); 1644e7ab3669SDouglas Gregor 1645e7ab3669SDouglas Gregor HadError = true; 1646e7ab3669SDouglas Gregor return; 1647e7ab3669SDouglas Gregor } 1648e7ab3669SDouglas Gregor } else if (Id.size() == 1 && Explicit) { 1649e7ab3669SDouglas Gregor // Top-level modules can't be explicit. 1650e7ab3669SDouglas Gregor Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level); 1651e7ab3669SDouglas Gregor Explicit = false; 1652e7ab3669SDouglas Gregor ExplicitLoc = SourceLocation(); 1653e7ab3669SDouglas Gregor HadError = true; 1654e7ab3669SDouglas Gregor } 1655e7ab3669SDouglas Gregor 1656e7ab3669SDouglas Gregor Module *PreviousActiveModule = ActiveModule; 1657e7ab3669SDouglas Gregor if (Id.size() > 1) { 1658e7ab3669SDouglas Gregor // This module map defines a submodule. Go find the module of which it 1659e7ab3669SDouglas Gregor // is a submodule. 1660d2d442caSCraig Topper ActiveModule = nullptr; 16614b8a9e95SBen Langmuir const Module *TopLevelModule = nullptr; 1662e7ab3669SDouglas Gregor for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) { 1663e7ab3669SDouglas Gregor if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) { 16644b8a9e95SBen Langmuir if (I == 0) 16654b8a9e95SBen Langmuir TopLevelModule = Next; 1666e7ab3669SDouglas Gregor ActiveModule = Next; 1667e7ab3669SDouglas Gregor continue; 1668e7ab3669SDouglas Gregor } 1669e7ab3669SDouglas Gregor 1670e7ab3669SDouglas Gregor if (ActiveModule) { 1671e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified) 16725b5d21eaSRichard Smith << Id[I].first 16735b5d21eaSRichard Smith << ActiveModule->getTopLevelModule()->getFullModuleName(); 1674e7ab3669SDouglas Gregor } else { 1675e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_expected_module_name); 1676e7ab3669SDouglas Gregor } 1677e7ab3669SDouglas Gregor HadError = true; 1678e7ab3669SDouglas Gregor return; 1679e7ab3669SDouglas Gregor } 16804b8a9e95SBen Langmuir 16814b8a9e95SBen Langmuir if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) { 16824b8a9e95SBen Langmuir assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) && 16834b8a9e95SBen Langmuir "submodule defined in same file as 'module *' that allowed its " 16844b8a9e95SBen Langmuir "top-level module"); 16854b8a9e95SBen Langmuir Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile); 16864b8a9e95SBen Langmuir } 1687e7ab3669SDouglas Gregor } 1688e7ab3669SDouglas Gregor 1689e7ab3669SDouglas Gregor StringRef ModuleName = Id.back().first; 1690e7ab3669SDouglas Gregor SourceLocation ModuleNameLoc = Id.back().second; 1691718292f2SDouglas Gregor 1692a686e1b0SDouglas Gregor // Parse the optional attribute list. 16934442605fSBill Wendling Attributes Attrs; 16945d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 16955d29dee0SDavide Italiano return; 16965d29dee0SDavide Italiano 1697a686e1b0SDouglas Gregor 1698718292f2SDouglas Gregor // Parse the opening brace. 1699718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 1700718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 1701718292f2SDouglas Gregor << ModuleName; 1702718292f2SDouglas Gregor HadError = true; 1703718292f2SDouglas Gregor return; 1704718292f2SDouglas Gregor } 1705718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 1706718292f2SDouglas Gregor 1707718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 1708eb90e830SDouglas Gregor if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { 17094a3751ffSRichard Smith // We might see a (re)definition of a module that we already have a 17104a3751ffSRichard Smith // definition for in two cases: 17114a3751ffSRichard Smith // - If we loaded one definition from an AST file and we've just found a 17124a3751ffSRichard Smith // corresponding definition in a module map file, or 17134a3751ffSRichard Smith bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid(); 17144a3751ffSRichard Smith // - If we're building a (preprocessed) module and we've just loaded the 17154a3751ffSRichard Smith // module map file from which it was created. 17164a3751ffSRichard Smith bool ParsedAsMainInput = 17174a3751ffSRichard Smith Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap && 17184a3751ffSRichard Smith Map.LangOpts.CurrentModule == ModuleName && 17194a3751ffSRichard Smith SourceMgr.getDecomposedLoc(ModuleNameLoc).first != 17204a3751ffSRichard Smith SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first; 17214a3751ffSRichard Smith if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) { 1722fcc54a3bSDouglas Gregor // Skip the module definition. 1723fcc54a3bSDouglas Gregor skipUntil(MMToken::RBrace); 1724fcc54a3bSDouglas Gregor if (Tok.is(MMToken::RBrace)) 1725fcc54a3bSDouglas Gregor consumeToken(); 1726fcc54a3bSDouglas Gregor else { 1727fcc54a3bSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 1728fcc54a3bSDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 1729fcc54a3bSDouglas Gregor HadError = true; 1730fcc54a3bSDouglas Gregor } 1731fcc54a3bSDouglas Gregor return; 1732fcc54a3bSDouglas Gregor } 1733fcc54a3bSDouglas Gregor 1734718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 1735718292f2SDouglas Gregor << ModuleName; 1736eb90e830SDouglas Gregor Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition); 1737718292f2SDouglas Gregor 1738718292f2SDouglas Gregor // Skip the module definition. 1739718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 1740718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 1741718292f2SDouglas Gregor consumeToken(); 1742718292f2SDouglas Gregor 1743718292f2SDouglas Gregor HadError = true; 1744718292f2SDouglas Gregor return; 1745718292f2SDouglas Gregor } 1746718292f2SDouglas Gregor 1747718292f2SDouglas Gregor // Start defining this module. 17489d6448b1SBen Langmuir ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework, 17499d6448b1SBen Langmuir Explicit).first; 1750eb90e830SDouglas Gregor ActiveModule->DefinitionLoc = ModuleNameLoc; 1751963c5535SDouglas Gregor if (Attrs.IsSystem || IsSystem) 1752a686e1b0SDouglas Gregor ActiveModule->IsSystem = true; 175377944868SRichard Smith if (Attrs.IsExternC) 175477944868SRichard Smith ActiveModule->IsExternC = true; 1755ed84df00SBruno Cardoso Lopes if (Attrs.NoUndeclaredIncludes || 1756ed84df00SBruno Cardoso Lopes (!ActiveModule->Parent && ModuleName == "Darwin")) 1757ed84df00SBruno Cardoso Lopes ActiveModule->NoUndeclaredIncludes = true; 17583c1a41adSRichard Smith ActiveModule->Directory = Directory; 1759718292f2SDouglas Gregor 17604d867640SGraydon Hoare if (!ActiveModule->Parent) { 17614d867640SGraydon Hoare StringRef MapFileName(ModuleMapFile->getName()); 17624d867640SGraydon Hoare if (MapFileName.endswith("module.private.modulemap") || 17634d867640SGraydon Hoare MapFileName.endswith("module_private.map")) { 17644d867640SGraydon Hoare // Adding a top-level module from a private modulemap is likely a 17654d867640SGraydon Hoare // user error; we check to see if there's another top-level module 17664d867640SGraydon Hoare // defined in the non-private map in the same dir, and if so emit a 17674d867640SGraydon Hoare // warning. 17684d867640SGraydon Hoare for (auto E = Map.module_begin(); E != Map.module_end(); ++E) { 17694d867640SGraydon Hoare auto const *M = E->getValue(); 17704d867640SGraydon Hoare if (!M->Parent && 17714d867640SGraydon Hoare M->Directory == ActiveModule->Directory && 17724d867640SGraydon Hoare M->Name != ActiveModule->Name) { 17734d867640SGraydon Hoare Diags.Report(ActiveModule->DefinitionLoc, 17744d867640SGraydon Hoare diag::warn_mmap_mismatched_top_level_private) 17754d867640SGraydon Hoare << ActiveModule->Name << M->Name; 17764d867640SGraydon Hoare // The pattern we're defending against here is typically due to 17774d867640SGraydon Hoare // a module named FooPrivate which is supposed to be a submodule 17784d867640SGraydon Hoare // called Foo.Private. Emit a fixit in that case. 17794d867640SGraydon Hoare auto D = 17804d867640SGraydon Hoare Diags.Report(ActiveModule->DefinitionLoc, 17814d867640SGraydon Hoare diag::note_mmap_rename_top_level_private_as_submodule); 17824d867640SGraydon Hoare D << ActiveModule->Name << M->Name; 17834d867640SGraydon Hoare StringRef Bad(ActiveModule->Name); 17844d867640SGraydon Hoare if (Bad.consume_back("Private")) { 17854d867640SGraydon Hoare SmallString<128> Fixed = Bad; 17864d867640SGraydon Hoare Fixed.append(".Private"); 17874d867640SGraydon Hoare D << FixItHint::CreateReplacement(ActiveModule->DefinitionLoc, 17884d867640SGraydon Hoare Fixed); 17894d867640SGraydon Hoare } 17904d867640SGraydon Hoare break; 17914d867640SGraydon Hoare } 17924d867640SGraydon Hoare } 17934d867640SGraydon Hoare } 17944d867640SGraydon Hoare } 17954d867640SGraydon Hoare 1796718292f2SDouglas Gregor bool Done = false; 1797718292f2SDouglas Gregor do { 1798718292f2SDouglas Gregor switch (Tok.Kind) { 1799718292f2SDouglas Gregor case MMToken::EndOfFile: 1800718292f2SDouglas Gregor case MMToken::RBrace: 1801718292f2SDouglas Gregor Done = true; 1802718292f2SDouglas Gregor break; 1803718292f2SDouglas Gregor 180435b13eceSDouglas Gregor case MMToken::ConfigMacros: 180535b13eceSDouglas Gregor parseConfigMacros(); 180635b13eceSDouglas Gregor break; 180735b13eceSDouglas Gregor 1808fb912657SDouglas Gregor case MMToken::Conflict: 1809fb912657SDouglas Gregor parseConflict(); 1810fb912657SDouglas Gregor break; 1811fb912657SDouglas Gregor 1812718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 181397292843SDaniel Jasper case MMToken::ExternKeyword: 1814f2161a70SDouglas Gregor case MMToken::FrameworkKeyword: 1815718292f2SDouglas Gregor case MMToken::ModuleKeyword: 1816718292f2SDouglas Gregor parseModuleDecl(); 1817718292f2SDouglas Gregor break; 1818718292f2SDouglas Gregor 18192b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 18202b82c2a5SDouglas Gregor parseExportDecl(); 18212b82c2a5SDouglas Gregor break; 18222b82c2a5SDouglas Gregor 1823ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 1824ba7f2f71SDaniel Jasper parseUseDecl(); 1825ba7f2f71SDaniel Jasper break; 1826ba7f2f71SDaniel Jasper 18271fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 18281fb5c3a6SDouglas Gregor parseRequiresDecl(); 18291fb5c3a6SDouglas Gregor break; 18301fb5c3a6SDouglas Gregor 1831202210b3SRichard Smith case MMToken::TextualKeyword: 1832202210b3SRichard Smith parseHeaderDecl(MMToken::TextualKeyword, consumeToken()); 1833306d8920SRichard Smith break; 1834306d8920SRichard Smith 1835524e33e1SDouglas Gregor case MMToken::UmbrellaKeyword: { 1836524e33e1SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 1837524e33e1SDouglas Gregor if (Tok.is(MMToken::HeaderKeyword)) 1838b53e5483SLawrence Crowl parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc); 1839524e33e1SDouglas Gregor else 1840524e33e1SDouglas Gregor parseUmbrellaDirDecl(UmbrellaLoc); 1841718292f2SDouglas Gregor break; 1842524e33e1SDouglas Gregor } 1843718292f2SDouglas Gregor 1844202210b3SRichard Smith case MMToken::ExcludeKeyword: 1845202210b3SRichard Smith parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken()); 184659527666SDouglas Gregor break; 184759527666SDouglas Gregor 1848202210b3SRichard Smith case MMToken::PrivateKeyword: 1849202210b3SRichard Smith parseHeaderDecl(MMToken::PrivateKeyword, consumeToken()); 1850b53e5483SLawrence Crowl break; 1851b53e5483SLawrence Crowl 1852322f633cSDouglas Gregor case MMToken::HeaderKeyword: 1853202210b3SRichard Smith parseHeaderDecl(MMToken::HeaderKeyword, consumeToken()); 1854718292f2SDouglas Gregor break; 1855718292f2SDouglas Gregor 18566ddfca91SDouglas Gregor case MMToken::LinkKeyword: 18576ddfca91SDouglas Gregor parseLinkDecl(); 18586ddfca91SDouglas Gregor break; 18596ddfca91SDouglas Gregor 1860718292f2SDouglas Gregor default: 1861718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 1862718292f2SDouglas Gregor consumeToken(); 1863718292f2SDouglas Gregor break; 1864718292f2SDouglas Gregor } 1865718292f2SDouglas Gregor } while (!Done); 1866718292f2SDouglas Gregor 1867718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 1868718292f2SDouglas Gregor consumeToken(); 1869718292f2SDouglas Gregor else { 1870718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 1871718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 1872718292f2SDouglas Gregor HadError = true; 1873718292f2SDouglas Gregor } 1874718292f2SDouglas Gregor 187511dfe6feSDouglas Gregor // If the active module is a top-level framework, and there are no link 187611dfe6feSDouglas Gregor // libraries, automatically link against the framework. 187711dfe6feSDouglas Gregor if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() && 187811dfe6feSDouglas Gregor ActiveModule->LinkLibraries.empty()) { 187911dfe6feSDouglas Gregor inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager()); 188011dfe6feSDouglas Gregor } 188111dfe6feSDouglas Gregor 1882ec8c9752SBen Langmuir // If the module meets all requirements but is still unavailable, mark the 1883ec8c9752SBen Langmuir // whole tree as unavailable to prevent it from building. 1884ec8c9752SBen Langmuir if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement && 1885ec8c9752SBen Langmuir ActiveModule->Parent) { 1886ec8c9752SBen Langmuir ActiveModule->getTopLevelModule()->markUnavailable(); 1887ec8c9752SBen Langmuir ActiveModule->getTopLevelModule()->MissingHeaders.append( 1888ec8c9752SBen Langmuir ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end()); 1889ec8c9752SBen Langmuir } 1890ec8c9752SBen Langmuir 1891e7ab3669SDouglas Gregor // We're done parsing this module. Pop back to the previous module. 1892e7ab3669SDouglas Gregor ActiveModule = PreviousActiveModule; 1893718292f2SDouglas Gregor } 1894718292f2SDouglas Gregor 189597292843SDaniel Jasper /// \brief Parse an extern module declaration. 189697292843SDaniel Jasper /// 189797292843SDaniel Jasper /// extern module-declaration: 189897292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 189997292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() { 190097292843SDaniel Jasper assert(Tok.is(MMToken::ExternKeyword)); 1901ae6df27eSRichard Smith SourceLocation ExternLoc = consumeToken(); // 'extern' keyword 190297292843SDaniel Jasper 190397292843SDaniel Jasper // Parse 'module' keyword. 190497292843SDaniel Jasper if (!Tok.is(MMToken::ModuleKeyword)) { 190597292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 190697292843SDaniel Jasper consumeToken(); 190797292843SDaniel Jasper HadError = true; 190897292843SDaniel Jasper return; 190997292843SDaniel Jasper } 191097292843SDaniel Jasper consumeToken(); // 'module' keyword 191197292843SDaniel Jasper 191297292843SDaniel Jasper // Parse the module name. 191397292843SDaniel Jasper ModuleId Id; 191497292843SDaniel Jasper if (parseModuleId(Id)) { 191597292843SDaniel Jasper HadError = true; 191697292843SDaniel Jasper return; 191797292843SDaniel Jasper } 191897292843SDaniel Jasper 191997292843SDaniel Jasper // Parse the referenced module map file name. 192097292843SDaniel Jasper if (!Tok.is(MMToken::StringLiteral)) { 192197292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file); 192297292843SDaniel Jasper HadError = true; 192397292843SDaniel Jasper return; 192497292843SDaniel Jasper } 192597292843SDaniel Jasper std::string FileName = Tok.getString(); 192697292843SDaniel Jasper consumeToken(); // filename 192797292843SDaniel Jasper 192897292843SDaniel Jasper StringRef FileNameRef = FileName; 192997292843SDaniel Jasper SmallString<128> ModuleMapFileName; 193097292843SDaniel Jasper if (llvm::sys::path::is_relative(FileNameRef)) { 193197292843SDaniel Jasper ModuleMapFileName += Directory->getName(); 193297292843SDaniel Jasper llvm::sys::path::append(ModuleMapFileName, FileName); 193392e1b62dSYaron Keren FileNameRef = ModuleMapFileName; 193497292843SDaniel Jasper } 193597292843SDaniel Jasper if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef)) 19369acb99e3SRichard Smith Map.parseModuleMapFile( 19379acb99e3SRichard Smith File, /*IsSystem=*/false, 19389acb99e3SRichard Smith Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd 19399acb99e3SRichard Smith ? Directory 19408128f332SRichard Smith : File->getDir(), 19418128f332SRichard Smith FileID(), nullptr, ExternLoc); 194297292843SDaniel Jasper } 194397292843SDaniel Jasper 19447ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M. 19457ff29148SBen Langmuir /// 19467ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system 19477ff29148SBen Langmuir /// module map files: 19487ff29148SBen Langmuir /// 19497ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which 19507ff29148SBen Langmuir /// should really be mapped to 'textual' now that we have this feature. We 19517ff29148SBen Langmuir /// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to 19527ff29148SBen Langmuir /// true. Later, this bit will be used to map all the headers inside this 19537ff29148SBen Langmuir /// module to 'textual'. 19547ff29148SBen Langmuir /// 19557ff29148SBen Langmuir /// This affects Darwin.C.excluded (for assert.h) and Tcl.Private. 19567ff29148SBen Langmuir /// 19577ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement 19587ff29148SBen Langmuir /// was never correct and causes issues now that we check it, so drop it. 19597ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature, 19607ff29148SBen Langmuir bool &IsRequiresExcludedHack) { 19618013e81dSBenjamin Kramer if (Feature == "excluded" && 19628013e81dSBenjamin Kramer (M->fullModuleNameIs({"Darwin", "C", "excluded"}) || 19638013e81dSBenjamin Kramer M->fullModuleNameIs({"Tcl", "Private"}))) { 19647ff29148SBen Langmuir IsRequiresExcludedHack = true; 19657ff29148SBen Langmuir return false; 19668013e81dSBenjamin Kramer } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) { 19677ff29148SBen Langmuir return false; 19687ff29148SBen Langmuir } 19697ff29148SBen Langmuir 19707ff29148SBen Langmuir return true; 19717ff29148SBen Langmuir } 19727ff29148SBen Langmuir 19731fb5c3a6SDouglas Gregor /// \brief Parse a requires declaration. 19741fb5c3a6SDouglas Gregor /// 19751fb5c3a6SDouglas Gregor /// requires-declaration: 19761fb5c3a6SDouglas Gregor /// 'requires' feature-list 19771fb5c3a6SDouglas Gregor /// 19781fb5c3a6SDouglas Gregor /// feature-list: 1979a3feee2aSRichard Smith /// feature ',' feature-list 1980a3feee2aSRichard Smith /// feature 1981a3feee2aSRichard Smith /// 1982a3feee2aSRichard Smith /// feature: 1983a3feee2aSRichard Smith /// '!'[opt] identifier 19841fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() { 19851fb5c3a6SDouglas Gregor assert(Tok.is(MMToken::RequiresKeyword)); 19861fb5c3a6SDouglas Gregor 19871fb5c3a6SDouglas Gregor // Parse 'requires' keyword. 19881fb5c3a6SDouglas Gregor consumeToken(); 19891fb5c3a6SDouglas Gregor 19901fb5c3a6SDouglas Gregor // Parse the feature-list. 19911fb5c3a6SDouglas Gregor do { 1992a3feee2aSRichard Smith bool RequiredState = true; 1993a3feee2aSRichard Smith if (Tok.is(MMToken::Exclaim)) { 1994a3feee2aSRichard Smith RequiredState = false; 1995a3feee2aSRichard Smith consumeToken(); 1996a3feee2aSRichard Smith } 1997a3feee2aSRichard Smith 19981fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 19991fb5c3a6SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature); 20001fb5c3a6SDouglas Gregor HadError = true; 20011fb5c3a6SDouglas Gregor return; 20021fb5c3a6SDouglas Gregor } 20031fb5c3a6SDouglas Gregor 20041fb5c3a6SDouglas Gregor // Consume the feature name. 20051fb5c3a6SDouglas Gregor std::string Feature = Tok.getString(); 20061fb5c3a6SDouglas Gregor consumeToken(); 20071fb5c3a6SDouglas Gregor 20087ff29148SBen Langmuir bool IsRequiresExcludedHack = false; 20097ff29148SBen Langmuir bool ShouldAddRequirement = 20107ff29148SBen Langmuir shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack); 20117ff29148SBen Langmuir 20127ff29148SBen Langmuir if (IsRequiresExcludedHack) 20137ff29148SBen Langmuir UsesRequiresExcludedHack.insert(ActiveModule); 20147ff29148SBen Langmuir 20157ff29148SBen Langmuir if (ShouldAddRequirement) { 20161fb5c3a6SDouglas Gregor // Add this feature. 20177ff29148SBen Langmuir ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts, 20187ff29148SBen Langmuir *Map.Target); 20197ff29148SBen Langmuir } 20201fb5c3a6SDouglas Gregor 20211fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Comma)) 20221fb5c3a6SDouglas Gregor break; 20231fb5c3a6SDouglas Gregor 20241fb5c3a6SDouglas Gregor // Consume the comma. 20251fb5c3a6SDouglas Gregor consumeToken(); 20261fb5c3a6SDouglas Gregor } while (true); 20271fb5c3a6SDouglas Gregor } 20281fb5c3a6SDouglas Gregor 2029718292f2SDouglas Gregor /// \brief Parse a header declaration. 2030718292f2SDouglas Gregor /// 2031718292f2SDouglas Gregor /// header-declaration: 2032306d8920SRichard Smith /// 'textual'[opt] 'header' string-literal 2033202210b3SRichard Smith /// 'private' 'textual'[opt] 'header' string-literal 2034202210b3SRichard Smith /// 'exclude' 'header' string-literal 2035202210b3SRichard Smith /// 'umbrella' 'header' string-literal 2036306d8920SRichard Smith /// 2037306d8920SRichard Smith /// FIXME: Support 'private textual header'. 2038b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, 2039b53e5483SLawrence Crowl SourceLocation LeadingLoc) { 2040202210b3SRichard Smith // We've already consumed the first token. 2041202210b3SRichard Smith ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader; 2042202210b3SRichard Smith if (LeadingToken == MMToken::PrivateKeyword) { 2043202210b3SRichard Smith Role = ModuleMap::PrivateHeader; 2044202210b3SRichard Smith // 'private' may optionally be followed by 'textual'. 2045202210b3SRichard Smith if (Tok.is(MMToken::TextualKeyword)) { 2046202210b3SRichard Smith LeadingToken = Tok.Kind; 20471871ed3dSBenjamin Kramer consumeToken(); 2048202210b3SRichard Smith } 2049202210b3SRichard Smith } 20507ff29148SBen Langmuir 2051202210b3SRichard Smith if (LeadingToken == MMToken::TextualKeyword) 2052202210b3SRichard Smith Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 2053202210b3SRichard Smith 20547ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 20557ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 20567ff29148SBen Langmuir // Module::UsesRequiresExcludedHack). 20577ff29148SBen Langmuir Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 20587ff29148SBen Langmuir } 20597ff29148SBen Langmuir 2060202210b3SRichard Smith if (LeadingToken != MMToken::HeaderKeyword) { 2061202210b3SRichard Smith if (!Tok.is(MMToken::HeaderKeyword)) { 2062202210b3SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2063202210b3SRichard Smith << (LeadingToken == MMToken::PrivateKeyword ? "private" : 2064202210b3SRichard Smith LeadingToken == MMToken::ExcludeKeyword ? "exclude" : 2065202210b3SRichard Smith LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella"); 2066202210b3SRichard Smith return; 2067202210b3SRichard Smith } 2068202210b3SRichard Smith consumeToken(); 2069202210b3SRichard Smith } 2070718292f2SDouglas Gregor 2071718292f2SDouglas Gregor // Parse the header name. 2072718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2073718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2074718292f2SDouglas Gregor << "header"; 2075718292f2SDouglas Gregor HadError = true; 2076718292f2SDouglas Gregor return; 2077718292f2SDouglas Gregor } 20783c1a41adSRichard Smith Module::UnresolvedHeaderDirective Header; 20790761a8a0SDaniel Jasper Header.FileName = Tok.getString(); 20800761a8a0SDaniel Jasper Header.FileNameLoc = consumeToken(); 20811d60987fSRichard Smith Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword; 2082040e1266SRichard Smith Header.Kind = 2083040e1266SRichard Smith (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded 2084040e1266SRichard Smith : Map.headerRoleToKind(Role)); 2085718292f2SDouglas Gregor 2086524e33e1SDouglas Gregor // Check whether we already have an umbrella. 20871d60987fSRichard Smith if (Header.IsUmbrella && ActiveModule->Umbrella) { 20880761a8a0SDaniel Jasper Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) 2089524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2090322f633cSDouglas Gregor HadError = true; 2091322f633cSDouglas Gregor return; 2092322f633cSDouglas Gregor } 2093322f633cSDouglas Gregor 2094040e1266SRichard Smith // If we were given stat information, parse it so we can skip looking for 2095040e1266SRichard Smith // the file. 2096040e1266SRichard Smith if (Tok.is(MMToken::LBrace)) { 2097040e1266SRichard Smith SourceLocation LBraceLoc = consumeToken(); 20983ec6663bSDouglas Gregor 2099040e1266SRichard Smith while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) { 2100040e1266SRichard Smith enum Attribute { Size, ModTime, Unknown }; 2101040e1266SRichard Smith StringRef Str = Tok.getString(); 2102040e1266SRichard Smith SourceLocation Loc = consumeToken(); 2103040e1266SRichard Smith switch (llvm::StringSwitch<Attribute>(Str) 2104040e1266SRichard Smith .Case("size", Size) 2105040e1266SRichard Smith .Case("mtime", ModTime) 2106040e1266SRichard Smith .Default(Unknown)) { 2107040e1266SRichard Smith case Size: 2108040e1266SRichard Smith if (Header.Size) 2109040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2110040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2111040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2112040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2113040e1266SRichard Smith skipUntil(MMToken::RBrace); 2114040e1266SRichard Smith break; 2115040e1266SRichard Smith } 2116040e1266SRichard Smith Header.Size = Tok.getInteger(); 2117040e1266SRichard Smith consumeToken(); 2118040e1266SRichard Smith break; 2119040e1266SRichard Smith 2120040e1266SRichard Smith case ModTime: 2121040e1266SRichard Smith if (Header.ModTime) 2122040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2123040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2124040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2125040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2126040e1266SRichard Smith skipUntil(MMToken::RBrace); 2127040e1266SRichard Smith break; 2128040e1266SRichard Smith } 2129040e1266SRichard Smith Header.ModTime = Tok.getInteger(); 2130040e1266SRichard Smith consumeToken(); 2131040e1266SRichard Smith break; 2132040e1266SRichard Smith 2133040e1266SRichard Smith case Unknown: 2134040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_expected_header_attribute); 2135040e1266SRichard Smith skipUntil(MMToken::RBrace); 2136040e1266SRichard Smith break; 2137040e1266SRichard Smith } 21383ec6663bSDouglas Gregor } 21395257fc63SDouglas Gregor 2140040e1266SRichard Smith if (Tok.is(MMToken::RBrace)) 2141040e1266SRichard Smith consumeToken(); 2142040e1266SRichard Smith else { 2143040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 2144040e1266SRichard Smith Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 2145322f633cSDouglas Gregor HadError = true; 2146322f633cSDouglas Gregor } 21470101b540SHans Wennborg } 214825d50758SRichard Smith 2149040e1266SRichard Smith Map.addUnresolvedHeader(ActiveModule, std::move(Header)); 2150718292f2SDouglas Gregor } 2151718292f2SDouglas Gregor 215241f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A, 215341f81994SBen Langmuir const Module::Header *B) { 215441f81994SBen Langmuir return A->NameAsWritten.compare(B->NameAsWritten); 215541f81994SBen Langmuir } 215641f81994SBen Langmuir 2157524e33e1SDouglas Gregor /// \brief Parse an umbrella directory declaration. 2158524e33e1SDouglas Gregor /// 2159524e33e1SDouglas Gregor /// umbrella-dir-declaration: 2160524e33e1SDouglas Gregor /// umbrella string-literal 2161524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { 2162524e33e1SDouglas Gregor // Parse the directory name. 2163524e33e1SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2164524e33e1SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2165524e33e1SDouglas Gregor << "umbrella"; 2166524e33e1SDouglas Gregor HadError = true; 2167524e33e1SDouglas Gregor return; 2168524e33e1SDouglas Gregor } 2169524e33e1SDouglas Gregor 2170524e33e1SDouglas Gregor std::string DirName = Tok.getString(); 2171524e33e1SDouglas Gregor SourceLocation DirNameLoc = consumeToken(); 2172524e33e1SDouglas Gregor 2173524e33e1SDouglas Gregor // Check whether we already have an umbrella. 2174524e33e1SDouglas Gregor if (ActiveModule->Umbrella) { 2175524e33e1SDouglas Gregor Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash) 2176524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2177524e33e1SDouglas Gregor HadError = true; 2178524e33e1SDouglas Gregor return; 2179524e33e1SDouglas Gregor } 2180524e33e1SDouglas Gregor 2181524e33e1SDouglas Gregor // Look for this file. 2182d2d442caSCraig Topper const DirectoryEntry *Dir = nullptr; 2183524e33e1SDouglas Gregor if (llvm::sys::path::is_absolute(DirName)) 2184524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(DirName); 2185524e33e1SDouglas Gregor else { 21862c1dd271SDylan Noblesmith SmallString<128> PathName; 2187524e33e1SDouglas Gregor PathName = Directory->getName(); 2188524e33e1SDouglas Gregor llvm::sys::path::append(PathName, DirName); 2189524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(PathName); 2190524e33e1SDouglas Gregor } 2191524e33e1SDouglas Gregor 2192524e33e1SDouglas Gregor if (!Dir) { 2193a0320b97SVassil Vassilev Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found) 2194524e33e1SDouglas Gregor << DirName; 2195524e33e1SDouglas Gregor return; 2196524e33e1SDouglas Gregor } 2197524e33e1SDouglas Gregor 21987ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 21997ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 22007ff29148SBen Langmuir // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the 22017ff29148SBen Langmuir // directory is relatively expensive, in practice this only applies to the 22027ff29148SBen Langmuir // uncommonly used Tcl module on Darwin platforms. 22037ff29148SBen Langmuir std::error_code EC; 22047ff29148SBen Langmuir SmallVector<Module::Header, 6> Headers; 2205b171a59bSBruno Cardoso Lopes vfs::FileSystem &FS = *SourceMgr.getFileManager().getVirtualFileSystem(); 2206b171a59bSBruno Cardoso Lopes for (vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E; 22077ff29148SBen Langmuir I != E && !EC; I.increment(EC)) { 2208b171a59bSBruno Cardoso Lopes if (const FileEntry *FE = 2209b171a59bSBruno Cardoso Lopes SourceMgr.getFileManager().getFile(I->getName())) { 22107ff29148SBen Langmuir 2211b171a59bSBruno Cardoso Lopes Module::Header Header = {I->getName(), FE}; 22127ff29148SBen Langmuir Headers.push_back(std::move(Header)); 22137ff29148SBen Langmuir } 22147ff29148SBen Langmuir } 22157ff29148SBen Langmuir 22167ff29148SBen Langmuir // Sort header paths so that the pcm doesn't depend on iteration order. 221741f81994SBen Langmuir llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders); 221841f81994SBen Langmuir 22197ff29148SBen Langmuir for (auto &Header : Headers) 22207ff29148SBen Langmuir Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader); 22217ff29148SBen Langmuir return; 22227ff29148SBen Langmuir } 22237ff29148SBen Langmuir 2224524e33e1SDouglas Gregor if (Module *OwningModule = Map.UmbrellaDirs[Dir]) { 2225524e33e1SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 2226524e33e1SDouglas Gregor << OwningModule->getFullModuleName(); 2227524e33e1SDouglas Gregor HadError = true; 2228524e33e1SDouglas Gregor return; 2229524e33e1SDouglas Gregor } 2230524e33e1SDouglas Gregor 2231524e33e1SDouglas Gregor // Record this umbrella directory. 22322b63d15fSRichard Smith Map.setUmbrellaDir(ActiveModule, Dir, DirName); 2233524e33e1SDouglas Gregor } 2234524e33e1SDouglas Gregor 22352b82c2a5SDouglas Gregor /// \brief Parse a module export declaration. 22362b82c2a5SDouglas Gregor /// 22372b82c2a5SDouglas Gregor /// export-declaration: 22382b82c2a5SDouglas Gregor /// 'export' wildcard-module-id 22392b82c2a5SDouglas Gregor /// 22402b82c2a5SDouglas Gregor /// wildcard-module-id: 22412b82c2a5SDouglas Gregor /// identifier 22422b82c2a5SDouglas Gregor /// '*' 22432b82c2a5SDouglas Gregor /// identifier '.' wildcard-module-id 22442b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() { 22452b82c2a5SDouglas Gregor assert(Tok.is(MMToken::ExportKeyword)); 22462b82c2a5SDouglas Gregor SourceLocation ExportLoc = consumeToken(); 22472b82c2a5SDouglas Gregor 22482b82c2a5SDouglas Gregor // Parse the module-id with an optional wildcard at the end. 22492b82c2a5SDouglas Gregor ModuleId ParsedModuleId; 22502b82c2a5SDouglas Gregor bool Wildcard = false; 22512b82c2a5SDouglas Gregor do { 2252306d8920SRichard Smith // FIXME: Support string-literal module names here. 22532b82c2a5SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 22542b82c2a5SDouglas Gregor ParsedModuleId.push_back(std::make_pair(Tok.getString(), 22552b82c2a5SDouglas Gregor Tok.getLocation())); 22562b82c2a5SDouglas Gregor consumeToken(); 22572b82c2a5SDouglas Gregor 22582b82c2a5SDouglas Gregor if (Tok.is(MMToken::Period)) { 22592b82c2a5SDouglas Gregor consumeToken(); 22602b82c2a5SDouglas Gregor continue; 22612b82c2a5SDouglas Gregor } 22622b82c2a5SDouglas Gregor 22632b82c2a5SDouglas Gregor break; 22642b82c2a5SDouglas Gregor } 22652b82c2a5SDouglas Gregor 22662b82c2a5SDouglas Gregor if(Tok.is(MMToken::Star)) { 22672b82c2a5SDouglas Gregor Wildcard = true; 2268f5eedd05SDouglas Gregor consumeToken(); 22692b82c2a5SDouglas Gregor break; 22702b82c2a5SDouglas Gregor } 22712b82c2a5SDouglas Gregor 2272ba7f2f71SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_module_id); 22732b82c2a5SDouglas Gregor HadError = true; 22742b82c2a5SDouglas Gregor return; 22752b82c2a5SDouglas Gregor } while (true); 22762b82c2a5SDouglas Gregor 22772b82c2a5SDouglas Gregor Module::UnresolvedExportDecl Unresolved = { 22782b82c2a5SDouglas Gregor ExportLoc, ParsedModuleId, Wildcard 22792b82c2a5SDouglas Gregor }; 22802b82c2a5SDouglas Gregor ActiveModule->UnresolvedExports.push_back(Unresolved); 22812b82c2a5SDouglas Gregor } 22822b82c2a5SDouglas Gregor 22838f4d3ff1SRichard Smith /// \brief Parse a module use declaration. 2284ba7f2f71SDaniel Jasper /// 22858f4d3ff1SRichard Smith /// use-declaration: 22868f4d3ff1SRichard Smith /// 'use' wildcard-module-id 2287ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() { 2288ba7f2f71SDaniel Jasper assert(Tok.is(MMToken::UseKeyword)); 22898f4d3ff1SRichard Smith auto KWLoc = consumeToken(); 2290ba7f2f71SDaniel Jasper // Parse the module-id. 2291ba7f2f71SDaniel Jasper ModuleId ParsedModuleId; 22923cd34c76SDaniel Jasper parseModuleId(ParsedModuleId); 2293ba7f2f71SDaniel Jasper 22948f4d3ff1SRichard Smith if (ActiveModule->Parent) 22958f4d3ff1SRichard Smith Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule); 22968f4d3ff1SRichard Smith else 2297ba7f2f71SDaniel Jasper ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId); 2298ba7f2f71SDaniel Jasper } 2299ba7f2f71SDaniel Jasper 23006ddfca91SDouglas Gregor /// \brief Parse a link declaration. 23016ddfca91SDouglas Gregor /// 23026ddfca91SDouglas Gregor /// module-declaration: 23036ddfca91SDouglas Gregor /// 'link' 'framework'[opt] string-literal 23046ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() { 23056ddfca91SDouglas Gregor assert(Tok.is(MMToken::LinkKeyword)); 23066ddfca91SDouglas Gregor SourceLocation LinkLoc = consumeToken(); 23076ddfca91SDouglas Gregor 23086ddfca91SDouglas Gregor // Parse the optional 'framework' keyword. 23096ddfca91SDouglas Gregor bool IsFramework = false; 23106ddfca91SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 23116ddfca91SDouglas Gregor consumeToken(); 23126ddfca91SDouglas Gregor IsFramework = true; 23136ddfca91SDouglas Gregor } 23146ddfca91SDouglas Gregor 23156ddfca91SDouglas Gregor // Parse the library name 23166ddfca91SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 23176ddfca91SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name) 23186ddfca91SDouglas Gregor << IsFramework << SourceRange(LinkLoc); 23196ddfca91SDouglas Gregor HadError = true; 23206ddfca91SDouglas Gregor return; 23216ddfca91SDouglas Gregor } 23226ddfca91SDouglas Gregor 23236ddfca91SDouglas Gregor std::string LibraryName = Tok.getString(); 23246ddfca91SDouglas Gregor consumeToken(); 23256ddfca91SDouglas Gregor ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName, 23266ddfca91SDouglas Gregor IsFramework)); 23276ddfca91SDouglas Gregor } 23286ddfca91SDouglas Gregor 232935b13eceSDouglas Gregor /// \brief Parse a configuration macro declaration. 233035b13eceSDouglas Gregor /// 233135b13eceSDouglas Gregor /// module-declaration: 233235b13eceSDouglas Gregor /// 'config_macros' attributes[opt] config-macro-list? 233335b13eceSDouglas Gregor /// 233435b13eceSDouglas Gregor /// config-macro-list: 233535b13eceSDouglas Gregor /// identifier (',' identifier)? 233635b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() { 233735b13eceSDouglas Gregor assert(Tok.is(MMToken::ConfigMacros)); 233835b13eceSDouglas Gregor SourceLocation ConfigMacrosLoc = consumeToken(); 233935b13eceSDouglas Gregor 234035b13eceSDouglas Gregor // Only top-level modules can have configuration macros. 234135b13eceSDouglas Gregor if (ActiveModule->Parent) { 234235b13eceSDouglas Gregor Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule); 234335b13eceSDouglas Gregor } 234435b13eceSDouglas Gregor 234535b13eceSDouglas Gregor // Parse the optional attributes. 234635b13eceSDouglas Gregor Attributes Attrs; 23475d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 23485d29dee0SDavide Italiano return; 23495d29dee0SDavide Italiano 235035b13eceSDouglas Gregor if (Attrs.IsExhaustive && !ActiveModule->Parent) { 235135b13eceSDouglas Gregor ActiveModule->ConfigMacrosExhaustive = true; 235235b13eceSDouglas Gregor } 235335b13eceSDouglas Gregor 235435b13eceSDouglas Gregor // If we don't have an identifier, we're done. 2355306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 235635b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) 235735b13eceSDouglas Gregor return; 235835b13eceSDouglas Gregor 235935b13eceSDouglas Gregor // Consume the first identifier. 236035b13eceSDouglas Gregor if (!ActiveModule->Parent) { 236135b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 236235b13eceSDouglas Gregor } 236335b13eceSDouglas Gregor consumeToken(); 236435b13eceSDouglas Gregor 236535b13eceSDouglas Gregor do { 236635b13eceSDouglas Gregor // If there's a comma, consume it. 236735b13eceSDouglas Gregor if (!Tok.is(MMToken::Comma)) 236835b13eceSDouglas Gregor break; 236935b13eceSDouglas Gregor consumeToken(); 237035b13eceSDouglas Gregor 237135b13eceSDouglas Gregor // We expect to see a macro name here. 2372306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 237335b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 237435b13eceSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro); 237535b13eceSDouglas Gregor break; 237635b13eceSDouglas Gregor } 237735b13eceSDouglas Gregor 237835b13eceSDouglas Gregor // Consume the macro name. 237935b13eceSDouglas Gregor if (!ActiveModule->Parent) { 238035b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 238135b13eceSDouglas Gregor } 238235b13eceSDouglas Gregor consumeToken(); 238335b13eceSDouglas Gregor } while (true); 238435b13eceSDouglas Gregor } 238535b13eceSDouglas Gregor 2386fb912657SDouglas Gregor /// \brief Format a module-id into a string. 2387fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) { 2388fb912657SDouglas Gregor std::string result; 2389fb912657SDouglas Gregor { 2390fb912657SDouglas Gregor llvm::raw_string_ostream OS(result); 2391fb912657SDouglas Gregor 2392fb912657SDouglas Gregor for (unsigned I = 0, N = Id.size(); I != N; ++I) { 2393fb912657SDouglas Gregor if (I) 2394fb912657SDouglas Gregor OS << "."; 2395fb912657SDouglas Gregor OS << Id[I].first; 2396fb912657SDouglas Gregor } 2397fb912657SDouglas Gregor } 2398fb912657SDouglas Gregor 2399fb912657SDouglas Gregor return result; 2400fb912657SDouglas Gregor } 2401fb912657SDouglas Gregor 2402fb912657SDouglas Gregor /// \brief Parse a conflict declaration. 2403fb912657SDouglas Gregor /// 2404fb912657SDouglas Gregor /// module-declaration: 2405fb912657SDouglas Gregor /// 'conflict' module-id ',' string-literal 2406fb912657SDouglas Gregor void ModuleMapParser::parseConflict() { 2407fb912657SDouglas Gregor assert(Tok.is(MMToken::Conflict)); 2408fb912657SDouglas Gregor SourceLocation ConflictLoc = consumeToken(); 2409fb912657SDouglas Gregor Module::UnresolvedConflict Conflict; 2410fb912657SDouglas Gregor 2411fb912657SDouglas Gregor // Parse the module-id. 2412fb912657SDouglas Gregor if (parseModuleId(Conflict.Id)) 2413fb912657SDouglas Gregor return; 2414fb912657SDouglas Gregor 2415fb912657SDouglas Gregor // Parse the ','. 2416fb912657SDouglas Gregor if (!Tok.is(MMToken::Comma)) { 2417fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma) 2418fb912657SDouglas Gregor << SourceRange(ConflictLoc); 2419fb912657SDouglas Gregor return; 2420fb912657SDouglas Gregor } 2421fb912657SDouglas Gregor consumeToken(); 2422fb912657SDouglas Gregor 2423fb912657SDouglas Gregor // Parse the message. 2424fb912657SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2425fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message) 2426fb912657SDouglas Gregor << formatModuleId(Conflict.Id); 2427fb912657SDouglas Gregor return; 2428fb912657SDouglas Gregor } 2429fb912657SDouglas Gregor Conflict.Message = Tok.getString().str(); 2430fb912657SDouglas Gregor consumeToken(); 2431fb912657SDouglas Gregor 2432fb912657SDouglas Gregor // Add this unresolved conflict. 2433fb912657SDouglas Gregor ActiveModule->UnresolvedConflicts.push_back(Conflict); 2434fb912657SDouglas Gregor } 2435fb912657SDouglas Gregor 24366ddfca91SDouglas Gregor /// \brief Parse an inferred module declaration (wildcard modules). 24379194a91dSDouglas Gregor /// 24389194a91dSDouglas Gregor /// module-declaration: 24399194a91dSDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt] 24409194a91dSDouglas Gregor /// { inferred-module-member* } 24419194a91dSDouglas Gregor /// 24429194a91dSDouglas Gregor /// inferred-module-member: 24439194a91dSDouglas Gregor /// 'export' '*' 24449194a91dSDouglas Gregor /// 'exclude' identifier 24459194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { 244673441091SDouglas Gregor assert(Tok.is(MMToken::Star)); 244773441091SDouglas Gregor SourceLocation StarLoc = consumeToken(); 244873441091SDouglas Gregor bool Failed = false; 244973441091SDouglas Gregor 245073441091SDouglas Gregor // Inferred modules must be submodules. 24519194a91dSDouglas Gregor if (!ActiveModule && !Framework) { 245273441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule); 245373441091SDouglas Gregor Failed = true; 245473441091SDouglas Gregor } 245573441091SDouglas Gregor 24569194a91dSDouglas Gregor if (ActiveModule) { 2457524e33e1SDouglas Gregor // Inferred modules must have umbrella directories. 24584898cde4SBen Langmuir if (!Failed && ActiveModule->IsAvailable && 24594898cde4SBen Langmuir !ActiveModule->getUmbrellaDir()) { 246073441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); 246173441091SDouglas Gregor Failed = true; 246273441091SDouglas Gregor } 246373441091SDouglas Gregor 246473441091SDouglas Gregor // Check for redefinition of an inferred module. 2465dd005f69SDouglas Gregor if (!Failed && ActiveModule->InferSubmodules) { 246673441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_redef); 2467dd005f69SDouglas Gregor if (ActiveModule->InferredSubmoduleLoc.isValid()) 2468dd005f69SDouglas Gregor Diags.Report(ActiveModule->InferredSubmoduleLoc, 246973441091SDouglas Gregor diag::note_mmap_prev_definition); 247073441091SDouglas Gregor Failed = true; 247173441091SDouglas Gregor } 247273441091SDouglas Gregor 24739194a91dSDouglas Gregor // Check for the 'framework' keyword, which is not permitted here. 24749194a91dSDouglas Gregor if (Framework) { 24759194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule); 24769194a91dSDouglas Gregor Framework = false; 24779194a91dSDouglas Gregor } 24789194a91dSDouglas Gregor } else if (Explicit) { 24799194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework); 24809194a91dSDouglas Gregor Explicit = false; 24819194a91dSDouglas Gregor } 24829194a91dSDouglas Gregor 248373441091SDouglas Gregor // If there were any problems with this inferred submodule, skip its body. 248473441091SDouglas Gregor if (Failed) { 248573441091SDouglas Gregor if (Tok.is(MMToken::LBrace)) { 248673441091SDouglas Gregor consumeToken(); 248773441091SDouglas Gregor skipUntil(MMToken::RBrace); 248873441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 248973441091SDouglas Gregor consumeToken(); 249073441091SDouglas Gregor } 249173441091SDouglas Gregor HadError = true; 249273441091SDouglas Gregor return; 249373441091SDouglas Gregor } 249473441091SDouglas Gregor 24959194a91dSDouglas Gregor // Parse optional attributes. 24964442605fSBill Wendling Attributes Attrs; 24975d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 24985d29dee0SDavide Italiano return; 24999194a91dSDouglas Gregor 25009194a91dSDouglas Gregor if (ActiveModule) { 250173441091SDouglas Gregor // Note that we have an inferred submodule. 2502dd005f69SDouglas Gregor ActiveModule->InferSubmodules = true; 2503dd005f69SDouglas Gregor ActiveModule->InferredSubmoduleLoc = StarLoc; 2504dd005f69SDouglas Gregor ActiveModule->InferExplicitSubmodules = Explicit; 25059194a91dSDouglas Gregor } else { 25069194a91dSDouglas Gregor // We'll be inferring framework modules for this directory. 25079194a91dSDouglas Gregor Map.InferredDirectories[Directory].InferModules = true; 2508c1d88ea5SBen Langmuir Map.InferredDirectories[Directory].Attrs = Attrs; 2509beee15e7SBen Langmuir Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile; 2510131daca0SRichard Smith // FIXME: Handle the 'framework' keyword. 25119194a91dSDouglas Gregor } 251273441091SDouglas Gregor 251373441091SDouglas Gregor // Parse the opening brace. 251473441091SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 251573441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard); 251673441091SDouglas Gregor HadError = true; 251773441091SDouglas Gregor return; 251873441091SDouglas Gregor } 251973441091SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 252073441091SDouglas Gregor 252173441091SDouglas Gregor // Parse the body of the inferred submodule. 252273441091SDouglas Gregor bool Done = false; 252373441091SDouglas Gregor do { 252473441091SDouglas Gregor switch (Tok.Kind) { 252573441091SDouglas Gregor case MMToken::EndOfFile: 252673441091SDouglas Gregor case MMToken::RBrace: 252773441091SDouglas Gregor Done = true; 252873441091SDouglas Gregor break; 252973441091SDouglas Gregor 25309194a91dSDouglas Gregor case MMToken::ExcludeKeyword: { 25319194a91dSDouglas Gregor if (ActiveModule) { 25329194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2533d2d442caSCraig Topper << (ActiveModule != nullptr); 25349194a91dSDouglas Gregor consumeToken(); 25359194a91dSDouglas Gregor break; 25369194a91dSDouglas Gregor } 25379194a91dSDouglas Gregor 25389194a91dSDouglas Gregor consumeToken(); 2539306d8920SRichard Smith // FIXME: Support string-literal module names here. 25409194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 25419194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name); 25429194a91dSDouglas Gregor break; 25439194a91dSDouglas Gregor } 25449194a91dSDouglas Gregor 25459194a91dSDouglas Gregor Map.InferredDirectories[Directory].ExcludedModules 25469194a91dSDouglas Gregor .push_back(Tok.getString()); 25479194a91dSDouglas Gregor consumeToken(); 25489194a91dSDouglas Gregor break; 25499194a91dSDouglas Gregor } 25509194a91dSDouglas Gregor 25519194a91dSDouglas Gregor case MMToken::ExportKeyword: 25529194a91dSDouglas Gregor if (!ActiveModule) { 25539194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2554d2d442caSCraig Topper << (ActiveModule != nullptr); 25559194a91dSDouglas Gregor consumeToken(); 25569194a91dSDouglas Gregor break; 25579194a91dSDouglas Gregor } 25589194a91dSDouglas Gregor 255973441091SDouglas Gregor consumeToken(); 256073441091SDouglas Gregor if (Tok.is(MMToken::Star)) 2561dd005f69SDouglas Gregor ActiveModule->InferExportWildcard = true; 256273441091SDouglas Gregor else 256373441091SDouglas Gregor Diags.Report(Tok.getLocation(), 256473441091SDouglas Gregor diag::err_mmap_expected_export_wildcard); 256573441091SDouglas Gregor consumeToken(); 256673441091SDouglas Gregor break; 256773441091SDouglas Gregor 256873441091SDouglas Gregor case MMToken::ExplicitKeyword: 256973441091SDouglas Gregor case MMToken::ModuleKeyword: 257073441091SDouglas Gregor case MMToken::HeaderKeyword: 2571b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 257273441091SDouglas Gregor case MMToken::UmbrellaKeyword: 257373441091SDouglas Gregor default: 25749194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2575d2d442caSCraig Topper << (ActiveModule != nullptr); 257673441091SDouglas Gregor consumeToken(); 257773441091SDouglas Gregor break; 257873441091SDouglas Gregor } 257973441091SDouglas Gregor } while (!Done); 258073441091SDouglas Gregor 258173441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 258273441091SDouglas Gregor consumeToken(); 258373441091SDouglas Gregor else { 258473441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 258573441091SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 258673441091SDouglas Gregor HadError = true; 258773441091SDouglas Gregor } 258873441091SDouglas Gregor } 258973441091SDouglas Gregor 25909194a91dSDouglas Gregor /// \brief Parse optional attributes. 25919194a91dSDouglas Gregor /// 25929194a91dSDouglas Gregor /// attributes: 25939194a91dSDouglas Gregor /// attribute attributes 25949194a91dSDouglas Gregor /// attribute 25959194a91dSDouglas Gregor /// 25969194a91dSDouglas Gregor /// attribute: 25979194a91dSDouglas Gregor /// [ identifier ] 25989194a91dSDouglas Gregor /// 25999194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes. 26009194a91dSDouglas Gregor /// 26019194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise. 26024442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { 26039194a91dSDouglas Gregor bool HadError = false; 26049194a91dSDouglas Gregor 26059194a91dSDouglas Gregor while (Tok.is(MMToken::LSquare)) { 26069194a91dSDouglas Gregor // Consume the '['. 26079194a91dSDouglas Gregor SourceLocation LSquareLoc = consumeToken(); 26089194a91dSDouglas Gregor 26099194a91dSDouglas Gregor // Check whether we have an attribute name here. 26109194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 26119194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute); 26129194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 26139194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 26149194a91dSDouglas Gregor consumeToken(); 26159194a91dSDouglas Gregor HadError = true; 26169194a91dSDouglas Gregor } 26179194a91dSDouglas Gregor 26189194a91dSDouglas Gregor // Decode the attribute name. 26199194a91dSDouglas Gregor AttributeKind Attribute 26209194a91dSDouglas Gregor = llvm::StringSwitch<AttributeKind>(Tok.getString()) 262135b13eceSDouglas Gregor .Case("exhaustive", AT_exhaustive) 262277944868SRichard Smith .Case("extern_c", AT_extern_c) 2623ed84df00SBruno Cardoso Lopes .Case("no_undeclared_includes", AT_no_undeclared_includes) 26249194a91dSDouglas Gregor .Case("system", AT_system) 26259194a91dSDouglas Gregor .Default(AT_unknown); 26269194a91dSDouglas Gregor switch (Attribute) { 26279194a91dSDouglas Gregor case AT_unknown: 26289194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute) 26299194a91dSDouglas Gregor << Tok.getString(); 26309194a91dSDouglas Gregor break; 26319194a91dSDouglas Gregor 26329194a91dSDouglas Gregor case AT_system: 26339194a91dSDouglas Gregor Attrs.IsSystem = true; 26349194a91dSDouglas Gregor break; 263535b13eceSDouglas Gregor 263677944868SRichard Smith case AT_extern_c: 263777944868SRichard Smith Attrs.IsExternC = true; 263877944868SRichard Smith break; 263977944868SRichard Smith 264035b13eceSDouglas Gregor case AT_exhaustive: 264135b13eceSDouglas Gregor Attrs.IsExhaustive = true; 264235b13eceSDouglas Gregor break; 2643ed84df00SBruno Cardoso Lopes 2644ed84df00SBruno Cardoso Lopes case AT_no_undeclared_includes: 2645ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes = true; 2646ed84df00SBruno Cardoso Lopes break; 26479194a91dSDouglas Gregor } 26489194a91dSDouglas Gregor consumeToken(); 26499194a91dSDouglas Gregor 26509194a91dSDouglas Gregor // Consume the ']'. 26519194a91dSDouglas Gregor if (!Tok.is(MMToken::RSquare)) { 26529194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare); 26539194a91dSDouglas Gregor Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match); 26549194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 26559194a91dSDouglas Gregor HadError = true; 26569194a91dSDouglas Gregor } 26579194a91dSDouglas Gregor 26589194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 26599194a91dSDouglas Gregor consumeToken(); 26609194a91dSDouglas Gregor } 26619194a91dSDouglas Gregor 26629194a91dSDouglas Gregor return HadError; 26639194a91dSDouglas Gregor } 26649194a91dSDouglas Gregor 2665718292f2SDouglas Gregor /// \brief Parse a module map file. 2666718292f2SDouglas Gregor /// 2667718292f2SDouglas Gregor /// module-map-file: 2668718292f2SDouglas Gregor /// module-declaration* 2669718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 2670718292f2SDouglas Gregor do { 2671718292f2SDouglas Gregor switch (Tok.Kind) { 2672718292f2SDouglas Gregor case MMToken::EndOfFile: 2673718292f2SDouglas Gregor return HadError; 2674718292f2SDouglas Gregor 2675e7ab3669SDouglas Gregor case MMToken::ExplicitKeyword: 267697292843SDaniel Jasper case MMToken::ExternKeyword: 2677718292f2SDouglas Gregor case MMToken::ModuleKeyword: 2678755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 2679718292f2SDouglas Gregor parseModuleDecl(); 2680718292f2SDouglas Gregor break; 2681718292f2SDouglas Gregor 26821fb5c3a6SDouglas Gregor case MMToken::Comma: 268335b13eceSDouglas Gregor case MMToken::ConfigMacros: 2684fb912657SDouglas Gregor case MMToken::Conflict: 2685a3feee2aSRichard Smith case MMToken::Exclaim: 268659527666SDouglas Gregor case MMToken::ExcludeKeyword: 26872b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 2688718292f2SDouglas Gregor case MMToken::HeaderKeyword: 2689718292f2SDouglas Gregor case MMToken::Identifier: 2690718292f2SDouglas Gregor case MMToken::LBrace: 26916ddfca91SDouglas Gregor case MMToken::LinkKeyword: 2692a686e1b0SDouglas Gregor case MMToken::LSquare: 26932b82c2a5SDouglas Gregor case MMToken::Period: 2694b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 2695718292f2SDouglas Gregor case MMToken::RBrace: 2696a686e1b0SDouglas Gregor case MMToken::RSquare: 26971fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 26982b82c2a5SDouglas Gregor case MMToken::Star: 2699718292f2SDouglas Gregor case MMToken::StringLiteral: 2700040e1266SRichard Smith case MMToken::IntegerLiteral: 2701b8afebe2SRichard Smith case MMToken::TextualKeyword: 2702718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 2703ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 2704718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 2705718292f2SDouglas Gregor HadError = true; 2706718292f2SDouglas Gregor consumeToken(); 2707718292f2SDouglas Gregor break; 2708718292f2SDouglas Gregor } 2709718292f2SDouglas Gregor } while (true); 2710718292f2SDouglas Gregor } 2711718292f2SDouglas Gregor 27129acb99e3SRichard Smith bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem, 27138128f332SRichard Smith const DirectoryEntry *Dir, FileID ID, 27148128f332SRichard Smith unsigned *Offset, 2715ae6df27eSRichard Smith SourceLocation ExternModuleLoc) { 27168128f332SRichard Smith assert(Target && "Missing target information"); 27174ddf2221SDouglas Gregor llvm::DenseMap<const FileEntry *, bool>::iterator Known 27184ddf2221SDouglas Gregor = ParsedModuleMap.find(File); 27194ddf2221SDouglas Gregor if (Known != ParsedModuleMap.end()) 27204ddf2221SDouglas Gregor return Known->second; 27214ddf2221SDouglas Gregor 27228128f332SRichard Smith // If the module map file wasn't already entered, do so now. 27238128f332SRichard Smith if (ID.isInvalid()) { 2724f3f84616SRichard Smith auto FileCharacter = 2725f3f84616SRichard Smith IsSystem ? SrcMgr::C_System_ModuleMap : SrcMgr::C_User_ModuleMap; 27268128f332SRichard Smith ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter); 27278128f332SRichard Smith } 27288128f332SRichard Smith 27298128f332SRichard Smith assert(Target && "Missing target information"); 27301f76c4e8SManuel Klimek const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID); 2731718292f2SDouglas Gregor if (!Buffer) 27324ddf2221SDouglas Gregor return ParsedModuleMap[File] = true; 27338128f332SRichard Smith assert((!Offset || *Offset <= Buffer->getBufferSize()) && 27348128f332SRichard Smith "invalid buffer offset"); 2735718292f2SDouglas Gregor 2736718292f2SDouglas Gregor // Parse this module map file. 27378128f332SRichard Smith Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts, 27388128f332SRichard Smith Buffer->getBufferStart(), 27398128f332SRichard Smith Buffer->getBufferStart() + (Offset ? *Offset : 0), 27408128f332SRichard Smith Buffer->getBufferEnd()); 27412a6edb30SRichard Smith SourceLocation Start = L.getSourceLocation(); 2742beee15e7SBen Langmuir ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir, 27431d60987fSRichard Smith IsSystem); 2744718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 27454ddf2221SDouglas Gregor ParsedModuleMap[File] = Result; 27462a6edb30SRichard Smith 27478128f332SRichard Smith if (Offset) { 27488128f332SRichard Smith auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation()); 27498128f332SRichard Smith assert(Loc.first == ID && "stopped in a different file?"); 27508128f332SRichard Smith *Offset = Loc.second; 27518128f332SRichard Smith } 27528128f332SRichard Smith 27532a6edb30SRichard Smith // Notify callbacks that we parsed it. 27542a6edb30SRichard Smith for (const auto &Cb : Callbacks) 27552a6edb30SRichard Smith Cb->moduleMapFileRead(Start, *File, IsSystem); 2756718292f2SDouglas Gregor return Result; 2757718292f2SDouglas Gregor } 2758