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" 15718292f2SDouglas Gregor #include "clang/Lex/Lexer.h" 16718292f2SDouglas Gregor #include "clang/Lex/LiteralSupport.h" 17718292f2SDouglas Gregor #include "clang/Lex/LexDiagnostic.h" 18718292f2SDouglas Gregor #include "clang/Basic/Diagnostic.h" 19718292f2SDouglas Gregor #include "clang/Basic/FileManager.h" 20718292f2SDouglas Gregor #include "clang/Basic/TargetInfo.h" 21718292f2SDouglas Gregor #include "clang/Basic/TargetOptions.h" 22718292f2SDouglas Gregor #include "llvm/Support/Allocator.h" 23e89dbc1dSDouglas Gregor #include "llvm/Support/FileSystem.h" 24718292f2SDouglas Gregor #include "llvm/Support/Host.h" 255257fc63SDouglas Gregor #include "llvm/Support/PathV2.h" 26718292f2SDouglas Gregor #include "llvm/Support/raw_ostream.h" 27718292f2SDouglas Gregor #include "llvm/ADT/StringRef.h" 28718292f2SDouglas Gregor #include "llvm/ADT/StringSwitch.h" 29718292f2SDouglas Gregor using namespace clang; 30718292f2SDouglas Gregor 312b82c2a5SDouglas Gregor Module::ExportDecl 322b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod, 332b82c2a5SDouglas Gregor const Module::UnresolvedExportDecl &Unresolved, 342b82c2a5SDouglas Gregor bool Complain) { 35f5eedd05SDouglas Gregor // We may have just a wildcard. 36f5eedd05SDouglas Gregor if (Unresolved.Id.empty()) { 37f5eedd05SDouglas Gregor assert(Unresolved.Wildcard && "Invalid unresolved export"); 38f5eedd05SDouglas Gregor return Module::ExportDecl(0, true); 39f5eedd05SDouglas Gregor } 40f5eedd05SDouglas Gregor 412b82c2a5SDouglas Gregor // Find the starting module. 422b82c2a5SDouglas Gregor Module *Context = lookupModuleUnqualified(Unresolved.Id[0].first, Mod); 432b82c2a5SDouglas Gregor if (!Context) { 442b82c2a5SDouglas Gregor if (Complain) 452b82c2a5SDouglas Gregor Diags->Report(Unresolved.Id[0].second, 462b82c2a5SDouglas Gregor diag::err_mmap_missing_module_unqualified) 472b82c2a5SDouglas Gregor << Unresolved.Id[0].first << Mod->getFullModuleName(); 482b82c2a5SDouglas Gregor 492b82c2a5SDouglas Gregor return Module::ExportDecl(); 502b82c2a5SDouglas Gregor } 512b82c2a5SDouglas Gregor 522b82c2a5SDouglas Gregor // Dig into the module path. 532b82c2a5SDouglas Gregor for (unsigned I = 1, N = Unresolved.Id.size(); I != N; ++I) { 542b82c2a5SDouglas Gregor Module *Sub = lookupModuleQualified(Unresolved.Id[I].first, 552b82c2a5SDouglas Gregor Context); 562b82c2a5SDouglas Gregor if (!Sub) { 572b82c2a5SDouglas Gregor if (Complain) 582b82c2a5SDouglas Gregor Diags->Report(Unresolved.Id[I].second, 592b82c2a5SDouglas Gregor diag::err_mmap_missing_module_qualified) 602b82c2a5SDouglas Gregor << Unresolved.Id[I].first << Context->getFullModuleName() 612b82c2a5SDouglas Gregor << SourceRange(Unresolved.Id[0].second, Unresolved.Id[I-1].second); 622b82c2a5SDouglas Gregor 632b82c2a5SDouglas Gregor return Module::ExportDecl(); 642b82c2a5SDouglas Gregor } 652b82c2a5SDouglas Gregor 662b82c2a5SDouglas Gregor Context = Sub; 672b82c2a5SDouglas Gregor } 682b82c2a5SDouglas Gregor 692b82c2a5SDouglas Gregor return Module::ExportDecl(Context, Unresolved.Wildcard); 702b82c2a5SDouglas Gregor } 712b82c2a5SDouglas Gregor 721fb5c3a6SDouglas Gregor ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC, 731fb5c3a6SDouglas Gregor const LangOptions &LangOpts) 741fb5c3a6SDouglas Gregor : LangOpts(LangOpts) 751fb5c3a6SDouglas Gregor { 76718292f2SDouglas Gregor llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs); 77718292f2SDouglas Gregor Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>( 78718292f2SDouglas Gregor new DiagnosticsEngine(DiagIDs)); 79718292f2SDouglas Gregor Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true); 80718292f2SDouglas Gregor SourceMgr = new SourceManager(*Diags, FileMgr); 81718292f2SDouglas Gregor } 82718292f2SDouglas Gregor 83718292f2SDouglas Gregor ModuleMap::~ModuleMap() { 845acdf59eSDouglas Gregor for (llvm::StringMap<Module *>::iterator I = Modules.begin(), 855acdf59eSDouglas Gregor IEnd = Modules.end(); 865acdf59eSDouglas Gregor I != IEnd; ++I) { 875acdf59eSDouglas Gregor delete I->getValue(); 885acdf59eSDouglas Gregor } 895acdf59eSDouglas Gregor 90718292f2SDouglas Gregor delete SourceMgr; 91718292f2SDouglas Gregor } 92718292f2SDouglas Gregor 93de3ef502SDouglas Gregor Module *ModuleMap::findModuleForHeader(const FileEntry *File) { 94ab0c8a84SDouglas Gregor llvm::DenseMap<const FileEntry *, Module *>::iterator Known 95ab0c8a84SDouglas Gregor = Headers.find(File); 961fb5c3a6SDouglas Gregor if (Known != Headers.end()) { 971fb5c3a6SDouglas Gregor // If a header corresponds to an unavailable module, don't report 981fb5c3a6SDouglas Gregor // that it maps to anything. 991fb5c3a6SDouglas Gregor if (!Known->second->isAvailable()) 1001fb5c3a6SDouglas Gregor return 0; 1011fb5c3a6SDouglas Gregor 102ab0c8a84SDouglas Gregor return Known->second; 1031fb5c3a6SDouglas Gregor } 104ab0c8a84SDouglas Gregor 105b65dbfffSDouglas Gregor const DirectoryEntry *Dir = File->getDir(); 106b65dbfffSDouglas Gregor llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs; 107b65dbfffSDouglas Gregor StringRef DirName = Dir->getName(); 108a89c5ac4SDouglas Gregor 109a89c5ac4SDouglas Gregor // Keep walking up the directory hierarchy, looking for a directory with 110a89c5ac4SDouglas Gregor // an umbrella header. 111b65dbfffSDouglas Gregor do { 112a89c5ac4SDouglas Gregor llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir 113a89c5ac4SDouglas Gregor = UmbrellaDirs.find(Dir); 114a89c5ac4SDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 115a89c5ac4SDouglas Gregor Module *Result = KnownDir->second; 116930a85ccSDouglas Gregor 117930a85ccSDouglas Gregor // Search up the module stack until we find a module with an umbrella 11873141fa9SDouglas Gregor // directory. 119930a85ccSDouglas Gregor Module *UmbrellaModule = Result; 12073141fa9SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 121930a85ccSDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 122930a85ccSDouglas Gregor 123930a85ccSDouglas Gregor if (UmbrellaModule->InferSubmodules) { 124a89c5ac4SDouglas Gregor // Infer submodules for each of the directories we found between 125a89c5ac4SDouglas Gregor // the directory of the umbrella header and the directory where 126a89c5ac4SDouglas Gregor // the actual header is located. 1279458f82dSDouglas Gregor bool Explicit = UmbrellaModule->InferExplicitSubmodules; 1289458f82dSDouglas Gregor 1297033127bSDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 130a89c5ac4SDouglas Gregor // Find or create the module that corresponds to this directory name. 131a89c5ac4SDouglas Gregor StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName()); 132a89c5ac4SDouglas Gregor Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 1339458f82dSDouglas Gregor Explicit).first; 134a89c5ac4SDouglas Gregor 135a89c5ac4SDouglas Gregor // Associate the module and the directory. 136a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I-1]] = Result; 137a89c5ac4SDouglas Gregor 138a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 139a89c5ac4SDouglas Gregor // wildcard to the set of exports. 140930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 141a89c5ac4SDouglas Gregor Result->Exports.push_back(Module::ExportDecl(0, true)); 142a89c5ac4SDouglas Gregor } 143a89c5ac4SDouglas Gregor 144a89c5ac4SDouglas Gregor // Infer a submodule with the same name as this header file. 145a89c5ac4SDouglas Gregor StringRef Name = llvm::sys::path::stem(File->getName()); 146a89c5ac4SDouglas Gregor Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 1479458f82dSDouglas Gregor Explicit).first; 148a89c5ac4SDouglas Gregor 149a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 150a89c5ac4SDouglas Gregor // wildcard to the set of exports. 151930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 152a89c5ac4SDouglas Gregor Result->Exports.push_back(Module::ExportDecl(0, true)); 153a89c5ac4SDouglas Gregor } else { 154a89c5ac4SDouglas Gregor // Record each of the directories we stepped through as being part of 155a89c5ac4SDouglas Gregor // the module we found, since the umbrella header covers them all. 156a89c5ac4SDouglas Gregor for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I) 157a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I]] = Result; 158a89c5ac4SDouglas Gregor } 159a89c5ac4SDouglas Gregor 160a89c5ac4SDouglas Gregor Headers[File] = Result; 1611fb5c3a6SDouglas Gregor 1621fb5c3a6SDouglas Gregor // If a header corresponds to an unavailable module, don't report 1631fb5c3a6SDouglas Gregor // that it maps to anything. 1641fb5c3a6SDouglas Gregor if (!Result->isAvailable()) 1651fb5c3a6SDouglas Gregor return 0; 1661fb5c3a6SDouglas Gregor 167a89c5ac4SDouglas Gregor return Result; 168a89c5ac4SDouglas Gregor } 169a89c5ac4SDouglas Gregor 170a89c5ac4SDouglas Gregor SkippedDirs.push_back(Dir); 171a89c5ac4SDouglas Gregor 172b65dbfffSDouglas Gregor // Retrieve our parent path. 173b65dbfffSDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 174b65dbfffSDouglas Gregor if (DirName.empty()) 175b65dbfffSDouglas Gregor break; 176b65dbfffSDouglas Gregor 177b65dbfffSDouglas Gregor // Resolve the parent path to a directory entry. 178b65dbfffSDouglas Gregor Dir = SourceMgr->getFileManager().getDirectory(DirName); 179a89c5ac4SDouglas Gregor } while (Dir); 180b65dbfffSDouglas Gregor 181ab0c8a84SDouglas Gregor return 0; 182ab0c8a84SDouglas Gregor } 183ab0c8a84SDouglas Gregor 1841fb5c3a6SDouglas Gregor bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) { 1851fb5c3a6SDouglas Gregor llvm::DenseMap<const FileEntry *, Module *>::iterator Known 1861fb5c3a6SDouglas Gregor = Headers.find(Header); 1871fb5c3a6SDouglas Gregor if (Known != Headers.end()) 1881fb5c3a6SDouglas Gregor return !Known->second->isAvailable(); 1891fb5c3a6SDouglas Gregor 1901fb5c3a6SDouglas Gregor const DirectoryEntry *Dir = Header->getDir(); 1911fb5c3a6SDouglas Gregor llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs; 1921fb5c3a6SDouglas Gregor StringRef DirName = Dir->getName(); 1931fb5c3a6SDouglas Gregor 1941fb5c3a6SDouglas Gregor // Keep walking up the directory hierarchy, looking for a directory with 1951fb5c3a6SDouglas Gregor // an umbrella header. 1961fb5c3a6SDouglas Gregor do { 1971fb5c3a6SDouglas Gregor llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir 1981fb5c3a6SDouglas Gregor = UmbrellaDirs.find(Dir); 1991fb5c3a6SDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 2001fb5c3a6SDouglas Gregor Module *Found = KnownDir->second; 2011fb5c3a6SDouglas Gregor if (!Found->isAvailable()) 2021fb5c3a6SDouglas Gregor return true; 2031fb5c3a6SDouglas Gregor 2041fb5c3a6SDouglas Gregor // Search up the module stack until we find a module with an umbrella 2051fb5c3a6SDouglas Gregor // directory. 2061fb5c3a6SDouglas Gregor Module *UmbrellaModule = Found; 2071fb5c3a6SDouglas Gregor while (!UmbrellaModule->getUmbrellaDir() && UmbrellaModule->Parent) 2081fb5c3a6SDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 2091fb5c3a6SDouglas Gregor 2101fb5c3a6SDouglas Gregor if (UmbrellaModule->InferSubmodules) { 2111fb5c3a6SDouglas Gregor for (unsigned I = SkippedDirs.size(); I != 0; --I) { 2121fb5c3a6SDouglas Gregor // Find or create the module that corresponds to this directory name. 2131fb5c3a6SDouglas Gregor StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName()); 2141fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 2151fb5c3a6SDouglas Gregor if (!Found) 2161fb5c3a6SDouglas Gregor return false; 2171fb5c3a6SDouglas Gregor if (!Found->isAvailable()) 2181fb5c3a6SDouglas Gregor return true; 2191fb5c3a6SDouglas Gregor } 2201fb5c3a6SDouglas Gregor 2211fb5c3a6SDouglas Gregor // Infer a submodule with the same name as this header file. 2221fb5c3a6SDouglas Gregor StringRef Name = llvm::sys::path::stem(Header->getName()); 2231fb5c3a6SDouglas Gregor Found = lookupModuleQualified(Name, Found); 2241fb5c3a6SDouglas Gregor if (!Found) 2251fb5c3a6SDouglas Gregor return false; 2261fb5c3a6SDouglas Gregor } 2271fb5c3a6SDouglas Gregor 2281fb5c3a6SDouglas Gregor return !Found->isAvailable(); 2291fb5c3a6SDouglas Gregor } 2301fb5c3a6SDouglas Gregor 2311fb5c3a6SDouglas Gregor SkippedDirs.push_back(Dir); 2321fb5c3a6SDouglas Gregor 2331fb5c3a6SDouglas Gregor // Retrieve our parent path. 2341fb5c3a6SDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 2351fb5c3a6SDouglas Gregor if (DirName.empty()) 2361fb5c3a6SDouglas Gregor break; 2371fb5c3a6SDouglas Gregor 2381fb5c3a6SDouglas Gregor // Resolve the parent path to a directory entry. 2391fb5c3a6SDouglas Gregor Dir = SourceMgr->getFileManager().getDirectory(DirName); 2401fb5c3a6SDouglas Gregor } while (Dir); 2411fb5c3a6SDouglas Gregor 2421fb5c3a6SDouglas Gregor return false; 2431fb5c3a6SDouglas Gregor } 2441fb5c3a6SDouglas Gregor 245de3ef502SDouglas Gregor Module *ModuleMap::findModule(StringRef Name) { 24688bdfb0eSDouglas Gregor llvm::StringMap<Module *>::iterator Known = Modules.find(Name); 24788bdfb0eSDouglas Gregor if (Known != Modules.end()) 24888bdfb0eSDouglas Gregor return Known->getValue(); 24988bdfb0eSDouglas Gregor 25088bdfb0eSDouglas Gregor return 0; 25188bdfb0eSDouglas Gregor } 25288bdfb0eSDouglas Gregor 2532b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) { 2542b82c2a5SDouglas Gregor for(; Context; Context = Context->Parent) { 2552b82c2a5SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Context)) 2562b82c2a5SDouglas Gregor return Sub; 2572b82c2a5SDouglas Gregor } 2582b82c2a5SDouglas Gregor 2592b82c2a5SDouglas Gregor return findModule(Name); 2602b82c2a5SDouglas Gregor } 2612b82c2a5SDouglas Gregor 2622b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) { 2632b82c2a5SDouglas Gregor if (!Context) 2642b82c2a5SDouglas Gregor return findModule(Name); 2652b82c2a5SDouglas Gregor 266eb90e830SDouglas Gregor return Context->findSubmodule(Name); 2672b82c2a5SDouglas Gregor } 2682b82c2a5SDouglas Gregor 269de3ef502SDouglas Gregor std::pair<Module *, bool> 27069021974SDouglas Gregor ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework, 27169021974SDouglas Gregor bool IsExplicit) { 27269021974SDouglas Gregor // Try to find an existing module with this name. 273eb90e830SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Parent)) 274eb90e830SDouglas Gregor return std::make_pair(Sub, false); 27569021974SDouglas Gregor 27669021974SDouglas Gregor // Create a new module with this name. 27769021974SDouglas Gregor Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, 27869021974SDouglas Gregor IsExplicit); 279eb90e830SDouglas Gregor if (!Parent) 28069021974SDouglas Gregor Modules[Name] = Result; 28169021974SDouglas Gregor return std::make_pair(Result, true); 28269021974SDouglas Gregor } 28369021974SDouglas Gregor 284de3ef502SDouglas Gregor Module * 28556c64013SDouglas Gregor ModuleMap::inferFrameworkModule(StringRef ModuleName, 286e89dbc1dSDouglas Gregor const DirectoryEntry *FrameworkDir, 287*a686e1b0SDouglas Gregor bool IsSystem, 288e89dbc1dSDouglas Gregor Module *Parent) { 28956c64013SDouglas Gregor // Check whether we've already found this module. 290e89dbc1dSDouglas Gregor if (Module *Mod = lookupModuleQualified(ModuleName, Parent)) 291e89dbc1dSDouglas Gregor return Mod; 292e89dbc1dSDouglas Gregor 293e89dbc1dSDouglas Gregor FileManager &FileMgr = SourceMgr->getFileManager(); 29456c64013SDouglas Gregor 29556c64013SDouglas Gregor // Look for an umbrella header. 29656c64013SDouglas Gregor llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 29756c64013SDouglas Gregor llvm::sys::path::append(UmbrellaName, "Headers"); 29856c64013SDouglas Gregor llvm::sys::path::append(UmbrellaName, ModuleName + ".h"); 299e89dbc1dSDouglas Gregor const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName); 30056c64013SDouglas Gregor 30156c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the 30256c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good 30356c64013SDouglas Gregor // idea. 30456c64013SDouglas Gregor if (!UmbrellaHeader) 30556c64013SDouglas Gregor return 0; 30656c64013SDouglas Gregor 307e89dbc1dSDouglas Gregor Module *Result = new Module(ModuleName, SourceLocation(), Parent, 308e89dbc1dSDouglas Gregor /*IsFramework=*/true, /*IsExplicit=*/false); 309*a686e1b0SDouglas Gregor if (IsSystem) 310*a686e1b0SDouglas Gregor Result->IsSystem = IsSystem; 311*a686e1b0SDouglas Gregor 312eb90e830SDouglas Gregor if (!Parent) 313e89dbc1dSDouglas Gregor Modules[ModuleName] = Result; 314e89dbc1dSDouglas Gregor 315322f633cSDouglas Gregor // umbrella header "umbrella-header-name" 31673141fa9SDouglas Gregor Result->Umbrella = UmbrellaHeader; 31756c64013SDouglas Gregor Headers[UmbrellaHeader] = Result; 3184dc71835SDouglas Gregor UmbrellaDirs[UmbrellaHeader->getDir()] = Result; 319d8bd7537SDouglas Gregor 320d8bd7537SDouglas Gregor // export * 321d8bd7537SDouglas Gregor Result->Exports.push_back(Module::ExportDecl(0, true)); 322d8bd7537SDouglas Gregor 323a89c5ac4SDouglas Gregor // module * { export * } 324a89c5ac4SDouglas Gregor Result->InferSubmodules = true; 325a89c5ac4SDouglas Gregor Result->InferExportWildcard = true; 326a89c5ac4SDouglas Gregor 327e89dbc1dSDouglas Gregor // Look for subframeworks. 328e89dbc1dSDouglas Gregor llvm::error_code EC; 329ddaa69cbSDouglas Gregor llvm::SmallString<128> SubframeworksDirName 330ddaa69cbSDouglas Gregor = StringRef(FrameworkDir->getName()); 331e89dbc1dSDouglas Gregor llvm::sys::path::append(SubframeworksDirName, "Frameworks"); 332ddaa69cbSDouglas Gregor llvm::SmallString<128> SubframeworksDirNameNative; 333ddaa69cbSDouglas Gregor llvm::sys::path::native(SubframeworksDirName.str(), 334ddaa69cbSDouglas Gregor SubframeworksDirNameNative); 335ddaa69cbSDouglas Gregor for (llvm::sys::fs::directory_iterator 336ddaa69cbSDouglas Gregor Dir(SubframeworksDirNameNative.str(), EC), DirEnd; 337e89dbc1dSDouglas Gregor Dir != DirEnd && !EC; Dir.increment(EC)) { 338e89dbc1dSDouglas Gregor if (!StringRef(Dir->path()).endswith(".framework")) 339e89dbc1dSDouglas Gregor continue; 340f2161a70SDouglas Gregor 341e89dbc1dSDouglas Gregor if (const DirectoryEntry *SubframeworkDir 342e89dbc1dSDouglas Gregor = FileMgr.getDirectory(Dir->path())) { 343e89dbc1dSDouglas Gregor // FIXME: Do we want to warn about subframeworks without umbrella headers? 344e89dbc1dSDouglas Gregor inferFrameworkModule(llvm::sys::path::stem(Dir->path()), SubframeworkDir, 345*a686e1b0SDouglas Gregor IsSystem, Result); 346e89dbc1dSDouglas Gregor } 347e89dbc1dSDouglas Gregor } 348e89dbc1dSDouglas Gregor 34956c64013SDouglas Gregor return Result; 35056c64013SDouglas Gregor } 35156c64013SDouglas Gregor 352a89c5ac4SDouglas Gregor void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){ 353a89c5ac4SDouglas Gregor Headers[UmbrellaHeader] = Mod; 35473141fa9SDouglas Gregor Mod->Umbrella = UmbrellaHeader; 3557033127bSDouglas Gregor UmbrellaDirs[UmbrellaHeader->getDir()] = Mod; 356a89c5ac4SDouglas Gregor } 357a89c5ac4SDouglas Gregor 358524e33e1SDouglas Gregor void ModuleMap::setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir) { 359524e33e1SDouglas Gregor Mod->Umbrella = UmbrellaDir; 360524e33e1SDouglas Gregor UmbrellaDirs[UmbrellaDir] = Mod; 361524e33e1SDouglas Gregor } 362524e33e1SDouglas Gregor 363a89c5ac4SDouglas Gregor void ModuleMap::addHeader(Module *Mod, const FileEntry *Header) { 364a89c5ac4SDouglas Gregor Mod->Headers.push_back(Header); 365a89c5ac4SDouglas Gregor Headers[Header] = Mod; 366a89c5ac4SDouglas Gregor } 367a89c5ac4SDouglas Gregor 368514b636aSDouglas Gregor const FileEntry * 369de3ef502SDouglas Gregor ModuleMap::getContainingModuleMapFile(Module *Module) { 370514b636aSDouglas Gregor if (Module->DefinitionLoc.isInvalid() || !SourceMgr) 371514b636aSDouglas Gregor return 0; 372514b636aSDouglas Gregor 373514b636aSDouglas Gregor return SourceMgr->getFileEntryForID( 374514b636aSDouglas Gregor SourceMgr->getFileID(Module->DefinitionLoc)); 375514b636aSDouglas Gregor } 376514b636aSDouglas Gregor 377718292f2SDouglas Gregor void ModuleMap::dump() { 378718292f2SDouglas Gregor llvm::errs() << "Modules:"; 379718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 380718292f2SDouglas Gregor MEnd = Modules.end(); 381718292f2SDouglas Gregor M != MEnd; ++M) 382d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 383718292f2SDouglas Gregor 384718292f2SDouglas Gregor llvm::errs() << "Headers:"; 385718292f2SDouglas Gregor for (llvm::DenseMap<const FileEntry *, Module *>::iterator 386718292f2SDouglas Gregor H = Headers.begin(), 387718292f2SDouglas Gregor HEnd = Headers.end(); 388718292f2SDouglas Gregor H != HEnd; ++H) { 389718292f2SDouglas Gregor llvm::errs() << " \"" << H->first->getName() << "\" -> " 390718292f2SDouglas Gregor << H->second->getFullModuleName() << "\n"; 391718292f2SDouglas Gregor } 392718292f2SDouglas Gregor } 393718292f2SDouglas Gregor 3942b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) { 3952b82c2a5SDouglas Gregor bool HadError = false; 3962b82c2a5SDouglas Gregor for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) { 3972b82c2a5SDouglas Gregor Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I], 3982b82c2a5SDouglas Gregor Complain); 399f5eedd05SDouglas Gregor if (Export.getPointer() || Export.getInt()) 4002b82c2a5SDouglas Gregor Mod->Exports.push_back(Export); 4012b82c2a5SDouglas Gregor else 4022b82c2a5SDouglas Gregor HadError = true; 4032b82c2a5SDouglas Gregor } 4042b82c2a5SDouglas Gregor Mod->UnresolvedExports.clear(); 4052b82c2a5SDouglas Gregor return HadError; 4062b82c2a5SDouglas Gregor } 4072b82c2a5SDouglas Gregor 4080093b3c7SDouglas Gregor Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) { 4090093b3c7SDouglas Gregor if (Loc.isInvalid()) 4100093b3c7SDouglas Gregor return 0; 4110093b3c7SDouglas Gregor 4120093b3c7SDouglas Gregor // Use the expansion location to determine which module we're in. 4130093b3c7SDouglas Gregor FullSourceLoc ExpansionLoc = Loc.getExpansionLoc(); 4140093b3c7SDouglas Gregor if (!ExpansionLoc.isFileID()) 4150093b3c7SDouglas Gregor return 0; 4160093b3c7SDouglas Gregor 4170093b3c7SDouglas Gregor 4180093b3c7SDouglas Gregor const SourceManager &SrcMgr = Loc.getManager(); 4190093b3c7SDouglas Gregor FileID ExpansionFileID = ExpansionLoc.getFileID(); 420224d8a74SDouglas Gregor 421224d8a74SDouglas Gregor while (const FileEntry *ExpansionFile 422224d8a74SDouglas Gregor = SrcMgr.getFileEntryForID(ExpansionFileID)) { 423224d8a74SDouglas Gregor // Find the module that owns this header (if any). 424224d8a74SDouglas Gregor if (Module *Mod = findModuleForHeader(ExpansionFile)) 425224d8a74SDouglas Gregor return Mod; 426224d8a74SDouglas Gregor 427224d8a74SDouglas Gregor // No module owns this header, so look up the inclusion chain to see if 428224d8a74SDouglas Gregor // any included header has an associated module. 429224d8a74SDouglas Gregor SourceLocation IncludeLoc = SrcMgr.getIncludeLoc(ExpansionFileID); 430224d8a74SDouglas Gregor if (IncludeLoc.isInvalid()) 4310093b3c7SDouglas Gregor return 0; 4320093b3c7SDouglas Gregor 433224d8a74SDouglas Gregor ExpansionFileID = SrcMgr.getFileID(IncludeLoc); 434224d8a74SDouglas Gregor } 435224d8a74SDouglas Gregor 436224d8a74SDouglas Gregor return 0; 4370093b3c7SDouglas Gregor } 4380093b3c7SDouglas Gregor 439718292f2SDouglas Gregor //----------------------------------------------------------------------------// 440718292f2SDouglas Gregor // Module map file parser 441718292f2SDouglas Gregor //----------------------------------------------------------------------------// 442718292f2SDouglas Gregor 443718292f2SDouglas Gregor namespace clang { 444718292f2SDouglas Gregor /// \brief A token in a module map file. 445718292f2SDouglas Gregor struct MMToken { 446718292f2SDouglas Gregor enum TokenKind { 4471fb5c3a6SDouglas Gregor Comma, 448718292f2SDouglas Gregor EndOfFile, 449718292f2SDouglas Gregor HeaderKeyword, 450718292f2SDouglas Gregor Identifier, 451718292f2SDouglas Gregor ExplicitKeyword, 4522b82c2a5SDouglas Gregor ExportKeyword, 453755b2055SDouglas Gregor FrameworkKeyword, 454718292f2SDouglas Gregor ModuleKeyword, 4552b82c2a5SDouglas Gregor Period, 456718292f2SDouglas Gregor UmbrellaKeyword, 4571fb5c3a6SDouglas Gregor RequiresKeyword, 4582b82c2a5SDouglas Gregor Star, 459718292f2SDouglas Gregor StringLiteral, 460718292f2SDouglas Gregor LBrace, 461*a686e1b0SDouglas Gregor RBrace, 462*a686e1b0SDouglas Gregor LSquare, 463*a686e1b0SDouglas Gregor RSquare 464718292f2SDouglas Gregor } Kind; 465718292f2SDouglas Gregor 466718292f2SDouglas Gregor unsigned Location; 467718292f2SDouglas Gregor unsigned StringLength; 468718292f2SDouglas Gregor const char *StringData; 469718292f2SDouglas Gregor 470718292f2SDouglas Gregor void clear() { 471718292f2SDouglas Gregor Kind = EndOfFile; 472718292f2SDouglas Gregor Location = 0; 473718292f2SDouglas Gregor StringLength = 0; 474718292f2SDouglas Gregor StringData = 0; 475718292f2SDouglas Gregor } 476718292f2SDouglas Gregor 477718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 478718292f2SDouglas Gregor 479718292f2SDouglas Gregor SourceLocation getLocation() const { 480718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 481718292f2SDouglas Gregor } 482718292f2SDouglas Gregor 483718292f2SDouglas Gregor StringRef getString() const { 484718292f2SDouglas Gregor return StringRef(StringData, StringLength); 485718292f2SDouglas Gregor } 486718292f2SDouglas Gregor }; 487718292f2SDouglas Gregor 488718292f2SDouglas Gregor class ModuleMapParser { 489718292f2SDouglas Gregor Lexer &L; 490718292f2SDouglas Gregor SourceManager &SourceMgr; 491718292f2SDouglas Gregor DiagnosticsEngine &Diags; 492718292f2SDouglas Gregor ModuleMap ⤅ 493718292f2SDouglas Gregor 4945257fc63SDouglas Gregor /// \brief The directory that this module map resides in. 4955257fc63SDouglas Gregor const DirectoryEntry *Directory; 4965257fc63SDouglas Gregor 497718292f2SDouglas Gregor /// \brief Whether an error occurred. 498718292f2SDouglas Gregor bool HadError; 499718292f2SDouglas Gregor 500718292f2SDouglas Gregor /// \brief Default target information, used only for string literal 501718292f2SDouglas Gregor /// parsing. 502718292f2SDouglas Gregor TargetInfo *Target; 503718292f2SDouglas Gregor 504718292f2SDouglas Gregor /// \brief Stores string data for the various string literals referenced 505718292f2SDouglas Gregor /// during parsing. 506718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 507718292f2SDouglas Gregor 508718292f2SDouglas Gregor /// \brief The current token. 509718292f2SDouglas Gregor MMToken Tok; 510718292f2SDouglas Gregor 511718292f2SDouglas Gregor /// \brief The active module. 512de3ef502SDouglas Gregor Module *ActiveModule; 513718292f2SDouglas Gregor 514718292f2SDouglas Gregor /// \brief Consume the current token and return its location. 515718292f2SDouglas Gregor SourceLocation consumeToken(); 516718292f2SDouglas Gregor 517718292f2SDouglas Gregor /// \brief Skip tokens until we reach the a token with the given kind 518718292f2SDouglas Gregor /// (or the end of the file). 519718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 520718292f2SDouglas Gregor 521e7ab3669SDouglas Gregor typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2> 522e7ab3669SDouglas Gregor ModuleId; 523e7ab3669SDouglas Gregor bool parseModuleId(ModuleId &Id); 524718292f2SDouglas Gregor void parseModuleDecl(); 5251fb5c3a6SDouglas Gregor void parseRequiresDecl(); 526322f633cSDouglas Gregor void parseHeaderDecl(SourceLocation UmbrellaLoc); 527524e33e1SDouglas Gregor void parseUmbrellaDirDecl(SourceLocation UmbrellaLoc); 5282b82c2a5SDouglas Gregor void parseExportDecl(); 52973441091SDouglas Gregor void parseInferredSubmoduleDecl(bool Explicit); 530718292f2SDouglas Gregor 5317033127bSDouglas Gregor const DirectoryEntry *getOverriddenHeaderSearchDir(); 5327033127bSDouglas Gregor 533718292f2SDouglas Gregor public: 534718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 535718292f2SDouglas Gregor DiagnosticsEngine &Diags, 5365257fc63SDouglas Gregor ModuleMap &Map, 5375257fc63SDouglas Gregor const DirectoryEntry *Directory) 5385257fc63SDouglas Gregor : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map), 5395257fc63SDouglas Gregor Directory(Directory), HadError(false), ActiveModule(0) 540718292f2SDouglas Gregor { 541718292f2SDouglas Gregor TargetOptions TargetOpts; 542718292f2SDouglas Gregor TargetOpts.Triple = llvm::sys::getDefaultTargetTriple(); 543718292f2SDouglas Gregor Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); 544718292f2SDouglas Gregor 545718292f2SDouglas Gregor Tok.clear(); 546718292f2SDouglas Gregor consumeToken(); 547718292f2SDouglas Gregor } 548718292f2SDouglas Gregor 549718292f2SDouglas Gregor bool parseModuleMapFile(); 550718292f2SDouglas Gregor }; 551718292f2SDouglas Gregor } 552718292f2SDouglas Gregor 553718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 554718292f2SDouglas Gregor retry: 555718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 556718292f2SDouglas Gregor Tok.clear(); 557718292f2SDouglas Gregor 558718292f2SDouglas Gregor Token LToken; 559718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 560718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 561718292f2SDouglas Gregor switch (LToken.getKind()) { 562718292f2SDouglas Gregor case tok::raw_identifier: 563718292f2SDouglas Gregor Tok.StringData = LToken.getRawIdentifierData(); 564718292f2SDouglas Gregor Tok.StringLength = LToken.getLength(); 565718292f2SDouglas Gregor Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString()) 566718292f2SDouglas Gregor .Case("header", MMToken::HeaderKeyword) 567718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 5682b82c2a5SDouglas Gregor .Case("export", MMToken::ExportKeyword) 569755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 570718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 5711fb5c3a6SDouglas Gregor .Case("requires", MMToken::RequiresKeyword) 572718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 573718292f2SDouglas Gregor .Default(MMToken::Identifier); 574718292f2SDouglas Gregor break; 575718292f2SDouglas Gregor 5761fb5c3a6SDouglas Gregor case tok::comma: 5771fb5c3a6SDouglas Gregor Tok.Kind = MMToken::Comma; 5781fb5c3a6SDouglas Gregor break; 5791fb5c3a6SDouglas Gregor 580718292f2SDouglas Gregor case tok::eof: 581718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 582718292f2SDouglas Gregor break; 583718292f2SDouglas Gregor 584718292f2SDouglas Gregor case tok::l_brace: 585718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 586718292f2SDouglas Gregor break; 587718292f2SDouglas Gregor 588*a686e1b0SDouglas Gregor case tok::l_square: 589*a686e1b0SDouglas Gregor Tok.Kind = MMToken::LSquare; 590*a686e1b0SDouglas Gregor break; 591*a686e1b0SDouglas Gregor 5922b82c2a5SDouglas Gregor case tok::period: 5932b82c2a5SDouglas Gregor Tok.Kind = MMToken::Period; 5942b82c2a5SDouglas Gregor break; 5952b82c2a5SDouglas Gregor 596718292f2SDouglas Gregor case tok::r_brace: 597718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 598718292f2SDouglas Gregor break; 599718292f2SDouglas Gregor 600*a686e1b0SDouglas Gregor case tok::r_square: 601*a686e1b0SDouglas Gregor Tok.Kind = MMToken::RSquare; 602*a686e1b0SDouglas Gregor break; 603*a686e1b0SDouglas Gregor 6042b82c2a5SDouglas Gregor case tok::star: 6052b82c2a5SDouglas Gregor Tok.Kind = MMToken::Star; 6062b82c2a5SDouglas Gregor break; 6072b82c2a5SDouglas Gregor 608718292f2SDouglas Gregor case tok::string_literal: { 609718292f2SDouglas Gregor // Parse the string literal. 610718292f2SDouglas Gregor LangOptions LangOpts; 611718292f2SDouglas Gregor StringLiteralParser StringLiteral(<oken, 1, SourceMgr, LangOpts, *Target); 612718292f2SDouglas Gregor if (StringLiteral.hadError) 613718292f2SDouglas Gregor goto retry; 614718292f2SDouglas Gregor 615718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 616718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 617718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 618718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 619718292f2SDouglas Gregor Saved[Length] = 0; 620718292f2SDouglas Gregor 621718292f2SDouglas Gregor // Form the token. 622718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 623718292f2SDouglas Gregor Tok.StringData = Saved; 624718292f2SDouglas Gregor Tok.StringLength = Length; 625718292f2SDouglas Gregor break; 626718292f2SDouglas Gregor } 627718292f2SDouglas Gregor 628718292f2SDouglas Gregor case tok::comment: 629718292f2SDouglas Gregor goto retry; 630718292f2SDouglas Gregor 631718292f2SDouglas Gregor default: 632718292f2SDouglas Gregor Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token); 633718292f2SDouglas Gregor HadError = true; 634718292f2SDouglas Gregor goto retry; 635718292f2SDouglas Gregor } 636718292f2SDouglas Gregor 637718292f2SDouglas Gregor return Result; 638718292f2SDouglas Gregor } 639718292f2SDouglas Gregor 640718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 641718292f2SDouglas Gregor unsigned braceDepth = 0; 642*a686e1b0SDouglas Gregor unsigned squareDepth = 0; 643718292f2SDouglas Gregor do { 644718292f2SDouglas Gregor switch (Tok.Kind) { 645718292f2SDouglas Gregor case MMToken::EndOfFile: 646718292f2SDouglas Gregor return; 647718292f2SDouglas Gregor 648718292f2SDouglas Gregor case MMToken::LBrace: 649*a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 650718292f2SDouglas Gregor return; 651718292f2SDouglas Gregor 652718292f2SDouglas Gregor ++braceDepth; 653718292f2SDouglas Gregor break; 654718292f2SDouglas Gregor 655*a686e1b0SDouglas Gregor case MMToken::LSquare: 656*a686e1b0SDouglas Gregor if (Tok.is(K) && braceDepth == 0 && squareDepth == 0) 657*a686e1b0SDouglas Gregor return; 658*a686e1b0SDouglas Gregor 659*a686e1b0SDouglas Gregor ++squareDepth; 660*a686e1b0SDouglas Gregor break; 661*a686e1b0SDouglas Gregor 662718292f2SDouglas Gregor case MMToken::RBrace: 663718292f2SDouglas Gregor if (braceDepth > 0) 664718292f2SDouglas Gregor --braceDepth; 665718292f2SDouglas Gregor else if (Tok.is(K)) 666718292f2SDouglas Gregor return; 667718292f2SDouglas Gregor break; 668718292f2SDouglas Gregor 669*a686e1b0SDouglas Gregor case MMToken::RSquare: 670*a686e1b0SDouglas Gregor if (squareDepth > 0) 671*a686e1b0SDouglas Gregor --squareDepth; 672*a686e1b0SDouglas Gregor else if (Tok.is(K)) 673*a686e1b0SDouglas Gregor return; 674*a686e1b0SDouglas Gregor break; 675*a686e1b0SDouglas Gregor 676718292f2SDouglas Gregor default: 677*a686e1b0SDouglas Gregor if (braceDepth == 0 && squareDepth == 0 && Tok.is(K)) 678718292f2SDouglas Gregor return; 679718292f2SDouglas Gregor break; 680718292f2SDouglas Gregor } 681718292f2SDouglas Gregor 682718292f2SDouglas Gregor consumeToken(); 683718292f2SDouglas Gregor } while (true); 684718292f2SDouglas Gregor } 685718292f2SDouglas Gregor 686e7ab3669SDouglas Gregor /// \brief Parse a module-id. 687e7ab3669SDouglas Gregor /// 688e7ab3669SDouglas Gregor /// module-id: 689e7ab3669SDouglas Gregor /// identifier 690e7ab3669SDouglas Gregor /// identifier '.' module-id 691e7ab3669SDouglas Gregor /// 692e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise. 693e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) { 694e7ab3669SDouglas Gregor Id.clear(); 695e7ab3669SDouglas Gregor do { 696e7ab3669SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 697e7ab3669SDouglas Gregor Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation())); 698e7ab3669SDouglas Gregor consumeToken(); 699e7ab3669SDouglas Gregor } else { 700e7ab3669SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 701e7ab3669SDouglas Gregor return true; 702e7ab3669SDouglas Gregor } 703e7ab3669SDouglas Gregor 704e7ab3669SDouglas Gregor if (!Tok.is(MMToken::Period)) 705e7ab3669SDouglas Gregor break; 706e7ab3669SDouglas Gregor 707e7ab3669SDouglas Gregor consumeToken(); 708e7ab3669SDouglas Gregor } while (true); 709e7ab3669SDouglas Gregor 710e7ab3669SDouglas Gregor return false; 711e7ab3669SDouglas Gregor } 712e7ab3669SDouglas Gregor 713*a686e1b0SDouglas Gregor namespace { 714*a686e1b0SDouglas Gregor /// \brief Enumerates the known attributes. 715*a686e1b0SDouglas Gregor enum AttributeKind { 716*a686e1b0SDouglas Gregor /// \brief An unknown attribute. 717*a686e1b0SDouglas Gregor AT_unknown, 718*a686e1b0SDouglas Gregor /// \brief The 'system' attribute. 719*a686e1b0SDouglas Gregor AT_system 720*a686e1b0SDouglas Gregor }; 721*a686e1b0SDouglas Gregor } 722*a686e1b0SDouglas Gregor 723718292f2SDouglas Gregor /// \brief Parse a module declaration. 724718292f2SDouglas Gregor /// 725718292f2SDouglas Gregor /// module-declaration: 726*a686e1b0SDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' module-id attributes[opt] 727*a686e1b0SDouglas Gregor /// { module-member* } 728*a686e1b0SDouglas Gregor /// 729*a686e1b0SDouglas Gregor /// attributes: 730*a686e1b0SDouglas Gregor /// attribute attributes 731*a686e1b0SDouglas Gregor /// attribute 732*a686e1b0SDouglas Gregor /// 733*a686e1b0SDouglas Gregor /// attribute: 734*a686e1b0SDouglas Gregor /// [ identifier ] 735718292f2SDouglas Gregor /// 736718292f2SDouglas Gregor /// module-member: 7371fb5c3a6SDouglas Gregor /// requires-declaration 738718292f2SDouglas Gregor /// header-declaration 739e7ab3669SDouglas Gregor /// submodule-declaration 7402b82c2a5SDouglas Gregor /// export-declaration 74173441091SDouglas Gregor /// 74273441091SDouglas Gregor /// submodule-declaration: 74373441091SDouglas Gregor /// module-declaration 74473441091SDouglas Gregor /// inferred-submodule-declaration 745718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 746755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 747755b2055SDouglas Gregor Tok.is(MMToken::FrameworkKeyword)); 748f2161a70SDouglas Gregor // Parse 'explicit' or 'framework' keyword, if present. 749e7ab3669SDouglas Gregor SourceLocation ExplicitLoc; 750718292f2SDouglas Gregor bool Explicit = false; 751f2161a70SDouglas Gregor bool Framework = false; 752755b2055SDouglas Gregor 753f2161a70SDouglas Gregor // Parse 'explicit' keyword, if present. 754f2161a70SDouglas Gregor if (Tok.is(MMToken::ExplicitKeyword)) { 755e7ab3669SDouglas Gregor ExplicitLoc = consumeToken(); 756f2161a70SDouglas Gregor Explicit = true; 757f2161a70SDouglas Gregor } 758f2161a70SDouglas Gregor 759f2161a70SDouglas Gregor // Parse 'framework' keyword, if present. 760755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 761755b2055SDouglas Gregor consumeToken(); 762755b2055SDouglas Gregor Framework = true; 763755b2055SDouglas Gregor } 764718292f2SDouglas Gregor 765718292f2SDouglas Gregor // Parse 'module' keyword. 766718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 767d6343c99SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 768718292f2SDouglas Gregor consumeToken(); 769718292f2SDouglas Gregor HadError = true; 770718292f2SDouglas Gregor return; 771718292f2SDouglas Gregor } 772718292f2SDouglas Gregor consumeToken(); // 'module' keyword 773718292f2SDouglas Gregor 77473441091SDouglas Gregor // If we have a wildcard for the module name, this is an inferred submodule. 77573441091SDouglas Gregor // Parse it. 77673441091SDouglas Gregor if (Tok.is(MMToken::Star)) 77773441091SDouglas Gregor return parseInferredSubmoduleDecl(Explicit); 77873441091SDouglas Gregor 779718292f2SDouglas Gregor // Parse the module name. 780e7ab3669SDouglas Gregor ModuleId Id; 781e7ab3669SDouglas Gregor if (parseModuleId(Id)) { 782718292f2SDouglas Gregor HadError = true; 783718292f2SDouglas Gregor return; 784718292f2SDouglas Gregor } 785e7ab3669SDouglas Gregor 786e7ab3669SDouglas Gregor if (ActiveModule) { 787e7ab3669SDouglas Gregor if (Id.size() > 1) { 788e7ab3669SDouglas Gregor Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id) 789e7ab3669SDouglas Gregor << SourceRange(Id.front().second, Id.back().second); 790e7ab3669SDouglas Gregor 791e7ab3669SDouglas Gregor HadError = true; 792e7ab3669SDouglas Gregor return; 793e7ab3669SDouglas Gregor } 794e7ab3669SDouglas Gregor } else if (Id.size() == 1 && Explicit) { 795e7ab3669SDouglas Gregor // Top-level modules can't be explicit. 796e7ab3669SDouglas Gregor Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level); 797e7ab3669SDouglas Gregor Explicit = false; 798e7ab3669SDouglas Gregor ExplicitLoc = SourceLocation(); 799e7ab3669SDouglas Gregor HadError = true; 800e7ab3669SDouglas Gregor } 801e7ab3669SDouglas Gregor 802e7ab3669SDouglas Gregor Module *PreviousActiveModule = ActiveModule; 803e7ab3669SDouglas Gregor if (Id.size() > 1) { 804e7ab3669SDouglas Gregor // This module map defines a submodule. Go find the module of which it 805e7ab3669SDouglas Gregor // is a submodule. 806e7ab3669SDouglas Gregor ActiveModule = 0; 807e7ab3669SDouglas Gregor for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) { 808e7ab3669SDouglas Gregor if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) { 809e7ab3669SDouglas Gregor ActiveModule = Next; 810e7ab3669SDouglas Gregor continue; 811e7ab3669SDouglas Gregor } 812e7ab3669SDouglas Gregor 813e7ab3669SDouglas Gregor if (ActiveModule) { 814e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified) 815e7ab3669SDouglas Gregor << Id[I].first << ActiveModule->getTopLevelModule(); 816e7ab3669SDouglas Gregor } else { 817e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_expected_module_name); 818e7ab3669SDouglas Gregor } 819e7ab3669SDouglas Gregor HadError = true; 820e7ab3669SDouglas Gregor return; 821e7ab3669SDouglas Gregor } 822e7ab3669SDouglas Gregor } 823e7ab3669SDouglas Gregor 824e7ab3669SDouglas Gregor StringRef ModuleName = Id.back().first; 825e7ab3669SDouglas Gregor SourceLocation ModuleNameLoc = Id.back().second; 826718292f2SDouglas Gregor 827*a686e1b0SDouglas Gregor // Parse the optional attribute list. 828*a686e1b0SDouglas Gregor bool IsSystem = false; 829*a686e1b0SDouglas Gregor while (Tok.is(MMToken::LSquare)) { 830*a686e1b0SDouglas Gregor // Consume the '['. 831*a686e1b0SDouglas Gregor SourceLocation LSquareLoc = consumeToken(); 832*a686e1b0SDouglas Gregor 833*a686e1b0SDouglas Gregor // Check whether we have an attribute name here. 834*a686e1b0SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 835*a686e1b0SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_attribute); 836*a686e1b0SDouglas Gregor skipUntil(MMToken::RSquare); 837*a686e1b0SDouglas Gregor if (Tok.is(MMToken::RSquare)) 838*a686e1b0SDouglas Gregor consumeToken(); 839*a686e1b0SDouglas Gregor continue; 840*a686e1b0SDouglas Gregor } 841*a686e1b0SDouglas Gregor 842*a686e1b0SDouglas Gregor // Decode the attribute name. 843*a686e1b0SDouglas Gregor AttributeKind Attribute 844*a686e1b0SDouglas Gregor = llvm::StringSwitch<AttributeKind>(Tok.getString()) 845*a686e1b0SDouglas Gregor .Case("system", AT_system) 846*a686e1b0SDouglas Gregor .Default(AT_unknown); 847*a686e1b0SDouglas Gregor switch (Attribute) { 848*a686e1b0SDouglas Gregor case AT_unknown: 849*a686e1b0SDouglas Gregor Diags.Report(Tok.getLocation(), diag::warn_mmap_unknown_attribute) 850*a686e1b0SDouglas Gregor << Tok.getString(); 851*a686e1b0SDouglas Gregor break; 852*a686e1b0SDouglas Gregor 853*a686e1b0SDouglas Gregor case AT_system: 854*a686e1b0SDouglas Gregor IsSystem = true; 855*a686e1b0SDouglas Gregor break; 856*a686e1b0SDouglas Gregor } 857*a686e1b0SDouglas Gregor consumeToken(); 858*a686e1b0SDouglas Gregor 859*a686e1b0SDouglas Gregor // Consume the ']'. 860*a686e1b0SDouglas Gregor if (!Tok.is(MMToken::RSquare)) { 861*a686e1b0SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rsquare); 862*a686e1b0SDouglas Gregor Diags.Report(LSquareLoc, diag::note_mmap_lsquare_match); 863*a686e1b0SDouglas Gregor skipUntil(MMToken::RSquare); 864*a686e1b0SDouglas Gregor } 865*a686e1b0SDouglas Gregor 866*a686e1b0SDouglas Gregor if (Tok.is(MMToken::RSquare)) 867*a686e1b0SDouglas Gregor consumeToken(); 868*a686e1b0SDouglas Gregor } 869*a686e1b0SDouglas Gregor 870718292f2SDouglas Gregor // Parse the opening brace. 871718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 872718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 873718292f2SDouglas Gregor << ModuleName; 874718292f2SDouglas Gregor HadError = true; 875718292f2SDouglas Gregor return; 876718292f2SDouglas Gregor } 877718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 878718292f2SDouglas Gregor 879718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 880eb90e830SDouglas Gregor if (Module *Existing = Map.lookupModuleQualified(ModuleName, ActiveModule)) { 881fcc54a3bSDouglas Gregor if (Existing->DefinitionLoc.isInvalid() && !ActiveModule) { 882fcc54a3bSDouglas Gregor // Skip the module definition. 883fcc54a3bSDouglas Gregor skipUntil(MMToken::RBrace); 884fcc54a3bSDouglas Gregor if (Tok.is(MMToken::RBrace)) 885fcc54a3bSDouglas Gregor consumeToken(); 886fcc54a3bSDouglas Gregor else { 887fcc54a3bSDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 888fcc54a3bSDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 889fcc54a3bSDouglas Gregor HadError = true; 890fcc54a3bSDouglas Gregor } 891fcc54a3bSDouglas Gregor return; 892fcc54a3bSDouglas Gregor } 893fcc54a3bSDouglas Gregor 894718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 895718292f2SDouglas Gregor << ModuleName; 896eb90e830SDouglas Gregor Diags.Report(Existing->DefinitionLoc, diag::note_mmap_prev_definition); 897718292f2SDouglas Gregor 898718292f2SDouglas Gregor // Skip the module definition. 899718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 900718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 901718292f2SDouglas Gregor consumeToken(); 902718292f2SDouglas Gregor 903718292f2SDouglas Gregor HadError = true; 904718292f2SDouglas Gregor return; 905718292f2SDouglas Gregor } 906718292f2SDouglas Gregor 907718292f2SDouglas Gregor // Start defining this module. 908eb90e830SDouglas Gregor ActiveModule = Map.findOrCreateModule(ModuleName, ActiveModule, Framework, 909eb90e830SDouglas Gregor Explicit).first; 910eb90e830SDouglas Gregor ActiveModule->DefinitionLoc = ModuleNameLoc; 911*a686e1b0SDouglas Gregor if (IsSystem) 912*a686e1b0SDouglas Gregor ActiveModule->IsSystem = true; 913718292f2SDouglas Gregor 914718292f2SDouglas Gregor bool Done = false; 915718292f2SDouglas Gregor do { 916718292f2SDouglas Gregor switch (Tok.Kind) { 917718292f2SDouglas Gregor case MMToken::EndOfFile: 918718292f2SDouglas Gregor case MMToken::RBrace: 919718292f2SDouglas Gregor Done = true; 920718292f2SDouglas Gregor break; 921718292f2SDouglas Gregor 922718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 923f2161a70SDouglas Gregor case MMToken::FrameworkKeyword: 924718292f2SDouglas Gregor case MMToken::ModuleKeyword: 925718292f2SDouglas Gregor parseModuleDecl(); 926718292f2SDouglas Gregor break; 927718292f2SDouglas Gregor 9282b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 9292b82c2a5SDouglas Gregor parseExportDecl(); 9302b82c2a5SDouglas Gregor break; 9312b82c2a5SDouglas Gregor 9321fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 9331fb5c3a6SDouglas Gregor parseRequiresDecl(); 9341fb5c3a6SDouglas Gregor break; 9351fb5c3a6SDouglas Gregor 936524e33e1SDouglas Gregor case MMToken::UmbrellaKeyword: { 937524e33e1SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 938524e33e1SDouglas Gregor if (Tok.is(MMToken::HeaderKeyword)) 939524e33e1SDouglas Gregor parseHeaderDecl(UmbrellaLoc); 940524e33e1SDouglas Gregor else 941524e33e1SDouglas Gregor parseUmbrellaDirDecl(UmbrellaLoc); 942718292f2SDouglas Gregor break; 943524e33e1SDouglas Gregor } 944718292f2SDouglas Gregor 945322f633cSDouglas Gregor case MMToken::HeaderKeyword: 946322f633cSDouglas Gregor parseHeaderDecl(SourceLocation()); 947718292f2SDouglas Gregor break; 948718292f2SDouglas Gregor 949718292f2SDouglas Gregor default: 950718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 951718292f2SDouglas Gregor consumeToken(); 952718292f2SDouglas Gregor break; 953718292f2SDouglas Gregor } 954718292f2SDouglas Gregor } while (!Done); 955718292f2SDouglas Gregor 956718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 957718292f2SDouglas Gregor consumeToken(); 958718292f2SDouglas Gregor else { 959718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 960718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 961718292f2SDouglas Gregor HadError = true; 962718292f2SDouglas Gregor } 963718292f2SDouglas Gregor 964e7ab3669SDouglas Gregor // We're done parsing this module. Pop back to the previous module. 965e7ab3669SDouglas Gregor ActiveModule = PreviousActiveModule; 966718292f2SDouglas Gregor } 967718292f2SDouglas Gregor 9681fb5c3a6SDouglas Gregor /// \brief Parse a requires declaration. 9691fb5c3a6SDouglas Gregor /// 9701fb5c3a6SDouglas Gregor /// requires-declaration: 9711fb5c3a6SDouglas Gregor /// 'requires' feature-list 9721fb5c3a6SDouglas Gregor /// 9731fb5c3a6SDouglas Gregor /// feature-list: 9741fb5c3a6SDouglas Gregor /// identifier ',' feature-list 9751fb5c3a6SDouglas Gregor /// identifier 9761fb5c3a6SDouglas Gregor void ModuleMapParser::parseRequiresDecl() { 9771fb5c3a6SDouglas Gregor assert(Tok.is(MMToken::RequiresKeyword)); 9781fb5c3a6SDouglas Gregor 9791fb5c3a6SDouglas Gregor // Parse 'requires' keyword. 9801fb5c3a6SDouglas Gregor consumeToken(); 9811fb5c3a6SDouglas Gregor 9821fb5c3a6SDouglas Gregor // Parse the feature-list. 9831fb5c3a6SDouglas Gregor do { 9841fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 9851fb5c3a6SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_feature); 9861fb5c3a6SDouglas Gregor HadError = true; 9871fb5c3a6SDouglas Gregor return; 9881fb5c3a6SDouglas Gregor } 9891fb5c3a6SDouglas Gregor 9901fb5c3a6SDouglas Gregor // Consume the feature name. 9911fb5c3a6SDouglas Gregor std::string Feature = Tok.getString(); 9921fb5c3a6SDouglas Gregor consumeToken(); 9931fb5c3a6SDouglas Gregor 9941fb5c3a6SDouglas Gregor // Add this feature. 9951fb5c3a6SDouglas Gregor ActiveModule->addRequirement(Feature, Map.LangOpts); 9961fb5c3a6SDouglas Gregor 9971fb5c3a6SDouglas Gregor if (!Tok.is(MMToken::Comma)) 9981fb5c3a6SDouglas Gregor break; 9991fb5c3a6SDouglas Gregor 10001fb5c3a6SDouglas Gregor // Consume the comma. 10011fb5c3a6SDouglas Gregor consumeToken(); 10021fb5c3a6SDouglas Gregor } while (true); 10031fb5c3a6SDouglas Gregor } 10041fb5c3a6SDouglas Gregor 1005f2161a70SDouglas Gregor /// \brief Append to \p Paths the set of paths needed to get to the 1006f2161a70SDouglas Gregor /// subframework in which the given module lives. 1007f2161a70SDouglas Gregor void appendSubframeworkPaths(Module *Mod, llvm::SmallVectorImpl<char> &Path) { 1008f2161a70SDouglas Gregor // Collect the framework names from the given module to the top-level module. 1009f2161a70SDouglas Gregor llvm::SmallVector<StringRef, 2> Paths; 1010f2161a70SDouglas Gregor for (; Mod; Mod = Mod->Parent) { 1011f2161a70SDouglas Gregor if (Mod->IsFramework) 1012f2161a70SDouglas Gregor Paths.push_back(Mod->Name); 1013f2161a70SDouglas Gregor } 1014f2161a70SDouglas Gregor 1015f2161a70SDouglas Gregor if (Paths.empty()) 1016f2161a70SDouglas Gregor return; 1017f2161a70SDouglas Gregor 1018f2161a70SDouglas Gregor // Add Frameworks/Name.framework for each subframework. 1019f2161a70SDouglas Gregor for (unsigned I = Paths.size() - 1; I != 0; --I) { 1020f2161a70SDouglas Gregor llvm::sys::path::append(Path, "Frameworks"); 1021f2161a70SDouglas Gregor llvm::sys::path::append(Path, Paths[I-1] + ".framework"); 1022f2161a70SDouglas Gregor } 1023f2161a70SDouglas Gregor } 1024f2161a70SDouglas Gregor 1025718292f2SDouglas Gregor /// \brief Parse a header declaration. 1026718292f2SDouglas Gregor /// 1027718292f2SDouglas Gregor /// header-declaration: 1028322f633cSDouglas Gregor /// 'umbrella'[opt] 'header' string-literal 1029322f633cSDouglas Gregor void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) { 1030718292f2SDouglas Gregor assert(Tok.is(MMToken::HeaderKeyword)); 10311871ed3dSBenjamin Kramer consumeToken(); 1032718292f2SDouglas Gregor 1033322f633cSDouglas Gregor bool Umbrella = UmbrellaLoc.isValid(); 1034322f633cSDouglas Gregor 1035718292f2SDouglas Gregor // Parse the header name. 1036718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 1037718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 1038718292f2SDouglas Gregor << "header"; 1039718292f2SDouglas Gregor HadError = true; 1040718292f2SDouglas Gregor return; 1041718292f2SDouglas Gregor } 1042e7ab3669SDouglas Gregor std::string FileName = Tok.getString(); 1043718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 1044718292f2SDouglas Gregor 1045524e33e1SDouglas Gregor // Check whether we already have an umbrella. 1046524e33e1SDouglas Gregor if (Umbrella && ActiveModule->Umbrella) { 1047524e33e1SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_umbrella_clash) 1048524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 1049322f633cSDouglas Gregor HadError = true; 1050322f633cSDouglas Gregor return; 1051322f633cSDouglas Gregor } 1052322f633cSDouglas Gregor 10535257fc63SDouglas Gregor // Look for this file. 1054e7ab3669SDouglas Gregor const FileEntry *File = 0; 10555257fc63SDouglas Gregor llvm::SmallString<128> PathName; 1056e7ab3669SDouglas Gregor if (llvm::sys::path::is_absolute(FileName)) { 1057e7ab3669SDouglas Gregor PathName = FileName; 1058e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 10597033127bSDouglas Gregor } else if (const DirectoryEntry *Dir = getOverriddenHeaderSearchDir()) { 10607033127bSDouglas Gregor PathName = Dir->getName(); 10617033127bSDouglas Gregor llvm::sys::path::append(PathName, FileName); 10627033127bSDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 1063e7ab3669SDouglas Gregor } else { 1064e7ab3669SDouglas Gregor // Search for the header file within the search directory. 10657033127bSDouglas Gregor PathName = Directory->getName(); 1066e7ab3669SDouglas Gregor unsigned PathLength = PathName.size(); 1067755b2055SDouglas Gregor 1068f2161a70SDouglas Gregor if (ActiveModule->isPartOfFramework()) { 1069f2161a70SDouglas Gregor appendSubframeworkPaths(ActiveModule, PathName); 1070755b2055SDouglas Gregor 1071e7ab3669SDouglas Gregor // Check whether this file is in the public headers. 1072e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, "Headers"); 10735257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 1074e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 1075e7ab3669SDouglas Gregor 1076e7ab3669SDouglas Gregor if (!File) { 1077e7ab3669SDouglas Gregor // Check whether this file is in the private headers. 1078e7ab3669SDouglas Gregor PathName.resize(PathLength); 1079e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, "PrivateHeaders"); 1080e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, FileName); 1081e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 1082e7ab3669SDouglas Gregor } 1083e7ab3669SDouglas Gregor } else { 1084e7ab3669SDouglas Gregor // Lookup for normal headers. 1085e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, FileName); 1086e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 1087e7ab3669SDouglas Gregor } 1088e7ab3669SDouglas Gregor } 10895257fc63SDouglas Gregor 10905257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 10915257fc63SDouglas Gregor // Come up with a lazy way to do this. 1092e7ab3669SDouglas Gregor if (File) { 10935257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 10945257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 10955257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 10965257fc63SDouglas Gregor HadError = true; 1097322f633cSDouglas Gregor } else if (Umbrella) { 1098322f633cSDouglas Gregor const DirectoryEntry *UmbrellaDir = File->getDir(); 1099322f633cSDouglas Gregor if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) { 1100322f633cSDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 1101322f633cSDouglas Gregor << OwningModule->getFullModuleName(); 1102322f633cSDouglas Gregor HadError = true; 11035257fc63SDouglas Gregor } else { 1104322f633cSDouglas Gregor // Record this umbrella header. 1105322f633cSDouglas Gregor Map.setUmbrellaHeader(ActiveModule, File); 1106322f633cSDouglas Gregor } 1107322f633cSDouglas Gregor } else { 1108322f633cSDouglas Gregor // Record this header. 1109a89c5ac4SDouglas Gregor Map.addHeader(ActiveModule, File); 11105257fc63SDouglas Gregor } 11115257fc63SDouglas Gregor } else { 11125257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 1113524e33e1SDouglas Gregor << Umbrella << FileName; 11145257fc63SDouglas Gregor HadError = true; 11155257fc63SDouglas Gregor } 1116718292f2SDouglas Gregor } 1117718292f2SDouglas Gregor 1118524e33e1SDouglas Gregor /// \brief Parse an umbrella directory declaration. 1119524e33e1SDouglas Gregor /// 1120524e33e1SDouglas Gregor /// umbrella-dir-declaration: 1121524e33e1SDouglas Gregor /// umbrella string-literal 1122524e33e1SDouglas Gregor void ModuleMapParser::parseUmbrellaDirDecl(SourceLocation UmbrellaLoc) { 1123524e33e1SDouglas Gregor // Parse the directory name. 1124524e33e1SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 1125524e33e1SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 1126524e33e1SDouglas Gregor << "umbrella"; 1127524e33e1SDouglas Gregor HadError = true; 1128524e33e1SDouglas Gregor return; 1129524e33e1SDouglas Gregor } 1130524e33e1SDouglas Gregor 1131524e33e1SDouglas Gregor std::string DirName = Tok.getString(); 1132524e33e1SDouglas Gregor SourceLocation DirNameLoc = consumeToken(); 1133524e33e1SDouglas Gregor 1134524e33e1SDouglas Gregor // Check whether we already have an umbrella. 1135524e33e1SDouglas Gregor if (ActiveModule->Umbrella) { 1136524e33e1SDouglas Gregor Diags.Report(DirNameLoc, diag::err_mmap_umbrella_clash) 1137524e33e1SDouglas Gregor << ActiveModule->getFullModuleName(); 1138524e33e1SDouglas Gregor HadError = true; 1139524e33e1SDouglas Gregor return; 1140524e33e1SDouglas Gregor } 1141524e33e1SDouglas Gregor 1142524e33e1SDouglas Gregor // Look for this file. 1143524e33e1SDouglas Gregor const DirectoryEntry *Dir = 0; 1144524e33e1SDouglas Gregor if (llvm::sys::path::is_absolute(DirName)) 1145524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(DirName); 1146524e33e1SDouglas Gregor else { 1147524e33e1SDouglas Gregor llvm::SmallString<128> PathName; 1148524e33e1SDouglas Gregor PathName = Directory->getName(); 1149524e33e1SDouglas Gregor llvm::sys::path::append(PathName, DirName); 1150524e33e1SDouglas Gregor Dir = SourceMgr.getFileManager().getDirectory(PathName); 1151524e33e1SDouglas Gregor } 1152524e33e1SDouglas Gregor 1153524e33e1SDouglas Gregor if (!Dir) { 1154524e33e1SDouglas Gregor Diags.Report(DirNameLoc, diag::err_mmap_umbrella_dir_not_found) 1155524e33e1SDouglas Gregor << DirName; 1156524e33e1SDouglas Gregor HadError = true; 1157524e33e1SDouglas Gregor return; 1158524e33e1SDouglas Gregor } 1159524e33e1SDouglas Gregor 1160524e33e1SDouglas Gregor if (Module *OwningModule = Map.UmbrellaDirs[Dir]) { 1161524e33e1SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 1162524e33e1SDouglas Gregor << OwningModule->getFullModuleName(); 1163524e33e1SDouglas Gregor HadError = true; 1164524e33e1SDouglas Gregor return; 1165524e33e1SDouglas Gregor } 1166524e33e1SDouglas Gregor 1167524e33e1SDouglas Gregor // Record this umbrella directory. 1168524e33e1SDouglas Gregor Map.setUmbrellaDir(ActiveModule, Dir); 1169524e33e1SDouglas Gregor } 1170524e33e1SDouglas Gregor 11712b82c2a5SDouglas Gregor /// \brief Parse a module export declaration. 11722b82c2a5SDouglas Gregor /// 11732b82c2a5SDouglas Gregor /// export-declaration: 11742b82c2a5SDouglas Gregor /// 'export' wildcard-module-id 11752b82c2a5SDouglas Gregor /// 11762b82c2a5SDouglas Gregor /// wildcard-module-id: 11772b82c2a5SDouglas Gregor /// identifier 11782b82c2a5SDouglas Gregor /// '*' 11792b82c2a5SDouglas Gregor /// identifier '.' wildcard-module-id 11802b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() { 11812b82c2a5SDouglas Gregor assert(Tok.is(MMToken::ExportKeyword)); 11822b82c2a5SDouglas Gregor SourceLocation ExportLoc = consumeToken(); 11832b82c2a5SDouglas Gregor 11842b82c2a5SDouglas Gregor // Parse the module-id with an optional wildcard at the end. 11852b82c2a5SDouglas Gregor ModuleId ParsedModuleId; 11862b82c2a5SDouglas Gregor bool Wildcard = false; 11872b82c2a5SDouglas Gregor do { 11882b82c2a5SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 11892b82c2a5SDouglas Gregor ParsedModuleId.push_back(std::make_pair(Tok.getString(), 11902b82c2a5SDouglas Gregor Tok.getLocation())); 11912b82c2a5SDouglas Gregor consumeToken(); 11922b82c2a5SDouglas Gregor 11932b82c2a5SDouglas Gregor if (Tok.is(MMToken::Period)) { 11942b82c2a5SDouglas Gregor consumeToken(); 11952b82c2a5SDouglas Gregor continue; 11962b82c2a5SDouglas Gregor } 11972b82c2a5SDouglas Gregor 11982b82c2a5SDouglas Gregor break; 11992b82c2a5SDouglas Gregor } 12002b82c2a5SDouglas Gregor 12012b82c2a5SDouglas Gregor if(Tok.is(MMToken::Star)) { 12022b82c2a5SDouglas Gregor Wildcard = true; 1203f5eedd05SDouglas Gregor consumeToken(); 12042b82c2a5SDouglas Gregor break; 12052b82c2a5SDouglas Gregor } 12062b82c2a5SDouglas Gregor 12072b82c2a5SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id); 12082b82c2a5SDouglas Gregor HadError = true; 12092b82c2a5SDouglas Gregor return; 12102b82c2a5SDouglas Gregor } while (true); 12112b82c2a5SDouglas Gregor 12122b82c2a5SDouglas Gregor Module::UnresolvedExportDecl Unresolved = { 12132b82c2a5SDouglas Gregor ExportLoc, ParsedModuleId, Wildcard 12142b82c2a5SDouglas Gregor }; 12152b82c2a5SDouglas Gregor ActiveModule->UnresolvedExports.push_back(Unresolved); 12162b82c2a5SDouglas Gregor } 12172b82c2a5SDouglas Gregor 121873441091SDouglas Gregor void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) { 121973441091SDouglas Gregor assert(Tok.is(MMToken::Star)); 122073441091SDouglas Gregor SourceLocation StarLoc = consumeToken(); 122173441091SDouglas Gregor bool Failed = false; 122273441091SDouglas Gregor 122373441091SDouglas Gregor // Inferred modules must be submodules. 122473441091SDouglas Gregor if (!ActiveModule) { 122573441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule); 122673441091SDouglas Gregor Failed = true; 122773441091SDouglas Gregor } 122873441091SDouglas Gregor 1229524e33e1SDouglas Gregor // Inferred modules must have umbrella directories. 1230524e33e1SDouglas Gregor if (!Failed && !ActiveModule->getUmbrellaDir()) { 123173441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); 123273441091SDouglas Gregor Failed = true; 123373441091SDouglas Gregor } 123473441091SDouglas Gregor 123573441091SDouglas Gregor // Check for redefinition of an inferred module. 1236dd005f69SDouglas Gregor if (!Failed && ActiveModule->InferSubmodules) { 123773441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_redef); 1238dd005f69SDouglas Gregor if (ActiveModule->InferredSubmoduleLoc.isValid()) 1239dd005f69SDouglas Gregor Diags.Report(ActiveModule->InferredSubmoduleLoc, 124073441091SDouglas Gregor diag::note_mmap_prev_definition); 124173441091SDouglas Gregor Failed = true; 124273441091SDouglas Gregor } 124373441091SDouglas Gregor 124473441091SDouglas Gregor // If there were any problems with this inferred submodule, skip its body. 124573441091SDouglas Gregor if (Failed) { 124673441091SDouglas Gregor if (Tok.is(MMToken::LBrace)) { 124773441091SDouglas Gregor consumeToken(); 124873441091SDouglas Gregor skipUntil(MMToken::RBrace); 124973441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 125073441091SDouglas Gregor consumeToken(); 125173441091SDouglas Gregor } 125273441091SDouglas Gregor HadError = true; 125373441091SDouglas Gregor return; 125473441091SDouglas Gregor } 125573441091SDouglas Gregor 125673441091SDouglas Gregor // Note that we have an inferred submodule. 1257dd005f69SDouglas Gregor ActiveModule->InferSubmodules = true; 1258dd005f69SDouglas Gregor ActiveModule->InferredSubmoduleLoc = StarLoc; 1259dd005f69SDouglas Gregor ActiveModule->InferExplicitSubmodules = Explicit; 126073441091SDouglas Gregor 126173441091SDouglas Gregor // Parse the opening brace. 126273441091SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 126373441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard); 126473441091SDouglas Gregor HadError = true; 126573441091SDouglas Gregor return; 126673441091SDouglas Gregor } 126773441091SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 126873441091SDouglas Gregor 126973441091SDouglas Gregor // Parse the body of the inferred submodule. 127073441091SDouglas Gregor bool Done = false; 127173441091SDouglas Gregor do { 127273441091SDouglas Gregor switch (Tok.Kind) { 127373441091SDouglas Gregor case MMToken::EndOfFile: 127473441091SDouglas Gregor case MMToken::RBrace: 127573441091SDouglas Gregor Done = true; 127673441091SDouglas Gregor break; 127773441091SDouglas Gregor 127873441091SDouglas Gregor case MMToken::ExportKeyword: { 127973441091SDouglas Gregor consumeToken(); 128073441091SDouglas Gregor if (Tok.is(MMToken::Star)) 1281dd005f69SDouglas Gregor ActiveModule->InferExportWildcard = true; 128273441091SDouglas Gregor else 128373441091SDouglas Gregor Diags.Report(Tok.getLocation(), 128473441091SDouglas Gregor diag::err_mmap_expected_export_wildcard); 128573441091SDouglas Gregor consumeToken(); 128673441091SDouglas Gregor break; 128773441091SDouglas Gregor } 128873441091SDouglas Gregor 128973441091SDouglas Gregor case MMToken::ExplicitKeyword: 129073441091SDouglas Gregor case MMToken::ModuleKeyword: 129173441091SDouglas Gregor case MMToken::HeaderKeyword: 129273441091SDouglas Gregor case MMToken::UmbrellaKeyword: 129373441091SDouglas Gregor default: 129473441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_wildcard_member); 129573441091SDouglas Gregor consumeToken(); 129673441091SDouglas Gregor break; 129773441091SDouglas Gregor } 129873441091SDouglas Gregor } while (!Done); 129973441091SDouglas Gregor 130073441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 130173441091SDouglas Gregor consumeToken(); 130273441091SDouglas Gregor else { 130373441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 130473441091SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 130573441091SDouglas Gregor HadError = true; 130673441091SDouglas Gregor } 130773441091SDouglas Gregor } 130873441091SDouglas Gregor 13097033127bSDouglas Gregor /// \brief If there is a specific header search directory due the presence 13107033127bSDouglas Gregor /// of an umbrella directory, retrieve that directory. Otherwise, returns null. 13117033127bSDouglas Gregor const DirectoryEntry *ModuleMapParser::getOverriddenHeaderSearchDir() { 13127033127bSDouglas Gregor for (Module *Mod = ActiveModule; Mod; Mod = Mod->Parent) { 13137033127bSDouglas Gregor // If we have an umbrella directory, use that. 13147033127bSDouglas Gregor if (Mod->hasUmbrellaDir()) 13157033127bSDouglas Gregor return Mod->getUmbrellaDir(); 13167033127bSDouglas Gregor 13177033127bSDouglas Gregor // If we have a framework directory, stop looking. 13187033127bSDouglas Gregor if (Mod->IsFramework) 13197033127bSDouglas Gregor return 0; 13207033127bSDouglas Gregor } 13217033127bSDouglas Gregor 13227033127bSDouglas Gregor return 0; 13237033127bSDouglas Gregor } 13247033127bSDouglas Gregor 1325718292f2SDouglas Gregor /// \brief Parse a module map file. 1326718292f2SDouglas Gregor /// 1327718292f2SDouglas Gregor /// module-map-file: 1328718292f2SDouglas Gregor /// module-declaration* 1329718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 1330718292f2SDouglas Gregor do { 1331718292f2SDouglas Gregor switch (Tok.Kind) { 1332718292f2SDouglas Gregor case MMToken::EndOfFile: 1333718292f2SDouglas Gregor return HadError; 1334718292f2SDouglas Gregor 1335e7ab3669SDouglas Gregor case MMToken::ExplicitKeyword: 1336718292f2SDouglas Gregor case MMToken::ModuleKeyword: 1337755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 1338718292f2SDouglas Gregor parseModuleDecl(); 1339718292f2SDouglas Gregor break; 1340718292f2SDouglas Gregor 13411fb5c3a6SDouglas Gregor case MMToken::Comma: 13422b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 1343718292f2SDouglas Gregor case MMToken::HeaderKeyword: 1344718292f2SDouglas Gregor case MMToken::Identifier: 1345718292f2SDouglas Gregor case MMToken::LBrace: 1346*a686e1b0SDouglas Gregor case MMToken::LSquare: 13472b82c2a5SDouglas Gregor case MMToken::Period: 1348718292f2SDouglas Gregor case MMToken::RBrace: 1349*a686e1b0SDouglas Gregor case MMToken::RSquare: 13501fb5c3a6SDouglas Gregor case MMToken::RequiresKeyword: 13512b82c2a5SDouglas Gregor case MMToken::Star: 1352718292f2SDouglas Gregor case MMToken::StringLiteral: 1353718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 1354718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 1355718292f2SDouglas Gregor HadError = true; 1356718292f2SDouglas Gregor consumeToken(); 1357718292f2SDouglas Gregor break; 1358718292f2SDouglas Gregor } 1359718292f2SDouglas Gregor } while (true); 1360718292f2SDouglas Gregor } 1361718292f2SDouglas Gregor 1362718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) { 1363718292f2SDouglas Gregor FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User); 1364718292f2SDouglas Gregor const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID); 1365718292f2SDouglas Gregor if (!Buffer) 1366718292f2SDouglas Gregor return true; 1367718292f2SDouglas Gregor 1368718292f2SDouglas Gregor // Parse this module map file. 13691fb5c3a6SDouglas Gregor Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts); 13701fb5c3a6SDouglas Gregor Diags->getClient()->BeginSourceFile(MMapLangOpts); 13715257fc63SDouglas Gregor ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir()); 1372718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 1373718292f2SDouglas Gregor Diags->getClient()->EndSourceFile(); 1374718292f2SDouglas Gregor 1375718292f2SDouglas Gregor return Result; 1376718292f2SDouglas Gregor } 1377