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 39*040e1266SRichard Smith Module::HeaderKind ModuleMap::headerRoleToKind(ModuleHeaderRole Role) { 40*040e1266SRichard Smith switch ((int)Role) { 41*040e1266SRichard Smith default: llvm_unreachable("unknown header role"); 42*040e1266SRichard Smith case NormalHeader: 43*040e1266SRichard Smith return Module::HK_Normal; 44*040e1266SRichard Smith case PrivateHeader: 45*040e1266SRichard Smith return Module::HK_Private; 46*040e1266SRichard Smith case TextualHeader: 47*040e1266SRichard Smith return Module::HK_Textual; 48*040e1266SRichard Smith case PrivateHeader | TextualHeader: 49*040e1266SRichard Smith return Module::HK_PrivateTextual; 50*040e1266SRichard Smith } 51*040e1266SRichard Smith } 52*040e1266SRichard Smith 53*040e1266SRichard Smith ModuleMap::ModuleHeaderRole 54*040e1266SRichard Smith ModuleMap::headerKindToRole(Module::HeaderKind Kind) { 55*040e1266SRichard Smith switch ((int)Kind) { 56*040e1266SRichard Smith case Module::HK_Normal: 57*040e1266SRichard Smith return NormalHeader; 58*040e1266SRichard Smith case Module::HK_Private: 59*040e1266SRichard Smith return PrivateHeader; 60*040e1266SRichard Smith case Module::HK_Textual: 61*040e1266SRichard Smith return TextualHeader; 62*040e1266SRichard Smith case Module::HK_PrivateTextual: 63*040e1266SRichard Smith return ModuleHeaderRole(PrivateHeader | TextualHeader); 64*040e1266SRichard Smith case Module::HK_Excluded: 65*040e1266SRichard Smith llvm_unreachable("unexpected header kind"); 66*040e1266SRichard Smith } 67*040e1266SRichard Smith llvm_unreachable("unknown header kind"); 68*040e1266SRichard Smith } 69*040e1266SRichard 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 * 138*040e1266SRichard Smith ModuleMap::findHeader(Module *M, 139*040e1266SRichard Smith const Module::UnresolvedHeaderDirective &Header, 1401d60987fSRichard Smith SmallVectorImpl<char> &RelativePathName) { 141*040e1266SRichard Smith auto GetFile = [&](StringRef Filename) -> const FileEntry * { 142*040e1266SRichard Smith auto *File = SourceMgr.getFileManager().getFile(Filename); 143*040e1266SRichard Smith if (!File || 144*040e1266SRichard Smith (Header.Size && File->getSize() != *Header.Size) || 145*040e1266SRichard Smith (Header.ModTime && File->getModificationTime() != *Header.ModTime)) 146*040e1266SRichard Smith return nullptr; 147*040e1266SRichard Smith return File; 148*040e1266SRichard Smith }; 149*040e1266SRichard 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()); 153*040e1266SRichard 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); 168*040e1266SRichard 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); 185*040e1266SRichard 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); 191*040e1266SRichard Smith return GetFile(FullPathName); 1921d60987fSRichard Smith } 1931d60987fSRichard Smith 194*040e1266SRichard Smith void ModuleMap::resolveHeader(Module *Mod, 195*040e1266SRichard Smith const Module::UnresolvedHeaderDirective &Header) { 196*040e1266SRichard Smith SmallString<128> RelativePathName; 197*040e1266SRichard Smith if (const FileEntry *File = findHeader(Mod, Header, RelativePathName)) { 198*040e1266SRichard Smith if (Header.IsUmbrella) { 199*040e1266SRichard Smith const DirectoryEntry *UmbrellaDir = File->getDir(); 200*040e1266SRichard Smith if (Module *UmbrellaMod = UmbrellaDirs[UmbrellaDir]) 201*040e1266SRichard Smith Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) 202*040e1266SRichard Smith << UmbrellaMod->getFullModuleName(); 203*040e1266SRichard Smith else 204*040e1266SRichard Smith // Record this umbrella header. 205*040e1266SRichard Smith setUmbrellaHeader(Mod, File, RelativePathName.str()); 206*040e1266SRichard Smith } else { 207*040e1266SRichard Smith Module::Header H = {RelativePathName.str(), File}; 208*040e1266SRichard Smith if (Header.Kind == Module::HK_Excluded) 209*040e1266SRichard Smith excludeHeader(Mod, H); 210*040e1266SRichard Smith else 211*040e1266SRichard Smith addHeader(Mod, H, headerKindToRole(Header.Kind)); 212*040e1266SRichard Smith } 213*040e1266SRichard Smith } else if (Header.HasBuiltinHeader && !Header.Size && !Header.ModTime) { 214*040e1266SRichard Smith // There's a builtin header but no corresponding on-disk header. Assume 215*040e1266SRichard Smith // this was supposed to modularize the builtin header alone. 216*040e1266SRichard Smith } else if (Header.Kind == Module::HK_Excluded) { 217*040e1266SRichard Smith // Ignore missing excluded header files. They're optional anyway. 218*040e1266SRichard Smith } else { 219*040e1266SRichard Smith // If we find a module that has a missing header, we mark this module as 220*040e1266SRichard Smith // unavailable and store the header directive for displaying diagnostics. 221*040e1266SRichard Smith Mod->MissingHeaders.push_back(Header); 222*040e1266SRichard Smith // A missing header with stat information doesn't make the module 223*040e1266SRichard Smith // unavailable; this keeps our behavior consistent as headers are lazily 224*040e1266SRichard Smith // resolved. (Such a module still can't be built though, except from 225*040e1266SRichard Smith // preprocessed source.) 226*040e1266SRichard Smith if (!Header.Size && !Header.ModTime) 227*040e1266SRichard Smith Mod->markUnavailable(); 228*040e1266SRichard Smith } 229*040e1266SRichard Smith } 230*040e1266SRichard Smith 231*040e1266SRichard Smith bool ModuleMap::resolveAsBuiltinHeader( 232*040e1266SRichard Smith Module *Mod, const Module::UnresolvedHeaderDirective &Header) { 233*040e1266SRichard Smith if (Header.Kind == Module::HK_Excluded || 234*040e1266SRichard Smith llvm::sys::path::is_absolute(Header.FileName) || 235*040e1266SRichard Smith Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella || 236*040e1266SRichard Smith !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory || 237*040e1266SRichard Smith !isBuiltinHeader(Header.FileName)) 238*040e1266SRichard 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. 243*040e1266SRichard Smith SmallString<128> Path; 244*040e1266SRichard Smith llvm::sys::path::append(Path, BuiltinIncludeDir->getName(), Header.FileName); 245*040e1266SRichard Smith auto *File = SourceMgr.getFileManager().getFile(Path); 246*040e1266SRichard Smith if (!File) 247*040e1266SRichard Smith return false; 248*040e1266SRichard Smith 249*040e1266SRichard Smith auto Role = headerKindToRole(Header.Kind); 250*040e1266SRichard Smith Module::Header H = {Path.str(), File}; 251*040e1266SRichard Smith addHeader(Mod, H, Role); 252*040e1266SRichard 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) { 333*040e1266SRichard 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 416*040e1266SRichard Smith if (RequestingModule) { 41792669ee4SDaniel Jasper resolveUses(RequestingModule, /*Complain=*/false); 418*040e1266SRichard Smith resolveHeaderDirectives(RequestingModule); 419*040e1266SRichard 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 { 601*040e1266SRichard 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 { 615*040e1266SRichard 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 749bbcc9f04SRichard Smith Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc, 750bbcc9f04SRichard Smith StringRef Name) { 751bbcc9f04SRichard Smith assert(LangOpts.CurrentModule == Name && "module name mismatch"); 752bbcc9f04SRichard Smith assert(!Modules[Name] && "redefining existing module"); 753bbcc9f04SRichard Smith 754bbcc9f04SRichard Smith auto *Result = 755bbcc9f04SRichard Smith new Module(Name, Loc, nullptr, /*IsFramework*/ false, 756bbcc9f04SRichard Smith /*IsExplicit*/ false, NumCreatedModules++); 757145e15a3SRichard Smith Result->Kind = Module::ModuleInterfaceUnit; 758bbcc9f04SRichard Smith Modules[Name] = SourceModule = Result; 759bbcc9f04SRichard Smith 760bbcc9f04SRichard Smith // Mark the main source file as being within the newly-created module so that 761bbcc9f04SRichard Smith // declarations and macros are properly visibility-restricted to it. 762bbcc9f04SRichard Smith auto *MainFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID()); 763bbcc9f04SRichard Smith assert(MainFile && "no input file for module interface"); 764bbcc9f04SRichard Smith Headers[MainFile].push_back(KnownHeader(Result, PrivateHeader)); 765bbcc9f04SRichard Smith 766bbcc9f04SRichard Smith return Result; 767bbcc9f04SRichard Smith } 768bbcc9f04SRichard Smith 76911dfe6feSDouglas Gregor /// \brief For a framework module, infer the framework against which we 77011dfe6feSDouglas Gregor /// should link. 77111dfe6feSDouglas Gregor static void inferFrameworkLink(Module *Mod, const DirectoryEntry *FrameworkDir, 77211dfe6feSDouglas Gregor FileManager &FileMgr) { 77311dfe6feSDouglas Gregor assert(Mod->IsFramework && "Can only infer linking for framework modules"); 77411dfe6feSDouglas Gregor assert(!Mod->isSubFramework() && 77511dfe6feSDouglas Gregor "Can only infer linking for top-level frameworks"); 77611dfe6feSDouglas Gregor 77711dfe6feSDouglas Gregor SmallString<128> LibName; 77811dfe6feSDouglas Gregor LibName += FrameworkDir->getName(); 77911dfe6feSDouglas Gregor llvm::sys::path::append(LibName, Mod->Name); 7808aaae5a9SJuergen Ributzka 7818aaae5a9SJuergen Ributzka // The library name of a framework has more than one possible extension since 7828aaae5a9SJuergen Ributzka // the introduction of the text-based dynamic library format. We need to check 7838aaae5a9SJuergen Ributzka // for both before we give up. 7848013e81dSBenjamin Kramer for (const char *extension : {"", ".tbd"}) { 7858aaae5a9SJuergen Ributzka llvm::sys::path::replace_extension(LibName, extension); 78611dfe6feSDouglas Gregor if (FileMgr.getFile(LibName)) { 78711dfe6feSDouglas Gregor Mod->LinkLibraries.push_back(Module::LinkLibrary(Mod->Name, 78811dfe6feSDouglas Gregor /*IsFramework=*/true)); 7898aaae5a9SJuergen Ributzka return; 7908aaae5a9SJuergen Ributzka } 79111dfe6feSDouglas Gregor } 79211dfe6feSDouglas Gregor } 79311dfe6feSDouglas Gregor 794a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 795a525400dSBen Langmuir bool IsSystem, Module *Parent) { 796c1d88ea5SBen Langmuir Attributes Attrs; 797c1d88ea5SBen Langmuir Attrs.IsSystem = IsSystem; 798a525400dSBen Langmuir return inferFrameworkModule(FrameworkDir, Attrs, Parent); 799c1d88ea5SBen Langmuir } 800c1d88ea5SBen Langmuir 801a525400dSBen Langmuir Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, 802c1d88ea5SBen Langmuir Attributes Attrs, Module *Parent) { 803a525400dSBen Langmuir // Note: as an egregious but useful hack we use the real path here, because 804a525400dSBen Langmuir // we might be looking at an embedded framework that symlinks out to a 805a525400dSBen Langmuir // top-level framework, and we need to infer as if we were naming the 806a525400dSBen Langmuir // top-level framework. 807a525400dSBen Langmuir StringRef FrameworkDirName = 808a525400dSBen Langmuir SourceMgr.getFileManager().getCanonicalName(FrameworkDir); 809a525400dSBen Langmuir 810a525400dSBen Langmuir // In case this is a case-insensitive filesystem, use the canonical 811a525400dSBen Langmuir // directory name as the ModuleName, since modules are case-sensitive. 812a525400dSBen Langmuir // FIXME: we should be able to give a fix-it hint for the correct spelling. 813a525400dSBen Langmuir SmallString<32> ModuleNameStorage; 814a525400dSBen Langmuir StringRef ModuleName = sanitizeFilenameAsIdentifier( 815a525400dSBen Langmuir llvm::sys::path::stem(FrameworkDirName), ModuleNameStorage); 816c1d88ea5SBen Langmuir 81756c64013SDouglas Gregor // Check whether we've already found this module. 818e89dbc1dSDouglas Gregor if (Module *Mod = lookupModuleQualified(ModuleName, Parent)) 819e89dbc1dSDouglas Gregor return Mod; 820e89dbc1dSDouglas Gregor 8211f76c4e8SManuel Klimek FileManager &FileMgr = SourceMgr.getFileManager(); 82256c64013SDouglas Gregor 8239194a91dSDouglas Gregor // If the framework has a parent path from which we're allowed to infer 8249194a91dSDouglas Gregor // a framework module, do so. 825beee15e7SBen Langmuir const FileEntry *ModuleMapFile = nullptr; 8269194a91dSDouglas Gregor if (!Parent) { 8274ddf2221SDouglas Gregor // Determine whether we're allowed to infer a module map. 8289194a91dSDouglas Gregor bool canInfer = false; 8294ddf2221SDouglas Gregor if (llvm::sys::path::has_parent_path(FrameworkDirName)) { 8309194a91dSDouglas Gregor // Figure out the parent path. 8314ddf2221SDouglas Gregor StringRef Parent = llvm::sys::path::parent_path(FrameworkDirName); 8329194a91dSDouglas Gregor if (const DirectoryEntry *ParentDir = FileMgr.getDirectory(Parent)) { 8339194a91dSDouglas Gregor // Check whether we have already looked into the parent directory 8349194a91dSDouglas Gregor // for a module map. 835e4412640SArgyrios Kyrtzidis llvm::DenseMap<const DirectoryEntry *, InferredDirectory>::const_iterator 8369194a91dSDouglas Gregor inferred = InferredDirectories.find(ParentDir); 8379194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) { 8389194a91dSDouglas Gregor // We haven't looked here before. Load a module map, if there is 8399194a91dSDouglas Gregor // one. 840984e1df7SBen Langmuir bool IsFrameworkDir = Parent.endswith(".framework"); 841984e1df7SBen Langmuir if (const FileEntry *ModMapFile = 842984e1df7SBen Langmuir HeaderInfo.lookupModuleMapFile(ParentDir, IsFrameworkDir)) { 843c1d88ea5SBen Langmuir parseModuleMapFile(ModMapFile, Attrs.IsSystem, ParentDir); 8449194a91dSDouglas Gregor inferred = InferredDirectories.find(ParentDir); 8459194a91dSDouglas Gregor } 8469194a91dSDouglas Gregor 8479194a91dSDouglas Gregor if (inferred == InferredDirectories.end()) 8489194a91dSDouglas Gregor inferred = InferredDirectories.insert( 8499194a91dSDouglas Gregor std::make_pair(ParentDir, InferredDirectory())).first; 8509194a91dSDouglas Gregor } 8519194a91dSDouglas Gregor 8529194a91dSDouglas Gregor if (inferred->second.InferModules) { 8539194a91dSDouglas Gregor // We're allowed to infer for this directory, but make sure it's okay 8549194a91dSDouglas Gregor // to infer this particular module. 8554ddf2221SDouglas Gregor StringRef Name = llvm::sys::path::stem(FrameworkDirName); 8569194a91dSDouglas Gregor canInfer = std::find(inferred->second.ExcludedModules.begin(), 8579194a91dSDouglas Gregor inferred->second.ExcludedModules.end(), 8589194a91dSDouglas Gregor Name) == inferred->second.ExcludedModules.end(); 8599194a91dSDouglas Gregor 860c1d88ea5SBen Langmuir Attrs.IsSystem |= inferred->second.Attrs.IsSystem; 861c1d88ea5SBen Langmuir Attrs.IsExternC |= inferred->second.Attrs.IsExternC; 862c1d88ea5SBen Langmuir Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive; 863ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes |= 864ed84df00SBruno Cardoso Lopes inferred->second.Attrs.NoUndeclaredIncludes; 865beee15e7SBen Langmuir ModuleMapFile = inferred->second.ModuleMapFile; 8669194a91dSDouglas Gregor } 8679194a91dSDouglas Gregor } 8689194a91dSDouglas Gregor } 8699194a91dSDouglas Gregor 8709194a91dSDouglas Gregor // If we're not allowed to infer a framework module, don't. 8719194a91dSDouglas Gregor if (!canInfer) 872d2d442caSCraig Topper return nullptr; 873beee15e7SBen Langmuir } else 8749d6448b1SBen Langmuir ModuleMapFile = getModuleMapFileForUniquing(Parent); 8759194a91dSDouglas Gregor 8769194a91dSDouglas Gregor 87756c64013SDouglas Gregor // Look for an umbrella header. 8782c1dd271SDylan Noblesmith SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 87917381a06SBenjamin Kramer llvm::sys::path::append(UmbrellaName, "Headers", ModuleName + ".h"); 880e89dbc1dSDouglas Gregor const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName); 88156c64013SDouglas Gregor 88256c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the 88356c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good 88456c64013SDouglas Gregor // idea. 88556c64013SDouglas Gregor if (!UmbrellaHeader) 886d2d442caSCraig Topper return nullptr; 88756c64013SDouglas Gregor 8889d6448b1SBen Langmuir Module *Result = new Module(ModuleName, SourceLocation(), Parent, 889a7e2cc68SRichard Smith /*IsFramework=*/true, /*IsExplicit=*/false, 890a7e2cc68SRichard Smith NumCreatedModules++); 8919d6448b1SBen Langmuir InferredModuleAllowedBy[Result] = ModuleMapFile; 8929d6448b1SBen Langmuir Result->IsInferred = true; 8937e82e019SRichard Smith if (!Parent) { 8947e82e019SRichard Smith if (LangOpts.CurrentModule == ModuleName) 895ba7f2f71SDaniel Jasper SourceModule = Result; 8967e82e019SRichard Smith Modules[ModuleName] = Result; 897ba7f2f71SDaniel Jasper } 898c1d88ea5SBen Langmuir 899c1d88ea5SBen Langmuir Result->IsSystem |= Attrs.IsSystem; 900c1d88ea5SBen Langmuir Result->IsExternC |= Attrs.IsExternC; 901c1d88ea5SBen Langmuir Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive; 902ed84df00SBruno Cardoso Lopes Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes; 9032b63d15fSRichard Smith Result->Directory = FrameworkDir; 904a686e1b0SDouglas Gregor 905322f633cSDouglas Gregor // umbrella header "umbrella-header-name" 9062b63d15fSRichard Smith // 9072b63d15fSRichard Smith // The "Headers/" component of the name is implied because this is 9082b63d15fSRichard Smith // a framework module. 9092b63d15fSRichard Smith setUmbrellaHeader(Result, UmbrellaHeader, ModuleName + ".h"); 910d8bd7537SDouglas Gregor 911d8bd7537SDouglas Gregor // export * 912d2d442caSCraig Topper Result->Exports.push_back(Module::ExportDecl(nullptr, true)); 913d8bd7537SDouglas Gregor 914a89c5ac4SDouglas Gregor // module * { export * } 915a89c5ac4SDouglas Gregor Result->InferSubmodules = true; 916a89c5ac4SDouglas Gregor Result->InferExportWildcard = true; 917a89c5ac4SDouglas Gregor 918e89dbc1dSDouglas Gregor // Look for subframeworks. 919c080917eSRafael Espindola std::error_code EC; 9202c1dd271SDylan Noblesmith SmallString<128> SubframeworksDirName 921ddaa69cbSDouglas Gregor = StringRef(FrameworkDir->getName()); 922e89dbc1dSDouglas Gregor llvm::sys::path::append(SubframeworksDirName, "Frameworks"); 9232d4d8cb3SBenjamin Kramer llvm::sys::path::native(SubframeworksDirName); 924b171a59bSBruno Cardoso Lopes vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); 925b171a59bSBruno Cardoso Lopes for (vfs::directory_iterator Dir = FS.dir_begin(SubframeworksDirName, EC), 926b171a59bSBruno Cardoso Lopes DirEnd; 927e89dbc1dSDouglas Gregor Dir != DirEnd && !EC; Dir.increment(EC)) { 928b171a59bSBruno Cardoso Lopes if (!StringRef(Dir->getName()).endswith(".framework")) 929e89dbc1dSDouglas Gregor continue; 930f2161a70SDouglas Gregor 931b171a59bSBruno Cardoso Lopes if (const DirectoryEntry *SubframeworkDir = 932b171a59bSBruno Cardoso Lopes FileMgr.getDirectory(Dir->getName())) { 93307c22b78SDouglas Gregor // Note: as an egregious but useful hack, we use the real path here and 93407c22b78SDouglas Gregor // check whether it is actually a subdirectory of the parent directory. 93507c22b78SDouglas Gregor // This will not be the case if the 'subframework' is actually a symlink 93607c22b78SDouglas Gregor // out to a top-level framework. 937e00c8b20SDouglas Gregor StringRef SubframeworkDirName = FileMgr.getCanonicalName(SubframeworkDir); 93807c22b78SDouglas Gregor bool FoundParent = false; 93907c22b78SDouglas Gregor do { 94007c22b78SDouglas Gregor // Get the parent directory name. 94107c22b78SDouglas Gregor SubframeworkDirName 94207c22b78SDouglas Gregor = llvm::sys::path::parent_path(SubframeworkDirName); 94307c22b78SDouglas Gregor if (SubframeworkDirName.empty()) 94407c22b78SDouglas Gregor break; 94507c22b78SDouglas Gregor 94607c22b78SDouglas Gregor if (FileMgr.getDirectory(SubframeworkDirName) == FrameworkDir) { 94707c22b78SDouglas Gregor FoundParent = true; 94807c22b78SDouglas Gregor break; 94907c22b78SDouglas Gregor } 95007c22b78SDouglas Gregor } while (true); 95107c22b78SDouglas Gregor 95207c22b78SDouglas Gregor if (!FoundParent) 95307c22b78SDouglas Gregor continue; 95407c22b78SDouglas Gregor 955e89dbc1dSDouglas Gregor // FIXME: Do we want to warn about subframeworks without umbrella headers? 956a525400dSBen Langmuir inferFrameworkModule(SubframeworkDir, Attrs, Result); 957e89dbc1dSDouglas Gregor } 958e89dbc1dSDouglas Gregor } 959e89dbc1dSDouglas Gregor 96011dfe6feSDouglas Gregor // If the module is a top-level framework, automatically link against the 96111dfe6feSDouglas Gregor // framework. 96211dfe6feSDouglas Gregor if (!Result->isSubFramework()) { 96311dfe6feSDouglas Gregor inferFrameworkLink(Result, FrameworkDir, FileMgr); 96411dfe6feSDouglas Gregor } 96511dfe6feSDouglas Gregor 96656c64013SDouglas Gregor return Result; 96756c64013SDouglas Gregor } 96856c64013SDouglas Gregor 9692b63d15fSRichard Smith void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader, 9702b63d15fSRichard Smith Twine NameAsWritten) { 97197da9178SDaniel Jasper Headers[UmbrellaHeader].push_back(KnownHeader(Mod, NormalHeader)); 97273141fa9SDouglas Gregor Mod->Umbrella = UmbrellaHeader; 9732b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 9747033127bSDouglas Gregor UmbrellaDirs[UmbrellaHeader->getDir()] = Mod; 975b3a0fa48SBruno Cardoso Lopes 976b3a0fa48SBruno Cardoso Lopes // Notify callbacks that we just added a new header. 977b3a0fa48SBruno Cardoso Lopes for (const auto &Cb : Callbacks) 978b3a0fa48SBruno Cardoso Lopes Cb->moduleMapAddUmbrellaHeader(&SourceMgr.getFileManager(), UmbrellaHeader); 979a89c5ac4SDouglas Gregor } 980a89c5ac4SDouglas Gregor 9812b63d15fSRichard Smith void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, 9822b63d15fSRichard Smith Twine NameAsWritten) { 983524e33e1SDouglas Gregor Mod->Umbrella = UmbrellaDir; 9842b63d15fSRichard Smith Mod->UmbrellaAsWritten = NameAsWritten.str(); 985524e33e1SDouglas Gregor UmbrellaDirs[UmbrellaDir] = Mod; 986524e33e1SDouglas Gregor } 987524e33e1SDouglas Gregor 988*040e1266SRichard Smith void ModuleMap::addUnresolvedHeader(Module *Mod, 989*040e1266SRichard Smith Module::UnresolvedHeaderDirective Header) { 990*040e1266SRichard Smith // If there is a builtin counterpart to this file, add it now so it can 991*040e1266SRichard Smith // wrap the system header. 992*040e1266SRichard Smith if (resolveAsBuiltinHeader(Mod, Header)) { 993*040e1266SRichard Smith // If we have both a builtin and system version of the file, the 994*040e1266SRichard Smith // builtin version may want to inject macros into the system header, so 995*040e1266SRichard Smith // force the system header to be treated as a textual header in this 996*040e1266SRichard Smith // case. 997*040e1266SRichard Smith Header.Kind = headerRoleToKind(ModuleMap::ModuleHeaderRole( 998*040e1266SRichard Smith headerKindToRole(Header.Kind) | ModuleMap::TextualHeader)); 999*040e1266SRichard Smith Header.HasBuiltinHeader = true; 10003c1a41adSRichard Smith } 1001*040e1266SRichard Smith 1002*040e1266SRichard Smith // If possible, don't stat the header until we need to. This requires the 1003*040e1266SRichard Smith // user to have provided us with some stat information about the file. 1004*040e1266SRichard Smith // FIXME: Add support for lazily stat'ing umbrella headers and excluded 1005*040e1266SRichard Smith // headers. 1006*040e1266SRichard Smith if ((Header.Size || Header.ModTime) && !Header.IsUmbrella && 1007*040e1266SRichard Smith Header.Kind != Module::HK_Excluded) { 1008*040e1266SRichard Smith // We expect more variation in mtime than size, so if we're given both, 1009*040e1266SRichard Smith // use the mtime as the key. 1010*040e1266SRichard Smith if (Header.ModTime) 1011*040e1266SRichard Smith LazyHeadersByModTime[*Header.ModTime].push_back(Mod); 1012*040e1266SRichard Smith else 1013*040e1266SRichard Smith LazyHeadersBySize[*Header.Size].push_back(Mod); 1014*040e1266SRichard Smith Mod->UnresolvedHeaders.push_back(Header); 1015*040e1266SRichard Smith return; 1016*040e1266SRichard Smith } 1017*040e1266SRichard Smith 1018*040e1266SRichard Smith // We don't have stat information or can't defer looking this file up. 1019*040e1266SRichard Smith // Perform the lookup now. 1020*040e1266SRichard Smith resolveHeader(Mod, Header); 1021*040e1266SRichard Smith } 1022*040e1266SRichard Smith 1023*040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(const FileEntry *File) const { 1024*040e1266SRichard Smith auto BySize = LazyHeadersBySize.find(File->getSize()); 1025*040e1266SRichard Smith if (BySize != LazyHeadersBySize.end()) { 1026*040e1266SRichard Smith for (auto *M : BySize->second) 1027*040e1266SRichard Smith resolveHeaderDirectives(M); 1028*040e1266SRichard Smith LazyHeadersBySize.erase(BySize); 1029*040e1266SRichard Smith } 1030*040e1266SRichard Smith 1031*040e1266SRichard Smith auto ByModTime = LazyHeadersByModTime.find(File->getModificationTime()); 1032*040e1266SRichard Smith if (ByModTime != LazyHeadersByModTime.end()) { 1033*040e1266SRichard Smith for (auto *M : ByModTime->second) 1034*040e1266SRichard Smith resolveHeaderDirectives(M); 1035*040e1266SRichard Smith LazyHeadersByModTime.erase(ByModTime); 1036*040e1266SRichard Smith } 1037*040e1266SRichard Smith } 1038*040e1266SRichard Smith 1039*040e1266SRichard Smith void ModuleMap::resolveHeaderDirectives(Module *Mod) const { 1040*040e1266SRichard Smith for (auto &Header : Mod->UnresolvedHeaders) 1041*040e1266SRichard Smith // This operation is logically const; we're just changing how we represent 1042*040e1266SRichard Smith // the header information for this file. 1043*040e1266SRichard Smith const_cast<ModuleMap*>(this)->resolveHeader(Mod, Header); 1044*040e1266SRichard Smith Mod->UnresolvedHeaders.clear(); 10450e98d938SNAKAMURA Takumi } 1046202210b3SRichard Smith 10473c1a41adSRichard Smith void ModuleMap::addHeader(Module *Mod, Module::Header Header, 1048d8879c85SRichard Smith ModuleHeaderRole Role, bool Imported) { 1049386bb073SRichard Smith KnownHeader KH(Mod, Role); 10503c1a41adSRichard Smith 1051386bb073SRichard Smith // Only add each header to the headers list once. 1052386bb073SRichard Smith // FIXME: Should we diagnose if a header is listed twice in the 1053386bb073SRichard Smith // same module definition? 1054386bb073SRichard Smith auto &HeaderList = Headers[Header.Entry]; 1055386bb073SRichard Smith for (auto H : HeaderList) 1056386bb073SRichard Smith if (H == KH) 1057386bb073SRichard Smith return; 1058386bb073SRichard Smith 1059386bb073SRichard Smith HeaderList.push_back(KH); 10601ec383c7SPiotr Padlewski Mod->Headers[headerRoleToKind(Role)].push_back(Header); 1061386bb073SRichard Smith 10627e82e019SRichard Smith bool isCompilingModuleHeader = 1063bbcc9f04SRichard Smith LangOpts.isCompilingModule() && Mod->getTopLevelModule() == SourceModule; 1064d8879c85SRichard Smith if (!Imported || isCompilingModuleHeader) { 1065d8879c85SRichard Smith // When we import HeaderFileInfo, the external source is expected to 1066d8879c85SRichard Smith // set the isModuleHeader flag itself. 1067d8879c85SRichard Smith HeaderInfo.MarkFileModuleHeader(Header.Entry, Role, 1068d8879c85SRichard Smith isCompilingModuleHeader); 1069d8879c85SRichard Smith } 1070e62cfd7cSBruno Cardoso Lopes 1071e62cfd7cSBruno Cardoso Lopes // Notify callbacks that we just added a new header. 1072e62cfd7cSBruno Cardoso Lopes for (const auto &Cb : Callbacks) 1073f0841790SBruno Cardoso Lopes Cb->moduleMapAddHeader(Header.Entry->getName()); 1074a89c5ac4SDouglas Gregor } 1075a89c5ac4SDouglas Gregor 10763c1a41adSRichard Smith void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) { 1077feb54b6dSRichard Smith // Add this as a known header so we won't implicitly add it to any 1078feb54b6dSRichard Smith // umbrella directory module. 1079feb54b6dSRichard Smith // FIXME: Should we only exclude it from umbrella modules within the 1080feb54b6dSRichard Smith // specified module? 10813c1a41adSRichard Smith (void) Headers[Header.Entry]; 10823c1a41adSRichard Smith 10833c1a41adSRichard Smith Mod->Headers[Module::HK_Excluded].push_back(std::move(Header)); 1084feb54b6dSRichard Smith } 1085feb54b6dSRichard Smith 1086514b636aSDouglas Gregor const FileEntry * 10874b8a9e95SBen Langmuir ModuleMap::getContainingModuleMapFile(const Module *Module) const { 10881f76c4e8SManuel Klimek if (Module->DefinitionLoc.isInvalid()) 1089d2d442caSCraig Topper return nullptr; 1090514b636aSDouglas Gregor 10911f76c4e8SManuel Klimek return SourceMgr.getFileEntryForID( 10921f76c4e8SManuel Klimek SourceMgr.getFileID(Module->DefinitionLoc)); 1093514b636aSDouglas Gregor } 1094514b636aSDouglas Gregor 10954b8a9e95SBen Langmuir const FileEntry *ModuleMap::getModuleMapFileForUniquing(const Module *M) const { 10969d6448b1SBen Langmuir if (M->IsInferred) { 10979d6448b1SBen Langmuir assert(InferredModuleAllowedBy.count(M) && "missing inferred module map"); 10989d6448b1SBen Langmuir return InferredModuleAllowedBy.find(M)->second; 10999d6448b1SBen Langmuir } 11009d6448b1SBen Langmuir return getContainingModuleMapFile(M); 11019d6448b1SBen Langmuir } 11029d6448b1SBen Langmuir 11039d6448b1SBen Langmuir void ModuleMap::setInferredModuleAllowedBy(Module *M, const FileEntry *ModMap) { 11049d6448b1SBen Langmuir assert(M->IsInferred && "module not inferred"); 11059d6448b1SBen Langmuir InferredModuleAllowedBy[M] = ModMap; 11069d6448b1SBen Langmuir } 11079d6448b1SBen Langmuir 1108cdae941eSYaron Keren LLVM_DUMP_METHOD void ModuleMap::dump() { 1109718292f2SDouglas Gregor llvm::errs() << "Modules:"; 1110718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 1111718292f2SDouglas Gregor MEnd = Modules.end(); 1112718292f2SDouglas Gregor M != MEnd; ++M) 1113d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 1114718292f2SDouglas Gregor 1115718292f2SDouglas Gregor llvm::errs() << "Headers:"; 111659527666SDouglas Gregor for (HeadersMap::iterator H = Headers.begin(), HEnd = Headers.end(); 1117718292f2SDouglas Gregor H != HEnd; ++H) { 111897da9178SDaniel Jasper llvm::errs() << " \"" << H->first->getName() << "\" -> "; 111997da9178SDaniel Jasper for (SmallVectorImpl<KnownHeader>::const_iterator I = H->second.begin(), 112097da9178SDaniel Jasper E = H->second.end(); 112197da9178SDaniel Jasper I != E; ++I) { 112297da9178SDaniel Jasper if (I != H->second.begin()) 112397da9178SDaniel Jasper llvm::errs() << ","; 112497da9178SDaniel Jasper llvm::errs() << I->getModule()->getFullModuleName(); 112597da9178SDaniel Jasper } 112697da9178SDaniel Jasper llvm::errs() << "\n"; 1127718292f2SDouglas Gregor } 1128718292f2SDouglas Gregor } 1129718292f2SDouglas Gregor 11302b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) { 113142413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedExports); 113242413141SRichard Smith Mod->UnresolvedExports.clear(); 113342413141SRichard Smith for (auto &UE : Unresolved) { 113442413141SRichard Smith Module::ExportDecl Export = resolveExport(Mod, UE, Complain); 1135f5eedd05SDouglas Gregor if (Export.getPointer() || Export.getInt()) 11362b82c2a5SDouglas Gregor Mod->Exports.push_back(Export); 11372b82c2a5SDouglas Gregor else 113842413141SRichard Smith Mod->UnresolvedExports.push_back(UE); 11392b82c2a5SDouglas Gregor } 114042413141SRichard Smith return !Mod->UnresolvedExports.empty(); 11412b82c2a5SDouglas Gregor } 11422b82c2a5SDouglas Gregor 1143ba7f2f71SDaniel Jasper bool ModuleMap::resolveUses(Module *Mod, bool Complain) { 114442413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedDirectUses); 114542413141SRichard Smith Mod->UnresolvedDirectUses.clear(); 114642413141SRichard Smith for (auto &UDU : Unresolved) { 114742413141SRichard Smith Module *DirectUse = resolveModuleId(UDU, Mod, Complain); 1148ba7f2f71SDaniel Jasper if (DirectUse) 1149ba7f2f71SDaniel Jasper Mod->DirectUses.push_back(DirectUse); 1150ba7f2f71SDaniel Jasper else 115142413141SRichard Smith Mod->UnresolvedDirectUses.push_back(UDU); 1152ba7f2f71SDaniel Jasper } 115342413141SRichard Smith return !Mod->UnresolvedDirectUses.empty(); 1154ba7f2f71SDaniel Jasper } 1155ba7f2f71SDaniel Jasper 1156fb912657SDouglas Gregor bool ModuleMap::resolveConflicts(Module *Mod, bool Complain) { 115742413141SRichard Smith auto Unresolved = std::move(Mod->UnresolvedConflicts); 115842413141SRichard Smith Mod->UnresolvedConflicts.clear(); 115942413141SRichard Smith for (auto &UC : Unresolved) { 116042413141SRichard Smith if (Module *OtherMod = resolveModuleId(UC.Id, Mod, Complain)) { 1161fb912657SDouglas Gregor Module::Conflict Conflict; 1162fb912657SDouglas Gregor Conflict.Other = OtherMod; 116342413141SRichard Smith Conflict.Message = UC.Message; 1164fb912657SDouglas Gregor Mod->Conflicts.push_back(Conflict); 116542413141SRichard Smith } else 116642413141SRichard Smith Mod->UnresolvedConflicts.push_back(UC); 1167fb912657SDouglas Gregor } 116842413141SRichard Smith return !Mod->UnresolvedConflicts.empty(); 1169fb912657SDouglas Gregor } 1170fb912657SDouglas Gregor 1171718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1172718292f2SDouglas Gregor // Module map file parser 1173718292f2SDouglas Gregor //----------------------------------------------------------------------------// 1174718292f2SDouglas Gregor 1175718292f2SDouglas Gregor namespace clang { 1176718292f2SDouglas Gregor /// \brief A token in a module map file. 1177718292f2SDouglas Gregor struct MMToken { 1178718292f2SDouglas Gregor enum TokenKind { 11791fb5c3a6SDouglas Gregor Comma, 118035b13eceSDouglas Gregor ConfigMacros, 1181fb912657SDouglas Gregor Conflict, 1182718292f2SDouglas Gregor EndOfFile, 1183718292f2SDouglas Gregor HeaderKeyword, 1184718292f2SDouglas Gregor Identifier, 1185a3feee2aSRichard Smith Exclaim, 118659527666SDouglas Gregor ExcludeKeyword, 1187718292f2SDouglas Gregor ExplicitKeyword, 11882b82c2a5SDouglas Gregor ExportKeyword, 118997292843SDaniel Jasper ExternKeyword, 1190755b2055SDouglas Gregor FrameworkKeyword, 11916ddfca91SDouglas Gregor LinkKeyword, 1192718292f2SDouglas Gregor ModuleKeyword, 11932b82c2a5SDouglas Gregor Period, 1194b53e5483SLawrence Crowl PrivateKeyword, 1195718292f2SDouglas Gregor UmbrellaKeyword, 1196ba7f2f71SDaniel Jasper UseKeyword, 11971fb5c3a6SDouglas Gregor RequiresKeyword, 11982b82c2a5SDouglas Gregor Star, 1199718292f2SDouglas Gregor StringLiteral, 1200*040e1266SRichard Smith IntegerLiteral, 1201306d8920SRichard Smith TextualKeyword, 1202718292f2SDouglas Gregor LBrace, 1203a686e1b0SDouglas Gregor RBrace, 1204a686e1b0SDouglas Gregor LSquare, 1205a686e1b0SDouglas Gregor RSquare 1206718292f2SDouglas Gregor } Kind; 1207718292f2SDouglas Gregor 1208718292f2SDouglas Gregor unsigned Location; 1209718292f2SDouglas Gregor unsigned StringLength; 1210*040e1266SRichard Smith union { 1211*040e1266SRichard Smith // If Kind != IntegerLiteral. 1212718292f2SDouglas Gregor const char *StringData; 1213*040e1266SRichard Smith // If Kind == IntegerLiteral. 1214*040e1266SRichard Smith uint64_t IntegerValue; 1215*040e1266SRichard Smith }; 1216718292f2SDouglas Gregor 1217718292f2SDouglas Gregor void clear() { 1218718292f2SDouglas Gregor Kind = EndOfFile; 1219718292f2SDouglas Gregor Location = 0; 1220718292f2SDouglas Gregor StringLength = 0; 1221d2d442caSCraig Topper StringData = nullptr; 1222718292f2SDouglas Gregor } 1223718292f2SDouglas Gregor 1224718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 1225718292f2SDouglas Gregor 1226718292f2SDouglas Gregor SourceLocation getLocation() const { 1227718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 1228718292f2SDouglas Gregor } 1229718292f2SDouglas Gregor 1230*040e1266SRichard Smith uint64_t getInteger() const { 1231*040e1266SRichard Smith return Kind == IntegerLiteral ? IntegerValue : 0; 1232*040e1266SRichard Smith } 1233*040e1266SRichard Smith 1234718292f2SDouglas Gregor StringRef getString() const { 1235*040e1266SRichard Smith return Kind == IntegerLiteral ? StringRef() 1236*040e1266SRichard Smith : StringRef(StringData, StringLength); 1237718292f2SDouglas Gregor } 1238718292f2SDouglas Gregor }; 1239718292f2SDouglas Gregor 1240718292f2SDouglas Gregor class ModuleMapParser { 1241718292f2SDouglas Gregor Lexer &L; 1242718292f2SDouglas Gregor SourceManager &SourceMgr; 1243bc10b9fbSDouglas Gregor 1244bc10b9fbSDouglas Gregor /// \brief Default target information, used only for string literal 1245bc10b9fbSDouglas Gregor /// parsing. 1246bc10b9fbSDouglas Gregor const TargetInfo *Target; 1247bc10b9fbSDouglas Gregor 1248718292f2SDouglas Gregor DiagnosticsEngine &Diags; 1249718292f2SDouglas Gregor ModuleMap ⤅ 1250718292f2SDouglas Gregor 1251beee15e7SBen Langmuir /// \brief The current module map file. 1252beee15e7SBen Langmuir const FileEntry *ModuleMapFile; 1253beee15e7SBen Langmuir 12549acb99e3SRichard Smith /// \brief The directory that file names in this module map file should 12559acb99e3SRichard Smith /// be resolved relative to. 12565257fc63SDouglas Gregor const DirectoryEntry *Directory; 12575257fc63SDouglas Gregor 1258963c5535SDouglas Gregor /// \brief Whether this module map is in a system header directory. 1259963c5535SDouglas Gregor bool IsSystem; 1260963c5535SDouglas Gregor 1261718292f2SDouglas Gregor /// \brief Whether an error occurred. 1262718292f2SDouglas Gregor bool HadError; 1263718292f2SDouglas Gregor 1264718292f2SDouglas Gregor /// \brief Stores string data for the various string literals referenced 1265718292f2SDouglas Gregor /// during parsing. 1266718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 1267718292f2SDouglas Gregor 1268718292f2SDouglas Gregor /// \brief The current token. 1269718292f2SDouglas Gregor MMToken Tok; 1270718292f2SDouglas Gregor 1271718292f2SDouglas Gregor /// \brief The active module. 1272de3ef502SDouglas Gregor Module *ActiveModule; 1273718292f2SDouglas Gregor 12747ff29148SBen Langmuir /// \brief Whether a module uses the 'requires excluded' hack to mark its 12757ff29148SBen Langmuir /// contents as 'textual'. 12767ff29148SBen Langmuir /// 12777ff29148SBen Langmuir /// On older Darwin SDK versions, 'requires excluded' is used to mark the 12787ff29148SBen Langmuir /// contents of the Darwin.C.excluded (assert.h) and Tcl.Private modules as 12797ff29148SBen Langmuir /// non-modular headers. For backwards compatibility, we continue to 12807ff29148SBen Langmuir /// support this idiom for just these modules, and map the headers to 12817ff29148SBen Langmuir /// 'textual' to match the original intent. 12827ff29148SBen Langmuir llvm::SmallPtrSet<Module *, 2> UsesRequiresExcludedHack; 12837ff29148SBen Langmuir 1284718292f2SDouglas Gregor /// \brief Consume the current token and return its location. 1285718292f2SDouglas Gregor SourceLocation consumeToken(); 1286718292f2SDouglas Gregor 1287718292f2SDouglas Gregor /// \brief Skip tokens until we reach the a token with the given kind 1288718292f2SDouglas Gregor /// (or the end of the file). 1289718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 1290718292f2SDouglas Gregor 1291f857950dSDmitri Gribenko typedef SmallVector<std::pair<std::string, SourceLocation>, 2> ModuleId; 1292e7ab3669SDouglas Gregor bool parseModuleId(ModuleId &Id); 1293718292f2SDouglas Gregor void parseModuleDecl(); 129497292843SDaniel Jasper void parseExternModuleDecl(); 12951fb5c3a6SDouglas Gregor void parseRequiresDecl(); 1296b53e5483SLawrence Crowl void parseHeaderDecl(clang::MMToken::TokenKind, 1297b53e5483SLawrence Crowl SourceLocation LeadingLoc); 1298524e33e1SDouglas Gregor void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc); 12992b82c2a5SDouglas Gregor void parseExportDecl(); 1300ba7f2f71SDaniel Jasper void parseUseDecl(); 13016ddfca91SDouglas Gregor void parseLinkDecl(); 130235b13eceSDouglas Gregor void parseConfigMacros(); 1303fb912657SDouglas Gregor void parseConflict(); 13049194a91dSDouglas Gregor void parseInferredModuleDecl(bool Framework, bool Explicit); 1305c1d88ea5SBen Langmuir 1306c1d88ea5SBen Langmuir typedef ModuleMap::Attributes Attributes; 13074442605fSBill Wendling bool parseOptionalAttributes(Attributes &Attrs); 1308718292f2SDouglas Gregor 1309718292f2SDouglas Gregor public: 1310718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 1311bc10b9fbSDouglas Gregor const TargetInfo *Target, 1312718292f2SDouglas Gregor DiagnosticsEngine &Diags, 13135257fc63SDouglas Gregor ModuleMap &Map, 1314beee15e7SBen Langmuir const FileEntry *ModuleMapFile, 13153ec6663bSDouglas Gregor const DirectoryEntry *Directory, 1316963c5535SDouglas Gregor bool IsSystem) 1317bc10b9fbSDouglas Gregor : L(L), SourceMgr(SourceMgr), Target(Target), Diags(Diags), Map(Map), 1318beee15e7SBen Langmuir ModuleMapFile(ModuleMapFile), Directory(Directory), 13191d60987fSRichard Smith IsSystem(IsSystem), HadError(false), ActiveModule(nullptr) 1320718292f2SDouglas Gregor { 1321718292f2SDouglas Gregor Tok.clear(); 1322718292f2SDouglas Gregor consumeToken(); 1323718292f2SDouglas Gregor } 1324718292f2SDouglas Gregor 1325718292f2SDouglas Gregor bool parseModuleMapFile(); 13268128f332SRichard Smith 13278128f332SRichard Smith bool terminatedByDirective() { return false; } 13288128f332SRichard Smith SourceLocation getLocation() { return Tok.getLocation(); } 1329718292f2SDouglas Gregor }; 1330ab9db510SAlexander Kornienko } 1331718292f2SDouglas Gregor 1332718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 1333718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 1334718292f2SDouglas Gregor 13358128f332SRichard Smith retry: 13368128f332SRichard Smith Tok.clear(); 1337718292f2SDouglas Gregor Token LToken; 1338718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 1339718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 1340718292f2SDouglas Gregor switch (LToken.getKind()) { 13412d57cea2SAlp Toker case tok::raw_identifier: { 13422d57cea2SAlp Toker StringRef RI = LToken.getRawIdentifier(); 13432d57cea2SAlp Toker Tok.StringData = RI.data(); 13442d57cea2SAlp Toker Tok.StringLength = RI.size(); 13452d57cea2SAlp Toker Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(RI) 134635b13eceSDouglas Gregor .Case("config_macros", MMToken::ConfigMacros) 1347fb912657SDouglas Gregor .Case("conflict", MMToken::Conflict) 134859527666SDouglas Gregor .Case("exclude", MMToken::ExcludeKeyword) 1349718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 13502b82c2a5SDouglas Gregor .Case("export", MMToken::ExportKeyword) 135197292843SDaniel Jasper .Case("extern", MMToken::ExternKeyword) 1352755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 135335b13eceSDouglas Gregor .Case("header", MMToken::HeaderKeyword) 13546ddfca91SDouglas Gregor .Case("link", MMToken::LinkKeyword) 1355718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 1356b53e5483SLawrence Crowl .Case("private", MMToken::PrivateKeyword) 13571fb5c3a6SDouglas Gregor .Case("requires", MMToken::RequiresKeyword) 1358306d8920SRichard Smith .Case("textual", MMToken::TextualKeyword) 1359718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 1360ba7f2f71SDaniel Jasper .Case("use", MMToken::UseKeyword) 1361718292f2SDouglas Gregor .Default(MMToken::Identifier); 1362718292f2SDouglas Gregor break; 13632d57cea2SAlp Toker } 1364718292f2SDouglas Gregor 13651fb5c3a6SDouglas Gregor case tok::comma: 13661fb5c3a6SDouglas Gregor Tok.Kind = MMToken::Comma; 13671fb5c3a6SDouglas Gregor break; 13681fb5c3a6SDouglas Gregor 1369718292f2SDouglas Gregor case tok::eof: 1370718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 1371718292f2SDouglas Gregor break; 1372718292f2SDouglas Gregor 1373718292f2SDouglas Gregor case tok::l_brace: 1374718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 1375718292f2SDouglas Gregor break; 1376718292f2SDouglas Gregor 1377a686e1b0SDouglas Gregor case tok::l_square: 1378a686e1b0SDouglas Gregor Tok.Kind = MMToken::LSquare; 1379a686e1b0SDouglas Gregor break; 1380a686e1b0SDouglas Gregor 13812b82c2a5SDouglas Gregor case tok::period: 13822b82c2a5SDouglas Gregor Tok.Kind = MMToken::Period; 13832b82c2a5SDouglas Gregor break; 13842b82c2a5SDouglas Gregor 1385718292f2SDouglas Gregor case tok::r_brace: 1386718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 1387718292f2SDouglas Gregor break; 1388718292f2SDouglas Gregor 1389a686e1b0SDouglas Gregor case tok::r_square: 1390a686e1b0SDouglas Gregor Tok.Kind = MMToken::RSquare; 1391a686e1b0SDouglas Gregor break; 1392a686e1b0SDouglas Gregor 13932b82c2a5SDouglas Gregor case tok::star: 13942b82c2a5SDouglas Gregor Tok.Kind = MMToken::Star; 13952b82c2a5SDouglas Gregor break; 13962b82c2a5SDouglas Gregor 1397a3feee2aSRichard Smith case tok::exclaim: 1398a3feee2aSRichard Smith Tok.Kind = MMToken::Exclaim; 1399a3feee2aSRichard Smith break; 1400a3feee2aSRichard Smith 1401718292f2SDouglas Gregor case tok::string_literal: { 1402d67aea28SRichard Smith if (LToken.hasUDSuffix()) { 1403d67aea28SRichard Smith Diags.Report(LToken.getLocation(), diag::err_invalid_string_udl); 1404d67aea28SRichard Smith HadError = true; 1405d67aea28SRichard Smith goto retry; 1406d67aea28SRichard Smith } 1407d67aea28SRichard Smith 1408718292f2SDouglas Gregor // Parse the string literal. 1409718292f2SDouglas Gregor LangOptions LangOpts; 14109d5583efSCraig Topper StringLiteralParser StringLiteral(LToken, SourceMgr, LangOpts, *Target); 1411718292f2SDouglas Gregor if (StringLiteral.hadError) 1412718292f2SDouglas Gregor goto retry; 1413718292f2SDouglas Gregor 1414718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 1415718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 1416718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 1417718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 1418718292f2SDouglas Gregor Saved[Length] = 0; 1419718292f2SDouglas Gregor 1420718292f2SDouglas Gregor // Form the token. 1421718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 1422718292f2SDouglas Gregor Tok.StringData = Saved; 1423718292f2SDouglas Gregor Tok.StringLength = Length; 1424718292f2SDouglas Gregor break; 1425718292f2SDouglas Gregor } 1426718292f2SDouglas Gregor 1427*040e1266SRichard Smith case tok::numeric_constant: { 1428*040e1266SRichard Smith // We don't support any suffixes or other complications. 1429*040e1266SRichard Smith SmallString<32> SpellingBuffer; 1430*040e1266SRichard Smith SpellingBuffer.resize(LToken.getLength() + 1); 1431*040e1266SRichard Smith const char *Start = SpellingBuffer.data(); 1432*040e1266SRichard Smith unsigned Length = 1433*040e1266SRichard Smith Lexer::getSpelling(LToken, Start, SourceMgr, L.getLangOpts()); 1434*040e1266SRichard Smith uint64_t Value; 1435*040e1266SRichard Smith if (StringRef(Start, Length).getAsInteger(0, Value)) { 1436*040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1437*040e1266SRichard Smith HadError = true; 1438*040e1266SRichard Smith goto retry; 1439*040e1266SRichard Smith } 1440*040e1266SRichard Smith 1441*040e1266SRichard Smith Tok.Kind = MMToken::IntegerLiteral; 1442*040e1266SRichard Smith Tok.IntegerValue = Value; 1443*040e1266SRichard Smith break; 1444*040e1266SRichard Smith } 1445*040e1266SRichard Smith 1446718292f2SDouglas Gregor case tok::comment: 1447718292f2SDouglas Gregor goto retry; 1448718292f2SDouglas Gregor 14498128f332SRichard Smith case tok::hash: 14508128f332SRichard Smith // A module map can be terminated prematurely by 14518128f332SRichard Smith // #pragma clang module contents 14528128f332SRichard Smith // When building the module, we'll treat the rest of the file as the 14538128f332SRichard Smith // contents of the module. 14548128f332SRichard Smith { 14558128f332SRichard Smith auto NextIsIdent = [&](StringRef Str) -> bool { 14568128f332SRichard Smith L.LexFromRawLexer(LToken); 14578128f332SRichard Smith return !LToken.isAtStartOfLine() && LToken.is(tok::raw_identifier) && 14588128f332SRichard Smith LToken.getRawIdentifier() == Str; 14598128f332SRichard Smith }; 14608128f332SRichard Smith if (NextIsIdent("pragma") && NextIsIdent("clang") && 14618128f332SRichard Smith NextIsIdent("module") && NextIsIdent("contents")) { 14628128f332SRichard Smith Tok.Kind = MMToken::EndOfFile; 14638128f332SRichard Smith break; 14648128f332SRichard Smith } 14658128f332SRichard Smith } 14668128f332SRichard Smith LLVM_FALLTHROUGH; 14678128f332SRichard Smith 1468718292f2SDouglas Gregor default: 14698128f332SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_unknown_token); 1470718292f2SDouglas Gregor HadError = true; 1471718292f2SDouglas Gregor goto retry; 1472718292f2SDouglas Gregor } 1473718292f2SDouglas Gregor 1474718292f2SDouglas Gregor return Result; 1475718292f2SDouglas Gregor } 1476718292f2SDouglas Gregor 1477718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 1478718292f2SDouglas Gregor unsigned braceDepth = 0; 1479a686e1b0SDouglas Gregor unsigned squareDepth = 0; 1480718292f2SDouglas Gregor do { 1481718292f2SDouglas Gregor switch (Tok.Kind) { 1482718292f2SDouglas Gregor case MMToken::EndOfFile: 1483718292f2SDouglas Gregor return; 1484718292f2SDouglas Gregor 1485718292f2SDouglas Gregor case MMToken::LBrace: 1486a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1487718292f2SDouglas Gregor return; 1488718292f2SDouglas Gregor 1489718292f2SDouglas Gregor ++braceDepth; 1490718292f2SDouglas Gregor break; 1491718292f2SDouglas Gregor 1492a686e1b0SDouglas Gregor case MMToken::LSquare: 1493a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 1494a686e1b0SDouglas Gregor return; 1495a686e1b0SDouglas Gregor 1496a686e1b0SDouglas Gregor ++squareDepth; 1497a686e1b0SDouglas Gregor break; 1498a686e1b0SDouglas Gregor 1499718292f2SDouglas Gregor case MMToken::RBrace: 1500718292f2SDouglas Gregor if (braceDepth > 0) 1501718292f2SDouglas Gregor --braceDepth; 1502718292f2SDouglas Gregor else if (Tok.is(K)) 1503718292f2SDouglas Gregor return; 1504718292f2SDouglas Gregor break; 1505718292f2SDouglas Gregor 1506a686e1b0SDouglas Gregor case MMToken::RSquare: 1507a686e1b0SDouglas Gregor if (squareDepth > 0) 1508a686e1b0SDouglas Gregor --squareDepth; 1509a686e1b0SDouglas Gregor else if (Tok.is(K)) 1510a686e1b0SDouglas Gregor return; 1511a686e1b0SDouglas Gregor break; 1512a686e1b0SDouglas Gregor 1513718292f2SDouglas Gregor default: 1514a686e1b0SDouglas Gregor if (braceDepth == 0 && squareDepth == 0 && Tok.is(K)) 1515718292f2SDouglas Gregor return; 1516718292f2SDouglas Gregor break; 1517718292f2SDouglas Gregor } 1518718292f2SDouglas Gregor 1519718292f2SDouglas Gregor consumeToken(); 1520718292f2SDouglas Gregor } while (true); 1521718292f2SDouglas Gregor } 1522718292f2SDouglas Gregor 1523e7ab3669SDouglas Gregor /// \brief Parse a module-id. 1524e7ab3669SDouglas Gregor /// 1525e7ab3669SDouglas Gregor /// module-id: 1526e7ab3669SDouglas Gregor /// identifier 1527e7ab3669SDouglas Gregor /// identifier '.' module-id 1528e7ab3669SDouglas Gregor /// 1529e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise. 1530e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) { 1531e7ab3669SDouglas Gregor Id.clear(); 1532e7ab3669SDouglas Gregor do { 15333cd34c76SDaniel Jasper if (Tok.is(MMToken::Identifier) || Tok.is(MMToken::StringLiteral)) { 1534e7ab3669SDouglas Gregor Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation())); 1535e7ab3669SDouglas Gregor consumeToken(); 1536e7ab3669SDouglas Gregor } else { 1537e7ab3669SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 1538e7ab3669SDouglas Gregor return true; 1539e7ab3669SDouglas Gregor } 1540e7ab3669SDouglas Gregor 1541e7ab3669SDouglas Gregor if (!Tok.is(MMToken::Period)) 1542e7ab3669SDouglas Gregor break; 1543e7ab3669SDouglas Gregor 1544e7ab3669SDouglas Gregor consumeToken(); 1545e7ab3669SDouglas Gregor } while (true); 1546e7ab3669SDouglas Gregor 1547e7ab3669SDouglas Gregor return false; 1548e7ab3669SDouglas Gregor } 1549e7ab3669SDouglas Gregor 1550a686e1b0SDouglas Gregor namespace { 1551a686e1b0SDouglas Gregor /// \brief Enumerates the known attributes. 1552a686e1b0SDouglas Gregor enum AttributeKind { 1553a686e1b0SDouglas Gregor /// \brief An unknown attribute. 1554a686e1b0SDouglas Gregor AT_unknown, 1555a686e1b0SDouglas Gregor /// \brief The 'system' attribute. 155635b13eceSDouglas Gregor AT_system, 155777944868SRichard Smith /// \brief The 'extern_c' attribute. 155877944868SRichard Smith AT_extern_c, 155935b13eceSDouglas Gregor /// \brief The 'exhaustive' attribute. 1560ed84df00SBruno Cardoso Lopes AT_exhaustive, 1561ed84df00SBruno Cardoso Lopes /// \brief The 'no_undeclared_includes' attribute. 1562ed84df00SBruno Cardoso Lopes AT_no_undeclared_includes 1563a686e1b0SDouglas Gregor }; 1564ab9db510SAlexander Kornienko } 1565a686e1b0SDouglas Gregor 1566718292f2SDouglas Gregor /// \brief Parse a module declaration. 1567718292f2SDouglas Gregor /// 1568718292f2SDouglas Gregor /// module-declaration: 156997292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 1570a686e1b0SDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt] 1571a686e1b0SDouglas Gregor /// { module-member* } 1572a686e1b0SDouglas Gregor /// 1573718292f2SDouglas Gregor /// module-member: 15741fb5c3a6SDouglas Gregor /// requires-declaration 1575718292f2SDouglas Gregor /// header-declaration 1576e7ab3669SDouglas Gregor /// submodule-declaration 15772b82c2a5SDouglas Gregor /// export-declaration 15786ddfca91SDouglas Gregor /// link-declaration 157973441091SDouglas Gregor /// 158073441091SDouglas Gregor /// submodule-declaration: 158173441091SDouglas Gregor /// module-declaration 158273441091SDouglas Gregor /// inferred-submodule-declaration 1583718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 1584755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 158597292843SDaniel Jasper Tok.is(MMToken::FrameworkKeyword) || Tok.is(MMToken::ExternKeyword)); 158697292843SDaniel Jasper if (Tok.is(MMToken::ExternKeyword)) { 158797292843SDaniel Jasper parseExternModuleDecl(); 158897292843SDaniel Jasper return; 158997292843SDaniel Jasper } 159097292843SDaniel Jasper 1591f2161a70SDouglas Gregor // Parse 'explicit' or 'framework' keyword, if present. 1592e7ab3669SDouglas Gregor SourceLocation ExplicitLoc; 1593718292f2SDouglas Gregor bool Explicit = false; 1594f2161a70SDouglas Gregor bool Framework = false; 1595755b2055SDouglas Gregor 1596f2161a70SDouglas Gregor // Parse 'explicit' keyword, if present. 1597f2161a70SDouglas Gregor if (Tok.is(MMToken::ExplicitKeyword)) { 1598e7ab3669SDouglas Gregor ExplicitLoc = consumeToken(); 1599f2161a70SDouglas Gregor Explicit = true; 1600f2161a70SDouglas Gregor } 1601f2161a70SDouglas Gregor 1602f2161a70SDouglas Gregor // Parse 'framework' keyword, if present. 1603755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 1604755b2055SDouglas Gregor consumeToken(); 1605755b2055SDouglas Gregor Framework = true; 1606755b2055SDouglas Gregor } 1607718292f2SDouglas Gregor 1608718292f2SDouglas Gregor // Parse 'module' keyword. 1609718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 1610d6343c99SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 1611718292f2SDouglas Gregor consumeToken(); 1612718292f2SDouglas Gregor HadError = true; 1613718292f2SDouglas Gregor return; 1614718292f2SDouglas Gregor } 1615718292f2SDouglas Gregor consumeToken(); // 'module' keyword 1616718292f2SDouglas Gregor 161773441091SDouglas Gregor // If we have a wildcard for the module name, this is an inferred submodule. 161873441091SDouglas Gregor // Parse it. 161973441091SDouglas Gregor if (Tok.is(MMToken::Star)) 16209194a91dSDouglas Gregor return parseInferredModuleDecl(Framework, Explicit); 162173441091SDouglas Gregor 1622718292f2SDouglas Gregor // Parse the module name. 1623e7ab3669SDouglas Gregor ModuleId Id; 1624e7ab3669SDouglas Gregor if (parseModuleId(Id)) { 1625718292f2SDouglas Gregor HadError = true; 1626718292f2SDouglas Gregor return; 1627718292f2SDouglas Gregor } 1628e7ab3669SDouglas Gregor 1629e7ab3669SDouglas Gregor if (ActiveModule) { 1630e7ab3669SDouglas Gregor if (Id.size() > 1) { 1631e7ab3669SDouglas Gregor Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id) 1632e7ab3669SDouglas Gregor << SourceRange(Id.front().second, Id.back().second); 1633e7ab3669SDouglas Gregor 1634e7ab3669SDouglas Gregor HadError = true; 1635e7ab3669SDouglas Gregor return; 1636e7ab3669SDouglas Gregor } 1637e7ab3669SDouglas Gregor } else if (Id.size() == 1 && Explicit) { 1638e7ab3669SDouglas Gregor // Top-level modules can't be explicit. 1639e7ab3669SDouglas Gregor Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level); 1640e7ab3669SDouglas Gregor Explicit = false; 1641e7ab3669SDouglas Gregor ExplicitLoc = SourceLocation(); 1642e7ab3669SDouglas Gregor HadError = true; 1643e7ab3669SDouglas Gregor } 1644e7ab3669SDouglas Gregor 1645e7ab3669SDouglas Gregor Module *PreviousActiveModule = ActiveModule; 1646e7ab3669SDouglas Gregor if (Id.size() > 1) { 1647e7ab3669SDouglas Gregor // This module map defines a submodule. Go find the module of which it 1648e7ab3669SDouglas Gregor // is a submodule. 1649d2d442caSCraig Topper ActiveModule = nullptr; 16504b8a9e95SBen Langmuir const Module *TopLevelModule = nullptr; 1651e7ab3669SDouglas Gregor for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) { 1652e7ab3669SDouglas Gregor if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) { 16534b8a9e95SBen Langmuir if (I == 0) 16544b8a9e95SBen Langmuir TopLevelModule = Next; 1655e7ab3669SDouglas Gregor ActiveModule = Next; 1656e7ab3669SDouglas Gregor continue; 1657e7ab3669SDouglas Gregor } 1658e7ab3669SDouglas Gregor 1659e7ab3669SDouglas Gregor if (ActiveModule) { 1660e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified) 16615b5d21eaSRichard Smith << Id[I].first 16625b5d21eaSRichard Smith << ActiveModule->getTopLevelModule()->getFullModuleName(); 1663e7ab3669SDouglas Gregor } else { 1664e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_expected_module_name); 1665e7ab3669SDouglas Gregor } 1666e7ab3669SDouglas Gregor HadError = true; 1667e7ab3669SDouglas Gregor return; 1668e7ab3669SDouglas Gregor } 16694b8a9e95SBen Langmuir 16704b8a9e95SBen Langmuir if (ModuleMapFile != Map.getContainingModuleMapFile(TopLevelModule)) { 16714b8a9e95SBen Langmuir assert(ModuleMapFile != Map.getModuleMapFileForUniquing(TopLevelModule) && 16724b8a9e95SBen Langmuir "submodule defined in same file as 'module *' that allowed its " 16734b8a9e95SBen Langmuir "top-level module"); 16744b8a9e95SBen Langmuir Map.addAdditionalModuleMapFile(TopLevelModule, ModuleMapFile); 16754b8a9e95SBen Langmuir } 1676e7ab3669SDouglas Gregor } 1677e7ab3669SDouglas Gregor 1678e7ab3669SDouglas Gregor StringRef ModuleName = Id.back().first; 1679e7ab3669SDouglas Gregor SourceLocation ModuleNameLoc = Id.back().second; 1680718292f2SDouglas Gregor 1681a686e1b0SDouglas Gregor // Parse the optional attribute list. 16824442605fSBill Wendling Attributes Attrs; 16835d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 16845d29dee0SDavide Italiano return; 16855d29dee0SDavide Italiano 1686a686e1b0SDouglas Gregor 1687718292f2SDouglas Gregor // Parse the opening brace. 1688718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 1689718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 1690718292f2SDouglas Gregor << ModuleName; 1691718292f2SDouglas Gregor HadError = true; 1692718292f2SDouglas Gregor return; 1693718292f2SDouglas Gregor } 1694718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 1695718292f2SDouglas Gregor 1696718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 1697eb90e830SDouglas Gregor if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { 16984a3751ffSRichard Smith // We might see a (re)definition of a module that we already have a 16994a3751ffSRichard Smith // definition for in two cases: 17004a3751ffSRichard Smith // - If we loaded one definition from an AST file and we've just found a 17014a3751ffSRichard Smith // corresponding definition in a module map file, or 17024a3751ffSRichard Smith bool LoadedFromASTFile = Existing->DefinitionLoc.isInvalid(); 17034a3751ffSRichard Smith // - If we're building a (preprocessed) module and we've just loaded the 17044a3751ffSRichard Smith // module map file from which it was created. 17054a3751ffSRichard Smith bool ParsedAsMainInput = 17064a3751ffSRichard Smith Map.LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap && 17074a3751ffSRichard Smith Map.LangOpts.CurrentModule == ModuleName && 17084a3751ffSRichard Smith SourceMgr.getDecomposedLoc(ModuleNameLoc).first != 17094a3751ffSRichard Smith SourceMgr.getDecomposedLoc(Existing->DefinitionLoc).first; 17104a3751ffSRichard Smith if (!ActiveModule && (LoadedFromASTFile || ParsedAsMainInput)) { 1711fcc54a3bSDouglas Gregor // Skip the module definition. 1712fcc54a3bSDouglas Gregor skipUntil(MMToken::RBrace); 1713fcc54a3bSDouglas Gregor if (Tok.is(MMToken::RBrace)) 1714fcc54a3bSDouglas Gregor consumeToken(); 1715fcc54a3bSDouglas Gregor else { 1716fcc54a3bSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 1717fcc54a3bSDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 1718fcc54a3bSDouglas Gregor HadError = true; 1719fcc54a3bSDouglas Gregor } 1720fcc54a3bSDouglas Gregor return; 1721fcc54a3bSDouglas Gregor } 1722fcc54a3bSDouglas Gregor 1723718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 1724718292f2SDouglas Gregor << ModuleName; 1725eb90e830SDouglas Gregor Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition); 1726718292f2SDouglas Gregor 1727718292f2SDouglas Gregor // Skip the module definition. 1728718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 1729718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 1730718292f2SDouglas Gregor consumeToken(); 1731718292f2SDouglas Gregor 1732718292f2SDouglas Gregor HadError = true; 1733718292f2SDouglas Gregor return; 1734718292f2SDouglas Gregor } 1735718292f2SDouglas Gregor 1736718292f2SDouglas Gregor // Start defining this module. 17379d6448b1SBen Langmuir ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework, 17389d6448b1SBen Langmuir Explicit).first; 1739eb90e830SDouglas Gregor ActiveModule->DefinitionLoc = ModuleNameLoc; 1740963c5535SDouglas Gregor if (Attrs.IsSystem || IsSystem) 1741a686e1b0SDouglas Gregor ActiveModule->IsSystem = true; 174277944868SRichard Smith if (Attrs.IsExternC) 174377944868SRichard Smith ActiveModule->IsExternC = true; 1744ed84df00SBruno Cardoso Lopes if (Attrs.NoUndeclaredIncludes || 1745ed84df00SBruno Cardoso Lopes (!ActiveModule->Parent && ModuleName == "Darwin")) 1746ed84df00SBruno Cardoso Lopes ActiveModule->NoUndeclaredIncludes = true; 17473c1a41adSRichard Smith ActiveModule->Directory = Directory; 1748718292f2SDouglas Gregor 17494d867640SGraydon Hoare if (!ActiveModule->Parent) { 17504d867640SGraydon Hoare StringRef MapFileName(ModuleMapFile->getName()); 17514d867640SGraydon Hoare if (MapFileName.endswith("module.private.modulemap") || 17524d867640SGraydon Hoare MapFileName.endswith("module_private.map")) { 17534d867640SGraydon Hoare // Adding a top-level module from a private modulemap is likely a 17544d867640SGraydon Hoare // user error; we check to see if there's another top-level module 17554d867640SGraydon Hoare // defined in the non-private map in the same dir, and if so emit a 17564d867640SGraydon Hoare // warning. 17574d867640SGraydon Hoare for (auto E = Map.module_begin(); E != Map.module_end(); ++E) { 17584d867640SGraydon Hoare auto const *M = E->getValue(); 17594d867640SGraydon Hoare if (!M->Parent && 17604d867640SGraydon Hoare M->Directory == ActiveModule->Directory && 17614d867640SGraydon Hoare M->Name != ActiveModule->Name) { 17624d867640SGraydon Hoare Diags.Report(ActiveModule->DefinitionLoc, 17634d867640SGraydon Hoare diag::warn_mmap_mismatched_top_level_private) 17644d867640SGraydon Hoare << ActiveModule->Name << M->Name; 17654d867640SGraydon Hoare // The pattern we're defending against here is typically due to 17664d867640SGraydon Hoare // a module named FooPrivate which is supposed to be a submodule 17674d867640SGraydon Hoare // called Foo.Private. Emit a fixit in that case. 17684d867640SGraydon Hoare auto D = 17694d867640SGraydon Hoare Diags.Report(ActiveModule->DefinitionLoc, 17704d867640SGraydon Hoare diag::note_mmap_rename_top_level_private_as_submodule); 17714d867640SGraydon Hoare D << ActiveModule->Name << M->Name; 17724d867640SGraydon Hoare StringRef Bad(ActiveModule->Name); 17734d867640SGraydon Hoare if (Bad.consume_back("Private")) { 17744d867640SGraydon Hoare SmallString<128> Fixed = Bad; 17754d867640SGraydon Hoare Fixed.append(".Private"); 17764d867640SGraydon Hoare D << FixItHint::CreateReplacement(ActiveModule->DefinitionLoc, 17774d867640SGraydon Hoare Fixed); 17784d867640SGraydon Hoare } 17794d867640SGraydon Hoare break; 17804d867640SGraydon Hoare } 17814d867640SGraydon Hoare } 17824d867640SGraydon Hoare } 17834d867640SGraydon Hoare } 17844d867640SGraydon Hoare 1785718292f2SDouglas Gregor bool Done = false; 1786718292f2SDouglas Gregor do { 1787718292f2SDouglas Gregor switch (Tok.Kind) { 1788718292f2SDouglas Gregor case MMToken::EndOfFile: 1789718292f2SDouglas Gregor case MMToken::RBrace: 1790718292f2SDouglas Gregor Done = true; 1791718292f2SDouglas Gregor break; 1792718292f2SDouglas Gregor 179335b13eceSDouglas Gregor case MMToken::ConfigMacros: 179435b13eceSDouglas Gregor parseConfigMacros(); 179535b13eceSDouglas Gregor break; 179635b13eceSDouglas Gregor 1797fb912657SDouglas Gregor case MMToken::Conflict: 1798fb912657SDouglas Gregor parseConflict(); 1799fb912657SDouglas Gregor break; 1800fb912657SDouglas Gregor 1801718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 180297292843SDaniel Jasper case MMToken::ExternKeyword: 1803f2161a70SDouglas Gregor case MMToken::FrameworkKeyword: 1804718292f2SDouglas Gregor case MMToken::ModuleKeyword: 1805718292f2SDouglas Gregor parseModuleDecl(); 1806718292f2SDouglas Gregor break; 1807718292f2SDouglas Gregor 18082b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 18092b82c2a5SDouglas Gregor parseExportDecl(); 18102b82c2a5SDouglas Gregor break; 18112b82c2a5SDouglas Gregor 1812ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 1813ba7f2f71SDaniel Jasper parseUseDecl(); 1814ba7f2f71SDaniel Jasper break; 1815ba7f2f71SDaniel Jasper 18161fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 18171fb5c3a6SDouglas Gregor parseRequiresDecl(); 18181fb5c3a6SDouglas Gregor break; 18191fb5c3a6SDouglas Gregor 1820202210b3SRichard Smith case MMToken::TextualKeyword: 1821202210b3SRichard Smith parseHeaderDecl(MMToken::TextualKeyword, consumeToken()); 1822306d8920SRichard Smith break; 1823306d8920SRichard Smith 1824524e33e1SDouglas Gregor case MMToken::UmbrellaKeyword: { 1825524e33e1SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 1826524e33e1SDouglas Gregor if (Tok.is(MMToken::HeaderKeyword)) 1827b53e5483SLawrence Crowl parseHeaderDecl(MMToken::UmbrellaKeyword, UmbrellaLoc); 1828524e33e1SDouglas Gregor else 1829524e33e1SDouglas Gregor parseUmbrellaDirDecl(UmbrellaLoc); 1830718292f2SDouglas Gregor break; 1831524e33e1SDouglas Gregor } 1832718292f2SDouglas Gregor 1833202210b3SRichard Smith case MMToken::ExcludeKeyword: 1834202210b3SRichard Smith parseHeaderDecl(MMToken::ExcludeKeyword, consumeToken()); 183559527666SDouglas Gregor break; 183659527666SDouglas Gregor 1837202210b3SRichard Smith case MMToken::PrivateKeyword: 1838202210b3SRichard Smith parseHeaderDecl(MMToken::PrivateKeyword, consumeToken()); 1839b53e5483SLawrence Crowl break; 1840b53e5483SLawrence Crowl 1841322f633cSDouglas Gregor case MMToken::HeaderKeyword: 1842202210b3SRichard Smith parseHeaderDecl(MMToken::HeaderKeyword, consumeToken()); 1843718292f2SDouglas Gregor break; 1844718292f2SDouglas Gregor 18456ddfca91SDouglas Gregor case MMToken::LinkKeyword: 18466ddfca91SDouglas Gregor parseLinkDecl(); 18476ddfca91SDouglas Gregor break; 18486ddfca91SDouglas Gregor 1849718292f2SDouglas Gregor default: 1850718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 1851718292f2SDouglas Gregor consumeToken(); 1852718292f2SDouglas Gregor break; 1853718292f2SDouglas Gregor } 1854718292f2SDouglas Gregor } while (!Done); 1855718292f2SDouglas Gregor 1856718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 1857718292f2SDouglas Gregor consumeToken(); 1858718292f2SDouglas Gregor else { 1859718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 1860718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 1861718292f2SDouglas Gregor HadError = true; 1862718292f2SDouglas Gregor } 1863718292f2SDouglas Gregor 186411dfe6feSDouglas Gregor // If the active module is a top-level framework, and there are no link 186511dfe6feSDouglas Gregor // libraries, automatically link against the framework. 186611dfe6feSDouglas Gregor if (ActiveModule->IsFramework && !ActiveModule->isSubFramework() && 186711dfe6feSDouglas Gregor ActiveModule->LinkLibraries.empty()) { 186811dfe6feSDouglas Gregor inferFrameworkLink(ActiveModule, Directory, SourceMgr.getFileManager()); 186911dfe6feSDouglas Gregor } 187011dfe6feSDouglas Gregor 1871ec8c9752SBen Langmuir // If the module meets all requirements but is still unavailable, mark the 1872ec8c9752SBen Langmuir // whole tree as unavailable to prevent it from building. 1873ec8c9752SBen Langmuir if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement && 1874ec8c9752SBen Langmuir ActiveModule->Parent) { 1875ec8c9752SBen Langmuir ActiveModule->getTopLevelModule()->markUnavailable(); 1876ec8c9752SBen Langmuir ActiveModule->getTopLevelModule()->MissingHeaders.append( 1877ec8c9752SBen Langmuir ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end()); 1878ec8c9752SBen Langmuir } 1879ec8c9752SBen Langmuir 1880e7ab3669SDouglas Gregor // We're done parsing this module. Pop back to the previous module. 1881e7ab3669SDouglas Gregor ActiveModule = PreviousActiveModule; 1882718292f2SDouglas Gregor } 1883718292f2SDouglas Gregor 188497292843SDaniel Jasper /// \brief Parse an extern module declaration. 188597292843SDaniel Jasper /// 188697292843SDaniel Jasper /// extern module-declaration: 188797292843SDaniel Jasper /// 'extern' 'module' module-id string-literal 188897292843SDaniel Jasper void ModuleMapParser::parseExternModuleDecl() { 188997292843SDaniel Jasper assert(Tok.is(MMToken::ExternKeyword)); 1890ae6df27eSRichard Smith SourceLocation ExternLoc = consumeToken(); // 'extern' keyword 189197292843SDaniel Jasper 189297292843SDaniel Jasper // Parse 'module' keyword. 189397292843SDaniel Jasper if (!Tok.is(MMToken::ModuleKeyword)) { 189497292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 189597292843SDaniel Jasper consumeToken(); 189697292843SDaniel Jasper HadError = true; 189797292843SDaniel Jasper return; 189897292843SDaniel Jasper } 189997292843SDaniel Jasper consumeToken(); // 'module' keyword 190097292843SDaniel Jasper 190197292843SDaniel Jasper // Parse the module name. 190297292843SDaniel Jasper ModuleId Id; 190397292843SDaniel Jasper if (parseModuleId(Id)) { 190497292843SDaniel Jasper HadError = true; 190597292843SDaniel Jasper return; 190697292843SDaniel Jasper } 190797292843SDaniel Jasper 190897292843SDaniel Jasper // Parse the referenced module map file name. 190997292843SDaniel Jasper if (!Tok.is(MMToken::StringLiteral)) { 191097292843SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_expected_mmap_file); 191197292843SDaniel Jasper HadError = true; 191297292843SDaniel Jasper return; 191397292843SDaniel Jasper } 191497292843SDaniel Jasper std::string FileName = Tok.getString(); 191597292843SDaniel Jasper consumeToken(); // filename 191697292843SDaniel Jasper 191797292843SDaniel Jasper StringRef FileNameRef = FileName; 191897292843SDaniel Jasper SmallString<128> ModuleMapFileName; 191997292843SDaniel Jasper if (llvm::sys::path::is_relative(FileNameRef)) { 192097292843SDaniel Jasper ModuleMapFileName += Directory->getName(); 192197292843SDaniel Jasper llvm::sys::path::append(ModuleMapFileName, FileName); 192292e1b62dSYaron Keren FileNameRef = ModuleMapFileName; 192397292843SDaniel Jasper } 192497292843SDaniel Jasper if (const FileEntry *File = SourceMgr.getFileManager().getFile(FileNameRef)) 19259acb99e3SRichard Smith Map.parseModuleMapFile( 19269acb99e3SRichard Smith File, /*IsSystem=*/false, 19279acb99e3SRichard Smith Map.HeaderInfo.getHeaderSearchOpts().ModuleMapFileHomeIsCwd 19289acb99e3SRichard Smith ? Directory 19298128f332SRichard Smith : File->getDir(), 19308128f332SRichard Smith FileID(), nullptr, ExternLoc); 193197292843SDaniel Jasper } 193297292843SDaniel Jasper 19337ff29148SBen Langmuir /// Whether to add the requirement \p Feature to the module \p M. 19347ff29148SBen Langmuir /// 19357ff29148SBen Langmuir /// This preserves backwards compatibility for two hacks in the Darwin system 19367ff29148SBen Langmuir /// module map files: 19377ff29148SBen Langmuir /// 19387ff29148SBen Langmuir /// 1. The use of 'requires excluded' to make headers non-modular, which 19397ff29148SBen Langmuir /// should really be mapped to 'textual' now that we have this feature. We 19407ff29148SBen Langmuir /// drop the 'excluded' requirement, and set \p IsRequiresExcludedHack to 19417ff29148SBen Langmuir /// true. Later, this bit will be used to map all the headers inside this 19427ff29148SBen Langmuir /// module to 'textual'. 19437ff29148SBen Langmuir /// 19447ff29148SBen Langmuir /// This affects Darwin.C.excluded (for assert.h) and Tcl.Private. 19457ff29148SBen Langmuir /// 19467ff29148SBen Langmuir /// 2. Removes a bogus cplusplus requirement from IOKit.avc. This requirement 19477ff29148SBen Langmuir /// was never correct and causes issues now that we check it, so drop it. 19487ff29148SBen Langmuir static bool shouldAddRequirement(Module *M, StringRef Feature, 19497ff29148SBen Langmuir bool &IsRequiresExcludedHack) { 19508013e81dSBenjamin Kramer if (Feature == "excluded" && 19518013e81dSBenjamin Kramer (M->fullModuleNameIs({"Darwin", "C", "excluded"}) || 19528013e81dSBenjamin Kramer M->fullModuleNameIs({"Tcl", "Private"}))) { 19537ff29148SBen Langmuir IsRequiresExcludedHack = true; 19547ff29148SBen Langmuir return false; 19558013e81dSBenjamin Kramer } else if (Feature == "cplusplus" && M->fullModuleNameIs({"IOKit", "avc"})) { 19567ff29148SBen Langmuir return false; 19577ff29148SBen Langmuir } 19587ff29148SBen Langmuir 19597ff29148SBen Langmuir return true; 19607ff29148SBen Langmuir } 19617ff29148SBen Langmuir 19621fb5c3a6SDouglas Gregor /// \brief Parse a requires declaration. 19631fb5c3a6SDouglas Gregor /// 19641fb5c3a6SDouglas Gregor /// requires-declaration: 19651fb5c3a6SDouglas Gregor /// 'requires' feature-list 19661fb5c3a6SDouglas Gregor /// 19671fb5c3a6SDouglas Gregor /// feature-list: 1968a3feee2aSRichard Smith /// feature ',' feature-list 1969a3feee2aSRichard Smith /// feature 1970a3feee2aSRichard Smith /// 1971a3feee2aSRichard Smith /// feature: 1972a3feee2aSRichard Smith /// '!'[opt] identifier 19731fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() { 19741fb5c3a6SDouglas Gregor assert(Tok.is(MMToken::RequiresKeyword)); 19751fb5c3a6SDouglas Gregor 19761fb5c3a6SDouglas Gregor // Parse 'requires' keyword. 19771fb5c3a6SDouglas Gregor consumeToken(); 19781fb5c3a6SDouglas Gregor 19791fb5c3a6SDouglas Gregor // Parse the feature-list. 19801fb5c3a6SDouglas Gregor do { 1981a3feee2aSRichard Smith bool RequiredState = true; 1982a3feee2aSRichard Smith if (Tok.is(MMToken::Exclaim)) { 1983a3feee2aSRichard Smith RequiredState = false; 1984a3feee2aSRichard Smith consumeToken(); 1985a3feee2aSRichard Smith } 1986a3feee2aSRichard Smith 19871fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 19881fb5c3a6SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature); 19891fb5c3a6SDouglas Gregor HadError = true; 19901fb5c3a6SDouglas Gregor return; 19911fb5c3a6SDouglas Gregor } 19921fb5c3a6SDouglas Gregor 19931fb5c3a6SDouglas Gregor // Consume the feature name. 19941fb5c3a6SDouglas Gregor std::string Feature = Tok.getString(); 19951fb5c3a6SDouglas Gregor consumeToken(); 19961fb5c3a6SDouglas Gregor 19977ff29148SBen Langmuir bool IsRequiresExcludedHack = false; 19987ff29148SBen Langmuir bool ShouldAddRequirement = 19997ff29148SBen Langmuir shouldAddRequirement(ActiveModule, Feature, IsRequiresExcludedHack); 20007ff29148SBen Langmuir 20017ff29148SBen Langmuir if (IsRequiresExcludedHack) 20027ff29148SBen Langmuir UsesRequiresExcludedHack.insert(ActiveModule); 20037ff29148SBen Langmuir 20047ff29148SBen Langmuir if (ShouldAddRequirement) { 20051fb5c3a6SDouglas Gregor // Add this feature. 20067ff29148SBen Langmuir ActiveModule->addRequirement(Feature, RequiredState, Map.LangOpts, 20077ff29148SBen Langmuir *Map.Target); 20087ff29148SBen Langmuir } 20091fb5c3a6SDouglas Gregor 20101fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Comma)) 20111fb5c3a6SDouglas Gregor break; 20121fb5c3a6SDouglas Gregor 20131fb5c3a6SDouglas Gregor // Consume the comma. 20141fb5c3a6SDouglas Gregor consumeToken(); 20151fb5c3a6SDouglas Gregor } while (true); 20161fb5c3a6SDouglas Gregor } 20171fb5c3a6SDouglas Gregor 2018718292f2SDouglas Gregor /// \brief Parse a header declaration. 2019718292f2SDouglas Gregor /// 2020718292f2SDouglas Gregor /// header-declaration: 2021306d8920SRichard Smith /// 'textual'[opt] 'header' string-literal 2022202210b3SRichard Smith /// 'private' 'textual'[opt] 'header' string-literal 2023202210b3SRichard Smith /// 'exclude' 'header' string-literal 2024202210b3SRichard Smith /// 'umbrella' 'header' string-literal 2025306d8920SRichard Smith /// 2026306d8920SRichard Smith /// FIXME: Support 'private textual header'. 2027b53e5483SLawrence Crowl void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, 2028b53e5483SLawrence Crowl SourceLocation LeadingLoc) { 2029202210b3SRichard Smith // We've already consumed the first token. 2030202210b3SRichard Smith ModuleMap::ModuleHeaderRole Role = ModuleMap::NormalHeader; 2031202210b3SRichard Smith if (LeadingToken == MMToken::PrivateKeyword) { 2032202210b3SRichard Smith Role = ModuleMap::PrivateHeader; 2033202210b3SRichard Smith // 'private' may optionally be followed by 'textual'. 2034202210b3SRichard Smith if (Tok.is(MMToken::TextualKeyword)) { 2035202210b3SRichard Smith LeadingToken = Tok.Kind; 20361871ed3dSBenjamin Kramer consumeToken(); 2037202210b3SRichard Smith } 2038202210b3SRichard Smith } 20397ff29148SBen Langmuir 2040202210b3SRichard Smith if (LeadingToken == MMToken::TextualKeyword) 2041202210b3SRichard Smith Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 2042202210b3SRichard Smith 20437ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 20447ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 20457ff29148SBen Langmuir // Module::UsesRequiresExcludedHack). 20467ff29148SBen Langmuir Role = ModuleMap::ModuleHeaderRole(Role | ModuleMap::TextualHeader); 20477ff29148SBen Langmuir } 20487ff29148SBen Langmuir 2049202210b3SRichard Smith if (LeadingToken != MMToken::HeaderKeyword) { 2050202210b3SRichard Smith if (!Tok.is(MMToken::HeaderKeyword)) { 2051202210b3SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2052202210b3SRichard Smith << (LeadingToken == MMToken::PrivateKeyword ? "private" : 2053202210b3SRichard Smith LeadingToken == MMToken::ExcludeKeyword ? "exclude" : 2054202210b3SRichard Smith LeadingToken == MMToken::TextualKeyword ? "textual" : "umbrella"); 2055202210b3SRichard Smith return; 2056202210b3SRichard Smith } 2057202210b3SRichard Smith consumeToken(); 2058202210b3SRichard Smith } 2059718292f2SDouglas Gregor 2060718292f2SDouglas Gregor // Parse the header name. 2061718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2062718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2063718292f2SDouglas Gregor << "header"; 2064718292f2SDouglas Gregor HadError = true; 2065718292f2SDouglas Gregor return; 2066718292f2SDouglas Gregor } 20673c1a41adSRichard Smith Module::UnresolvedHeaderDirective Header; 20680761a8a0SDaniel Jasper Header.FileName = Tok.getString(); 20690761a8a0SDaniel Jasper Header.FileNameLoc = consumeToken(); 20701d60987fSRichard Smith Header.IsUmbrella = LeadingToken == MMToken::UmbrellaKeyword; 2071*040e1266SRichard Smith Header.Kind = 2072*040e1266SRichard Smith (LeadingToken == MMToken::ExcludeKeyword ? Module::HK_Excluded 2073*040e1266SRichard Smith : Map.headerRoleToKind(Role)); 2074718292f2SDouglas Gregor 2075524e33e1SDouglas Gregor // Check whether we already have an umbrella. 20761d60987fSRichard Smith if (Header.IsUmbrella && ActiveModule->Umbrella) { 20770761a8a0SDaniel Jasper Diags.Report(Header.FileNameLoc, diag::err_mmap_umbrella_clash) 2078524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2079322f633cSDouglas Gregor HadError = true; 2080322f633cSDouglas Gregor return; 2081322f633cSDouglas Gregor } 2082322f633cSDouglas Gregor 2083*040e1266SRichard Smith // If we were given stat information, parse it so we can skip looking for 2084*040e1266SRichard Smith // the file. 2085*040e1266SRichard Smith if (Tok.is(MMToken::LBrace)) { 2086*040e1266SRichard Smith SourceLocation LBraceLoc = consumeToken(); 20873ec6663bSDouglas Gregor 2088*040e1266SRichard Smith while (!Tok.is(MMToken::RBrace) && !Tok.is(MMToken::EndOfFile)) { 2089*040e1266SRichard Smith enum Attribute { Size, ModTime, Unknown }; 2090*040e1266SRichard Smith StringRef Str = Tok.getString(); 2091*040e1266SRichard Smith SourceLocation Loc = consumeToken(); 2092*040e1266SRichard Smith switch (llvm::StringSwitch<Attribute>(Str) 2093*040e1266SRichard Smith .Case("size", Size) 2094*040e1266SRichard Smith .Case("mtime", ModTime) 2095*040e1266SRichard Smith .Default(Unknown)) { 2096*040e1266SRichard Smith case Size: 2097*040e1266SRichard Smith if (Header.Size) 2098*040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2099*040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2100*040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2101*040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2102*040e1266SRichard Smith skipUntil(MMToken::RBrace); 2103*040e1266SRichard Smith break; 2104*040e1266SRichard Smith } 2105*040e1266SRichard Smith Header.Size = Tok.getInteger(); 2106*040e1266SRichard Smith consumeToken(); 2107*040e1266SRichard Smith break; 2108*040e1266SRichard Smith 2109*040e1266SRichard Smith case ModTime: 2110*040e1266SRichard Smith if (Header.ModTime) 2111*040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_duplicate_header_attribute) << Str; 2112*040e1266SRichard Smith if (!Tok.is(MMToken::IntegerLiteral)) { 2113*040e1266SRichard Smith Diags.Report(Tok.getLocation(), 2114*040e1266SRichard Smith diag::err_mmap_invalid_header_attribute_value) << Str; 2115*040e1266SRichard Smith skipUntil(MMToken::RBrace); 2116*040e1266SRichard Smith break; 2117*040e1266SRichard Smith } 2118*040e1266SRichard Smith Header.ModTime = Tok.getInteger(); 2119*040e1266SRichard Smith consumeToken(); 2120*040e1266SRichard Smith break; 2121*040e1266SRichard Smith 2122*040e1266SRichard Smith case Unknown: 2123*040e1266SRichard Smith Diags.Report(Loc, diag::err_mmap_expected_header_attribute); 2124*040e1266SRichard Smith skipUntil(MMToken::RBrace); 2125*040e1266SRichard Smith break; 2126*040e1266SRichard Smith } 21273ec6663bSDouglas Gregor } 21285257fc63SDouglas Gregor 2129*040e1266SRichard Smith if (Tok.is(MMToken::RBrace)) 2130*040e1266SRichard Smith consumeToken(); 2131*040e1266SRichard Smith else { 2132*040e1266SRichard Smith Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 2133*040e1266SRichard Smith Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 2134322f633cSDouglas Gregor HadError = true; 2135322f633cSDouglas Gregor } 21360101b540SHans Wennborg } 213725d50758SRichard Smith 2138*040e1266SRichard Smith Map.addUnresolvedHeader(ActiveModule, std::move(Header)); 2139718292f2SDouglas Gregor } 2140718292f2SDouglas Gregor 214141f81994SBen Langmuir static int compareModuleHeaders(const Module::Header *A, 214241f81994SBen Langmuir const Module::Header *B) { 214341f81994SBen Langmuir return A->NameAsWritten.compare(B->NameAsWritten); 214441f81994SBen Langmuir } 214541f81994SBen Langmuir 2146524e33e1SDouglas Gregor /// \brief Parse an umbrella directory declaration. 2147524e33e1SDouglas Gregor /// 2148524e33e1SDouglas Gregor /// umbrella-dir-declaration: 2149524e33e1SDouglas Gregor /// umbrella string-literal 2150524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { 2151524e33e1SDouglas Gregor // Parse the directory name. 2152524e33e1SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2153524e33e1SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 2154524e33e1SDouglas Gregor << "umbrella"; 2155524e33e1SDouglas Gregor HadError = true; 2156524e33e1SDouglas Gregor return; 2157524e33e1SDouglas Gregor } 2158524e33e1SDouglas Gregor 2159524e33e1SDouglas Gregor std::string DirName = Tok.getString(); 2160524e33e1SDouglas Gregor SourceLocation DirNameLoc = consumeToken(); 2161524e33e1SDouglas Gregor 2162524e33e1SDouglas Gregor // Check whether we already have an umbrella. 2163524e33e1SDouglas Gregor if (ActiveModule->Umbrella) { 2164524e33e1SDouglas Gregor Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash) 2165524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 2166524e33e1SDouglas Gregor HadError = true; 2167524e33e1SDouglas Gregor return; 2168524e33e1SDouglas Gregor } 2169524e33e1SDouglas Gregor 2170524e33e1SDouglas Gregor // Look for this file. 2171d2d442caSCraig Topper const DirectoryEntry *Dir = nullptr; 2172524e33e1SDouglas Gregor if (llvm::sys::path::is_absolute(DirName)) 2173524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(DirName); 2174524e33e1SDouglas Gregor else { 21752c1dd271SDylan Noblesmith SmallString<128> PathName; 2176524e33e1SDouglas Gregor PathName = Directory->getName(); 2177524e33e1SDouglas Gregor llvm::sys::path::append(PathName, DirName); 2178524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(PathName); 2179524e33e1SDouglas Gregor } 2180524e33e1SDouglas Gregor 2181524e33e1SDouglas Gregor if (!Dir) { 2182a0320b97SVassil Vassilev Diags.Report(DirNameLoc, diag::warn_mmap_umbrella_dir_not_found) 2183524e33e1SDouglas Gregor << DirName; 2184524e33e1SDouglas Gregor return; 2185524e33e1SDouglas Gregor } 2186524e33e1SDouglas Gregor 21877ff29148SBen Langmuir if (UsesRequiresExcludedHack.count(ActiveModule)) { 21887ff29148SBen Langmuir // Mark this header 'textual' (see doc comment for 21897ff29148SBen Langmuir // ModuleMapParser::UsesRequiresExcludedHack). Although iterating over the 21907ff29148SBen Langmuir // directory is relatively expensive, in practice this only applies to the 21917ff29148SBen Langmuir // uncommonly used Tcl module on Darwin platforms. 21927ff29148SBen Langmuir std::error_code EC; 21937ff29148SBen Langmuir SmallVector<Module::Header, 6> Headers; 2194b171a59bSBruno Cardoso Lopes vfs::FileSystem &FS = *SourceMgr.getFileManager().getVirtualFileSystem(); 2195b171a59bSBruno Cardoso Lopes for (vfs::recursive_directory_iterator I(FS, Dir->getName(), EC), E; 21967ff29148SBen Langmuir I != E && !EC; I.increment(EC)) { 2197b171a59bSBruno Cardoso Lopes if (const FileEntry *FE = 2198b171a59bSBruno Cardoso Lopes SourceMgr.getFileManager().getFile(I->getName())) { 21997ff29148SBen Langmuir 2200b171a59bSBruno Cardoso Lopes Module::Header Header = {I->getName(), FE}; 22017ff29148SBen Langmuir Headers.push_back(std::move(Header)); 22027ff29148SBen Langmuir } 22037ff29148SBen Langmuir } 22047ff29148SBen Langmuir 22057ff29148SBen Langmuir // Sort header paths so that the pcm doesn't depend on iteration order. 220641f81994SBen Langmuir llvm::array_pod_sort(Headers.begin(), Headers.end(), compareModuleHeaders); 220741f81994SBen Langmuir 22087ff29148SBen Langmuir for (auto &Header : Headers) 22097ff29148SBen Langmuir Map.addHeader(ActiveModule, std::move(Header), ModuleMap::TextualHeader); 22107ff29148SBen Langmuir return; 22117ff29148SBen Langmuir } 22127ff29148SBen Langmuir 2213524e33e1SDouglas Gregor if (Module *OwningModule = Map.UmbrellaDirs[Dir]) { 2214524e33e1SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 2215524e33e1SDouglas Gregor << OwningModule->getFullModuleName(); 2216524e33e1SDouglas Gregor HadError = true; 2217524e33e1SDouglas Gregor return; 2218524e33e1SDouglas Gregor } 2219524e33e1SDouglas Gregor 2220524e33e1SDouglas Gregor // Record this umbrella directory. 22212b63d15fSRichard Smith Map.setUmbrellaDir(ActiveModule, Dir, DirName); 2222524e33e1SDouglas Gregor } 2223524e33e1SDouglas Gregor 22242b82c2a5SDouglas Gregor /// \brief Parse a module export declaration. 22252b82c2a5SDouglas Gregor /// 22262b82c2a5SDouglas Gregor /// export-declaration: 22272b82c2a5SDouglas Gregor /// 'export' wildcard-module-id 22282b82c2a5SDouglas Gregor /// 22292b82c2a5SDouglas Gregor /// wildcard-module-id: 22302b82c2a5SDouglas Gregor /// identifier 22312b82c2a5SDouglas Gregor /// '*' 22322b82c2a5SDouglas Gregor /// identifier '.' wildcard-module-id 22332b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() { 22342b82c2a5SDouglas Gregor assert(Tok.is(MMToken::ExportKeyword)); 22352b82c2a5SDouglas Gregor SourceLocation ExportLoc = consumeToken(); 22362b82c2a5SDouglas Gregor 22372b82c2a5SDouglas Gregor // Parse the module-id with an optional wildcard at the end. 22382b82c2a5SDouglas Gregor ModuleId ParsedModuleId; 22392b82c2a5SDouglas Gregor bool Wildcard = false; 22402b82c2a5SDouglas Gregor do { 2241306d8920SRichard Smith // FIXME: Support string-literal module names here. 22422b82c2a5SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 22432b82c2a5SDouglas Gregor ParsedModuleId.push_back(std::make_pair(Tok.getString(), 22442b82c2a5SDouglas Gregor Tok.getLocation())); 22452b82c2a5SDouglas Gregor consumeToken(); 22462b82c2a5SDouglas Gregor 22472b82c2a5SDouglas Gregor if (Tok.is(MMToken::Period)) { 22482b82c2a5SDouglas Gregor consumeToken(); 22492b82c2a5SDouglas Gregor continue; 22502b82c2a5SDouglas Gregor } 22512b82c2a5SDouglas Gregor 22522b82c2a5SDouglas Gregor break; 22532b82c2a5SDouglas Gregor } 22542b82c2a5SDouglas Gregor 22552b82c2a5SDouglas Gregor if(Tok.is(MMToken::Star)) { 22562b82c2a5SDouglas Gregor Wildcard = true; 2257f5eedd05SDouglas Gregor consumeToken(); 22582b82c2a5SDouglas Gregor break; 22592b82c2a5SDouglas Gregor } 22602b82c2a5SDouglas Gregor 2261ba7f2f71SDaniel Jasper Diags.Report(Tok.getLocation(), diag::err_mmap_module_id); 22622b82c2a5SDouglas Gregor HadError = true; 22632b82c2a5SDouglas Gregor return; 22642b82c2a5SDouglas Gregor } while (true); 22652b82c2a5SDouglas Gregor 22662b82c2a5SDouglas Gregor Module::UnresolvedExportDecl Unresolved = { 22672b82c2a5SDouglas Gregor ExportLoc, ParsedModuleId, Wildcard 22682b82c2a5SDouglas Gregor }; 22692b82c2a5SDouglas Gregor ActiveModule->UnresolvedExports.push_back(Unresolved); 22702b82c2a5SDouglas Gregor } 22712b82c2a5SDouglas Gregor 22728f4d3ff1SRichard Smith /// \brief Parse a module use declaration. 2273ba7f2f71SDaniel Jasper /// 22748f4d3ff1SRichard Smith /// use-declaration: 22758f4d3ff1SRichard Smith /// 'use' wildcard-module-id 2276ba7f2f71SDaniel Jasper void ModuleMapParser::parseUseDecl() { 2277ba7f2f71SDaniel Jasper assert(Tok.is(MMToken::UseKeyword)); 22788f4d3ff1SRichard Smith auto KWLoc = consumeToken(); 2279ba7f2f71SDaniel Jasper // Parse the module-id. 2280ba7f2f71SDaniel Jasper ModuleId ParsedModuleId; 22813cd34c76SDaniel Jasper parseModuleId(ParsedModuleId); 2282ba7f2f71SDaniel Jasper 22838f4d3ff1SRichard Smith if (ActiveModule->Parent) 22848f4d3ff1SRichard Smith Diags.Report(KWLoc, diag::err_mmap_use_decl_submodule); 22858f4d3ff1SRichard Smith else 2286ba7f2f71SDaniel Jasper ActiveModule->UnresolvedDirectUses.push_back(ParsedModuleId); 2287ba7f2f71SDaniel Jasper } 2288ba7f2f71SDaniel Jasper 22896ddfca91SDouglas Gregor /// \brief Parse a link declaration. 22906ddfca91SDouglas Gregor /// 22916ddfca91SDouglas Gregor /// module-declaration: 22926ddfca91SDouglas Gregor /// 'link' 'framework'[opt] string-literal 22936ddfca91SDouglas Gregor void ModuleMapParser::parseLinkDecl() { 22946ddfca91SDouglas Gregor assert(Tok.is(MMToken::LinkKeyword)); 22956ddfca91SDouglas Gregor SourceLocation LinkLoc = consumeToken(); 22966ddfca91SDouglas Gregor 22976ddfca91SDouglas Gregor // Parse the optional 'framework' keyword. 22986ddfca91SDouglas Gregor bool IsFramework = false; 22996ddfca91SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 23006ddfca91SDouglas Gregor consumeToken(); 23016ddfca91SDouglas Gregor IsFramework = true; 23026ddfca91SDouglas Gregor } 23036ddfca91SDouglas Gregor 23046ddfca91SDouglas Gregor // Parse the library name 23056ddfca91SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 23066ddfca91SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_library_name) 23076ddfca91SDouglas Gregor << IsFramework << SourceRange(LinkLoc); 23086ddfca91SDouglas Gregor HadError = true; 23096ddfca91SDouglas Gregor return; 23106ddfca91SDouglas Gregor } 23116ddfca91SDouglas Gregor 23126ddfca91SDouglas Gregor std::string LibraryName = Tok.getString(); 23136ddfca91SDouglas Gregor consumeToken(); 23146ddfca91SDouglas Gregor ActiveModule->LinkLibraries.push_back(Module::LinkLibrary(LibraryName, 23156ddfca91SDouglas Gregor IsFramework)); 23166ddfca91SDouglas Gregor } 23176ddfca91SDouglas Gregor 231835b13eceSDouglas Gregor /// \brief Parse a configuration macro declaration. 231935b13eceSDouglas Gregor /// 232035b13eceSDouglas Gregor /// module-declaration: 232135b13eceSDouglas Gregor /// 'config_macros' attributes[opt] config-macro-list? 232235b13eceSDouglas Gregor /// 232335b13eceSDouglas Gregor /// config-macro-list: 232435b13eceSDouglas Gregor /// identifier (',' identifier)? 232535b13eceSDouglas Gregor void ModuleMapParser::parseConfigMacros() { 232635b13eceSDouglas Gregor assert(Tok.is(MMToken::ConfigMacros)); 232735b13eceSDouglas Gregor SourceLocation ConfigMacrosLoc = consumeToken(); 232835b13eceSDouglas Gregor 232935b13eceSDouglas Gregor // Only top-level modules can have configuration macros. 233035b13eceSDouglas Gregor if (ActiveModule->Parent) { 233135b13eceSDouglas Gregor Diags.Report(ConfigMacrosLoc, diag::err_mmap_config_macro_submodule); 233235b13eceSDouglas Gregor } 233335b13eceSDouglas Gregor 233435b13eceSDouglas Gregor // Parse the optional attributes. 233535b13eceSDouglas Gregor Attributes Attrs; 23365d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 23375d29dee0SDavide Italiano return; 23385d29dee0SDavide Italiano 233935b13eceSDouglas Gregor if (Attrs.IsExhaustive && !ActiveModule->Parent) { 234035b13eceSDouglas Gregor ActiveModule->ConfigMacrosExhaustive = true; 234135b13eceSDouglas Gregor } 234235b13eceSDouglas Gregor 234335b13eceSDouglas Gregor // If we don't have an identifier, we're done. 2344306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 234535b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) 234635b13eceSDouglas Gregor return; 234735b13eceSDouglas Gregor 234835b13eceSDouglas Gregor // Consume the first identifier. 234935b13eceSDouglas Gregor if (!ActiveModule->Parent) { 235035b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 235135b13eceSDouglas Gregor } 235235b13eceSDouglas Gregor consumeToken(); 235335b13eceSDouglas Gregor 235435b13eceSDouglas Gregor do { 235535b13eceSDouglas Gregor // If there's a comma, consume it. 235635b13eceSDouglas Gregor if (!Tok.is(MMToken::Comma)) 235735b13eceSDouglas Gregor break; 235835b13eceSDouglas Gregor consumeToken(); 235935b13eceSDouglas Gregor 236035b13eceSDouglas Gregor // We expect to see a macro name here. 2361306d8920SRichard Smith // FIXME: Support macros with the same name as a keyword here. 236235b13eceSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 236335b13eceSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_config_macro); 236435b13eceSDouglas Gregor break; 236535b13eceSDouglas Gregor } 236635b13eceSDouglas Gregor 236735b13eceSDouglas Gregor // Consume the macro name. 236835b13eceSDouglas Gregor if (!ActiveModule->Parent) { 236935b13eceSDouglas Gregor ActiveModule->ConfigMacros.push_back(Tok.getString().str()); 237035b13eceSDouglas Gregor } 237135b13eceSDouglas Gregor consumeToken(); 237235b13eceSDouglas Gregor } while (true); 237335b13eceSDouglas Gregor } 237435b13eceSDouglas Gregor 2375fb912657SDouglas Gregor /// \brief Format a module-id into a string. 2376fb912657SDouglas Gregor static std::string formatModuleId(const ModuleId &Id) { 2377fb912657SDouglas Gregor std::string result; 2378fb912657SDouglas Gregor { 2379fb912657SDouglas Gregor llvm::raw_string_ostream OS(result); 2380fb912657SDouglas Gregor 2381fb912657SDouglas Gregor for (unsigned I = 0, N = Id.size(); I != N; ++I) { 2382fb912657SDouglas Gregor if (I) 2383fb912657SDouglas Gregor OS << "."; 2384fb912657SDouglas Gregor OS << Id[I].first; 2385fb912657SDouglas Gregor } 2386fb912657SDouglas Gregor } 2387fb912657SDouglas Gregor 2388fb912657SDouglas Gregor return result; 2389fb912657SDouglas Gregor } 2390fb912657SDouglas Gregor 2391fb912657SDouglas Gregor /// \brief Parse a conflict declaration. 2392fb912657SDouglas Gregor /// 2393fb912657SDouglas Gregor /// module-declaration: 2394fb912657SDouglas Gregor /// 'conflict' module-id ',' string-literal 2395fb912657SDouglas Gregor void ModuleMapParser::parseConflict() { 2396fb912657SDouglas Gregor assert(Tok.is(MMToken::Conflict)); 2397fb912657SDouglas Gregor SourceLocation ConflictLoc = consumeToken(); 2398fb912657SDouglas Gregor Module::UnresolvedConflict Conflict; 2399fb912657SDouglas Gregor 2400fb912657SDouglas Gregor // Parse the module-id. 2401fb912657SDouglas Gregor if (parseModuleId(Conflict.Id)) 2402fb912657SDouglas Gregor return; 2403fb912657SDouglas Gregor 2404fb912657SDouglas Gregor // Parse the ','. 2405fb912657SDouglas Gregor if (!Tok.is(MMToken::Comma)) { 2406fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_comma) 2407fb912657SDouglas Gregor << SourceRange(ConflictLoc); 2408fb912657SDouglas Gregor return; 2409fb912657SDouglas Gregor } 2410fb912657SDouglas Gregor consumeToken(); 2411fb912657SDouglas Gregor 2412fb912657SDouglas Gregor // Parse the message. 2413fb912657SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 2414fb912657SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_conflicts_message) 2415fb912657SDouglas Gregor << formatModuleId(Conflict.Id); 2416fb912657SDouglas Gregor return; 2417fb912657SDouglas Gregor } 2418fb912657SDouglas Gregor Conflict.Message = Tok.getString().str(); 2419fb912657SDouglas Gregor consumeToken(); 2420fb912657SDouglas Gregor 2421fb912657SDouglas Gregor // Add this unresolved conflict. 2422fb912657SDouglas Gregor ActiveModule->UnresolvedConflicts.push_back(Conflict); 2423fb912657SDouglas Gregor } 2424fb912657SDouglas Gregor 24256ddfca91SDouglas Gregor /// \brief Parse an inferred module declaration (wildcard modules). 24269194a91dSDouglas Gregor /// 24279194a91dSDouglas Gregor /// module-declaration: 24289194a91dSDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' * attributes[opt] 24299194a91dSDouglas Gregor /// { inferred-module-member* } 24309194a91dSDouglas Gregor /// 24319194a91dSDouglas Gregor /// inferred-module-member: 24329194a91dSDouglas Gregor /// 'export' '*' 24339194a91dSDouglas Gregor /// 'exclude' identifier 24349194a91dSDouglas Gregor void ModuleMapParser::parseInferredModuleDecl(bool Framework, bool Explicit) { 243573441091SDouglas Gregor assert(Tok.is(MMToken::Star)); 243673441091SDouglas Gregor SourceLocation StarLoc = consumeToken(); 243773441091SDouglas Gregor bool Failed = false; 243873441091SDouglas Gregor 243973441091SDouglas Gregor // Inferred modules must be submodules. 24409194a91dSDouglas Gregor if (!ActiveModule && !Framework) { 244173441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule); 244273441091SDouglas Gregor Failed = true; 244373441091SDouglas Gregor } 244473441091SDouglas Gregor 24459194a91dSDouglas Gregor if (ActiveModule) { 2446524e33e1SDouglas Gregor // Inferred modules must have umbrella directories. 24474898cde4SBen Langmuir if (!Failed && ActiveModule->IsAvailable && 24484898cde4SBen Langmuir !ActiveModule->getUmbrellaDir()) { 244973441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); 245073441091SDouglas Gregor Failed = true; 245173441091SDouglas Gregor } 245273441091SDouglas Gregor 245373441091SDouglas Gregor // Check for redefinition of an inferred module. 2454dd005f69SDouglas Gregor if (!Failed && ActiveModule->InferSubmodules) { 245573441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_redef); 2456dd005f69SDouglas Gregor if (ActiveModule->InferredSubmoduleLoc.isValid()) 2457dd005f69SDouglas Gregor Diags.Report(ActiveModule->InferredSubmoduleLoc, 245873441091SDouglas Gregor diag::note_mmap_prev_definition); 245973441091SDouglas Gregor Failed = true; 246073441091SDouglas Gregor } 246173441091SDouglas Gregor 24629194a91dSDouglas Gregor // Check for the 'framework' keyword, which is not permitted here. 24639194a91dSDouglas Gregor if (Framework) { 24649194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_framework_submodule); 24659194a91dSDouglas Gregor Framework = false; 24669194a91dSDouglas Gregor } 24679194a91dSDouglas Gregor } else if (Explicit) { 24689194a91dSDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_explicit_inferred_framework); 24699194a91dSDouglas Gregor Explicit = false; 24709194a91dSDouglas Gregor } 24719194a91dSDouglas Gregor 247273441091SDouglas Gregor // If there were any problems with this inferred submodule, skip its body. 247373441091SDouglas Gregor if (Failed) { 247473441091SDouglas Gregor if (Tok.is(MMToken::LBrace)) { 247573441091SDouglas Gregor consumeToken(); 247673441091SDouglas Gregor skipUntil(MMToken::RBrace); 247773441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 247873441091SDouglas Gregor consumeToken(); 247973441091SDouglas Gregor } 248073441091SDouglas Gregor HadError = true; 248173441091SDouglas Gregor return; 248273441091SDouglas Gregor } 248373441091SDouglas Gregor 24849194a91dSDouglas Gregor // Parse optional attributes. 24854442605fSBill Wendling Attributes Attrs; 24865d29dee0SDavide Italiano if (parseOptionalAttributes(Attrs)) 24875d29dee0SDavide Italiano return; 24889194a91dSDouglas Gregor 24899194a91dSDouglas Gregor if (ActiveModule) { 249073441091SDouglas Gregor // Note that we have an inferred submodule. 2491dd005f69SDouglas Gregor ActiveModule->InferSubmodules = true; 2492dd005f69SDouglas Gregor ActiveModule->InferredSubmoduleLoc = StarLoc; 2493dd005f69SDouglas Gregor ActiveModule->InferExplicitSubmodules = Explicit; 24949194a91dSDouglas Gregor } else { 24959194a91dSDouglas Gregor // We'll be inferring framework modules for this directory. 24969194a91dSDouglas Gregor Map.InferredDirectories[Directory].InferModules = true; 2497c1d88ea5SBen Langmuir Map.InferredDirectories[Directory].Attrs = Attrs; 2498beee15e7SBen Langmuir Map.InferredDirectories[Directory].ModuleMapFile = ModuleMapFile; 2499131daca0SRichard Smith // FIXME: Handle the 'framework' keyword. 25009194a91dSDouglas Gregor } 250173441091SDouglas Gregor 250273441091SDouglas Gregor // Parse the opening brace. 250373441091SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 250473441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard); 250573441091SDouglas Gregor HadError = true; 250673441091SDouglas Gregor return; 250773441091SDouglas Gregor } 250873441091SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 250973441091SDouglas Gregor 251073441091SDouglas Gregor // Parse the body of the inferred submodule. 251173441091SDouglas Gregor bool Done = false; 251273441091SDouglas Gregor do { 251373441091SDouglas Gregor switch (Tok.Kind) { 251473441091SDouglas Gregor case MMToken::EndOfFile: 251573441091SDouglas Gregor case MMToken::RBrace: 251673441091SDouglas Gregor Done = true; 251773441091SDouglas Gregor break; 251873441091SDouglas Gregor 25199194a91dSDouglas Gregor case MMToken::ExcludeKeyword: { 25209194a91dSDouglas Gregor if (ActiveModule) { 25219194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2522d2d442caSCraig Topper << (ActiveModule != nullptr); 25239194a91dSDouglas Gregor consumeToken(); 25249194a91dSDouglas Gregor break; 25259194a91dSDouglas Gregor } 25269194a91dSDouglas Gregor 25279194a91dSDouglas Gregor consumeToken(); 2528306d8920SRichard Smith // FIXME: Support string-literal module names here. 25299194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 25309194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_missing_exclude_name); 25319194a91dSDouglas Gregor break; 25329194a91dSDouglas Gregor } 25339194a91dSDouglas Gregor 25349194a91dSDouglas Gregor Map.InferredDirectories[Directory].ExcludedModules 25359194a91dSDouglas Gregor .push_back(Tok.getString()); 25369194a91dSDouglas Gregor consumeToken(); 25379194a91dSDouglas Gregor break; 25389194a91dSDouglas Gregor } 25399194a91dSDouglas Gregor 25409194a91dSDouglas Gregor case MMToken::ExportKeyword: 25419194a91dSDouglas Gregor if (!ActiveModule) { 25429194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2543d2d442caSCraig Topper << (ActiveModule != nullptr); 25449194a91dSDouglas Gregor consumeToken(); 25459194a91dSDouglas Gregor break; 25469194a91dSDouglas Gregor } 25479194a91dSDouglas Gregor 254873441091SDouglas Gregor consumeToken(); 254973441091SDouglas Gregor if (Tok.is(MMToken::Star)) 2550dd005f69SDouglas Gregor ActiveModule->InferExportWildcard = true; 255173441091SDouglas Gregor else 255273441091SDouglas Gregor Diags.Report(Tok.getLocation(), 255373441091SDouglas Gregor diag::err_mmap_expected_export_wildcard); 255473441091SDouglas Gregor consumeToken(); 255573441091SDouglas Gregor break; 255673441091SDouglas Gregor 255773441091SDouglas Gregor case MMToken::ExplicitKeyword: 255873441091SDouglas Gregor case MMToken::ModuleKeyword: 255973441091SDouglas Gregor case MMToken::HeaderKeyword: 2560b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 256173441091SDouglas Gregor case MMToken::UmbrellaKeyword: 256273441091SDouglas Gregor default: 25639194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_inferred_member) 2564d2d442caSCraig Topper << (ActiveModule != nullptr); 256573441091SDouglas Gregor consumeToken(); 256673441091SDouglas Gregor break; 256773441091SDouglas Gregor } 256873441091SDouglas Gregor } while (!Done); 256973441091SDouglas Gregor 257073441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 257173441091SDouglas Gregor consumeToken(); 257273441091SDouglas Gregor else { 257373441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 257473441091SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 257573441091SDouglas Gregor HadError = true; 257673441091SDouglas Gregor } 257773441091SDouglas Gregor } 257873441091SDouglas Gregor 25799194a91dSDouglas Gregor /// \brief Parse optional attributes. 25809194a91dSDouglas Gregor /// 25819194a91dSDouglas Gregor /// attributes: 25829194a91dSDouglas Gregor /// attribute attributes 25839194a91dSDouglas Gregor /// attribute 25849194a91dSDouglas Gregor /// 25859194a91dSDouglas Gregor /// attribute: 25869194a91dSDouglas Gregor /// [ identifier ] 25879194a91dSDouglas Gregor /// 25889194a91dSDouglas Gregor /// \param Attrs Will be filled in with the parsed attributes. 25899194a91dSDouglas Gregor /// 25909194a91dSDouglas Gregor /// \returns true if an error occurred, false otherwise. 25914442605fSBill Wendling bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { 25929194a91dSDouglas Gregor bool HadError = false; 25939194a91dSDouglas Gregor 25949194a91dSDouglas Gregor while (Tok.is(MMToken::LSquare)) { 25959194a91dSDouglas Gregor // Consume the '['. 25969194a91dSDouglas Gregor SourceLocation LSquareLoc = consumeToken(); 25979194a91dSDouglas Gregor 25989194a91dSDouglas Gregor // Check whether we have an attribute name here. 25999194a91dSDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 26009194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute); 26019194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 26029194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 26039194a91dSDouglas Gregor consumeToken(); 26049194a91dSDouglas Gregor HadError = true; 26059194a91dSDouglas Gregor } 26069194a91dSDouglas Gregor 26079194a91dSDouglas Gregor // Decode the attribute name. 26089194a91dSDouglas Gregor AttributeKind Attribute 26099194a91dSDouglas Gregor = llvm::StringSwitch<AttributeKind>(Tok.getString()) 261035b13eceSDouglas Gregor .Case("exhaustive", AT_exhaustive) 261177944868SRichard Smith .Case("extern_c", AT_extern_c) 2612ed84df00SBruno Cardoso Lopes .Case("no_undeclared_includes", AT_no_undeclared_includes) 26139194a91dSDouglas Gregor .Case("system", AT_system) 26149194a91dSDouglas Gregor .Default(AT_unknown); 26159194a91dSDouglas Gregor switch (Attribute) { 26169194a91dSDouglas Gregor case AT_unknown: 26179194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute) 26189194a91dSDouglas Gregor << Tok.getString(); 26199194a91dSDouglas Gregor break; 26209194a91dSDouglas Gregor 26219194a91dSDouglas Gregor case AT_system: 26229194a91dSDouglas Gregor Attrs.IsSystem = true; 26239194a91dSDouglas Gregor break; 262435b13eceSDouglas Gregor 262577944868SRichard Smith case AT_extern_c: 262677944868SRichard Smith Attrs.IsExternC = true; 262777944868SRichard Smith break; 262877944868SRichard Smith 262935b13eceSDouglas Gregor case AT_exhaustive: 263035b13eceSDouglas Gregor Attrs.IsExhaustive = true; 263135b13eceSDouglas Gregor break; 2632ed84df00SBruno Cardoso Lopes 2633ed84df00SBruno Cardoso Lopes case AT_no_undeclared_includes: 2634ed84df00SBruno Cardoso Lopes Attrs.NoUndeclaredIncludes = true; 2635ed84df00SBruno Cardoso Lopes break; 26369194a91dSDouglas Gregor } 26379194a91dSDouglas Gregor consumeToken(); 26389194a91dSDouglas Gregor 26399194a91dSDouglas Gregor // Consume the ']'. 26409194a91dSDouglas Gregor if (!Tok.is(MMToken::RSquare)) { 26419194a91dSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare); 26429194a91dSDouglas Gregor Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match); 26439194a91dSDouglas Gregor skipUntil(MMToken::RSquare); 26449194a91dSDouglas Gregor HadError = true; 26459194a91dSDouglas Gregor } 26469194a91dSDouglas Gregor 26479194a91dSDouglas Gregor if (Tok.is(MMToken::RSquare)) 26489194a91dSDouglas Gregor consumeToken(); 26499194a91dSDouglas Gregor } 26509194a91dSDouglas Gregor 26519194a91dSDouglas Gregor return HadError; 26529194a91dSDouglas Gregor } 26539194a91dSDouglas Gregor 2654718292f2SDouglas Gregor /// \brief Parse a module map file. 2655718292f2SDouglas Gregor /// 2656718292f2SDouglas Gregor /// module-map-file: 2657718292f2SDouglas Gregor /// module-declaration* 2658718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 2659718292f2SDouglas Gregor do { 2660718292f2SDouglas Gregor switch (Tok.Kind) { 2661718292f2SDouglas Gregor case MMToken::EndOfFile: 2662718292f2SDouglas Gregor return HadError; 2663718292f2SDouglas Gregor 2664e7ab3669SDouglas Gregor case MMToken::ExplicitKeyword: 266597292843SDaniel Jasper case MMToken::ExternKeyword: 2666718292f2SDouglas Gregor case MMToken::ModuleKeyword: 2667755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 2668718292f2SDouglas Gregor parseModuleDecl(); 2669718292f2SDouglas Gregor break; 2670718292f2SDouglas Gregor 26711fb5c3a6SDouglas Gregor case MMToken::Comma: 267235b13eceSDouglas Gregor case MMToken::ConfigMacros: 2673fb912657SDouglas Gregor case MMToken::Conflict: 2674a3feee2aSRichard Smith case MMToken::Exclaim: 267559527666SDouglas Gregor case MMToken::ExcludeKeyword: 26762b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 2677718292f2SDouglas Gregor case MMToken::HeaderKeyword: 2678718292f2SDouglas Gregor case MMToken::Identifier: 2679718292f2SDouglas Gregor case MMToken::LBrace: 26806ddfca91SDouglas Gregor case MMToken::LinkKeyword: 2681a686e1b0SDouglas Gregor case MMToken::LSquare: 26822b82c2a5SDouglas Gregor case MMToken::Period: 2683b53e5483SLawrence Crowl case MMToken::PrivateKeyword: 2684718292f2SDouglas Gregor case MMToken::RBrace: 2685a686e1b0SDouglas Gregor case MMToken::RSquare: 26861fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 26872b82c2a5SDouglas Gregor case MMToken::Star: 2688718292f2SDouglas Gregor case MMToken::StringLiteral: 2689*040e1266SRichard Smith case MMToken::IntegerLiteral: 2690b8afebe2SRichard Smith case MMToken::TextualKeyword: 2691718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 2692ba7f2f71SDaniel Jasper case MMToken::UseKeyword: 2693718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 2694718292f2SDouglas Gregor HadError = true; 2695718292f2SDouglas Gregor consumeToken(); 2696718292f2SDouglas Gregor break; 2697718292f2SDouglas Gregor } 2698718292f2SDouglas Gregor } while (true); 2699718292f2SDouglas Gregor } 2700718292f2SDouglas Gregor 27019acb99e3SRichard Smith bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem, 27028128f332SRichard Smith const DirectoryEntry *Dir, FileID ID, 27038128f332SRichard Smith unsigned *Offset, 2704ae6df27eSRichard Smith SourceLocation ExternModuleLoc) { 27058128f332SRichard Smith assert(Target && "Missing target information"); 27064ddf2221SDouglas Gregor llvm::DenseMap<const FileEntry *, bool>::iterator Known 27074ddf2221SDouglas Gregor = ParsedModuleMap.find(File); 27084ddf2221SDouglas Gregor if (Known != ParsedModuleMap.end()) 27094ddf2221SDouglas Gregor return Known->second; 27104ddf2221SDouglas Gregor 27118128f332SRichard Smith // If the module map file wasn't already entered, do so now. 27128128f332SRichard Smith if (ID.isInvalid()) { 2713cb69b57bSBen Langmuir auto FileCharacter = IsSystem ? SrcMgr::C_System : SrcMgr::C_User; 27148128f332SRichard Smith ID = SourceMgr.createFileID(File, ExternModuleLoc, FileCharacter); 27158128f332SRichard Smith } 27168128f332SRichard Smith 27178128f332SRichard Smith assert(Target && "Missing target information"); 27181f76c4e8SManuel Klimek const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID); 2719718292f2SDouglas Gregor if (!Buffer) 27204ddf2221SDouglas Gregor return ParsedModuleMap[File] = true; 27218128f332SRichard Smith assert((!Offset || *Offset <= Buffer->getBufferSize()) && 27228128f332SRichard Smith "invalid buffer offset"); 2723718292f2SDouglas Gregor 2724718292f2SDouglas Gregor // Parse this module map file. 27258128f332SRichard Smith Lexer L(SourceMgr.getLocForStartOfFile(ID), MMapLangOpts, 27268128f332SRichard Smith Buffer->getBufferStart(), 27278128f332SRichard Smith Buffer->getBufferStart() + (Offset ? *Offset : 0), 27288128f332SRichard Smith Buffer->getBufferEnd()); 27292a6edb30SRichard Smith SourceLocation Start = L.getSourceLocation(); 2730beee15e7SBen Langmuir ModuleMapParser Parser(L, SourceMgr, Target, Diags, *this, File, Dir, 27311d60987fSRichard Smith IsSystem); 2732718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 27334ddf2221SDouglas Gregor ParsedModuleMap[File] = Result; 27342a6edb30SRichard Smith 27358128f332SRichard Smith if (Offset) { 27368128f332SRichard Smith auto Loc = SourceMgr.getDecomposedLoc(Parser.getLocation()); 27378128f332SRichard Smith assert(Loc.first == ID && "stopped in a different file?"); 27388128f332SRichard Smith *Offset = Loc.second; 27398128f332SRichard Smith } 27408128f332SRichard Smith 27412a6edb30SRichard Smith // Notify callbacks that we parsed it. 27422a6edb30SRichard Smith for (const auto &Cb : Callbacks) 27432a6edb30SRichard Smith Cb->moduleMapFileRead(Start, *File, IsSystem); 2744718292f2SDouglas Gregor return Result; 2745718292f2SDouglas Gregor } 2746