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 72718292f2SDouglas Gregor ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) { 73718292f2SDouglas Gregor llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs); 74718292f2SDouglas Gregor Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>( 75718292f2SDouglas Gregor new DiagnosticsEngine(DiagIDs)); 76718292f2SDouglas Gregor Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true); 77718292f2SDouglas Gregor SourceMgr = new SourceManager(*Diags, FileMgr); 78718292f2SDouglas Gregor } 79718292f2SDouglas Gregor 80718292f2SDouglas Gregor ModuleMap::~ModuleMap() { 815acdf59eSDouglas Gregor for (llvm::StringMap<Module *>::iterator I = Modules.begin(), 825acdf59eSDouglas Gregor IEnd = Modules.end(); 835acdf59eSDouglas Gregor I != IEnd; ++I) { 845acdf59eSDouglas Gregor delete I->getValue(); 855acdf59eSDouglas Gregor } 865acdf59eSDouglas Gregor 87718292f2SDouglas Gregor delete SourceMgr; 88718292f2SDouglas Gregor } 89718292f2SDouglas Gregor 90de3ef502SDouglas Gregor Module *ModuleMap::findModuleForHeader(const FileEntry *File) { 91ab0c8a84SDouglas Gregor llvm::DenseMap<const FileEntry *, Module *>::iterator Known 92ab0c8a84SDouglas Gregor = Headers.find(File); 93ab0c8a84SDouglas Gregor if (Known != Headers.end()) 94ab0c8a84SDouglas Gregor return Known->second; 95ab0c8a84SDouglas Gregor 96b65dbfffSDouglas Gregor const DirectoryEntry *Dir = File->getDir(); 97b65dbfffSDouglas Gregor llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs; 98b65dbfffSDouglas Gregor StringRef DirName = Dir->getName(); 99a89c5ac4SDouglas Gregor 100a89c5ac4SDouglas Gregor // Keep walking up the directory hierarchy, looking for a directory with 101a89c5ac4SDouglas Gregor // an umbrella header. 102b65dbfffSDouglas Gregor do { 103a89c5ac4SDouglas Gregor llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir 104a89c5ac4SDouglas Gregor = UmbrellaDirs.find(Dir); 105a89c5ac4SDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 106a89c5ac4SDouglas Gregor Module *Result = KnownDir->second; 107930a85ccSDouglas Gregor 108930a85ccSDouglas Gregor // Search up the module stack until we find a module with an umbrella 109930a85ccSDouglas Gregor // header. 110930a85ccSDouglas Gregor Module *UmbrellaModule = Result; 111930a85ccSDouglas Gregor while (!UmbrellaModule->UmbrellaHeader && UmbrellaModule->Parent) 112930a85ccSDouglas Gregor UmbrellaModule = UmbrellaModule->Parent; 113930a85ccSDouglas Gregor 114930a85ccSDouglas Gregor if (UmbrellaModule->InferSubmodules) { 115a89c5ac4SDouglas Gregor // Infer submodules for each of the directories we found between 116a89c5ac4SDouglas Gregor // the directory of the umbrella header and the directory where 117a89c5ac4SDouglas Gregor // the actual header is located. 118a89c5ac4SDouglas Gregor 119a89c5ac4SDouglas Gregor // For a framework module, the umbrella directory is the framework 120a89c5ac4SDouglas Gregor // directory, so strip off the "Headers" or "PrivateHeaders". 121*9458f82dSDouglas Gregor bool Explicit = UmbrellaModule->InferExplicitSubmodules; 122a89c5ac4SDouglas Gregor unsigned LastSkippedDir = SkippedDirs.size(); 123*9458f82dSDouglas Gregor if (LastSkippedDir && UmbrellaModule->IsFramework) { 124*9458f82dSDouglas Gregor if (llvm::sys::path::filename(SkippedDirs.back()->getName()) 125*9458f82dSDouglas Gregor == "PrivateHeaders") { 126*9458f82dSDouglas Gregor // For private headers, add an explicit "Private" module. 127*9458f82dSDouglas Gregor // FIXME: This feels somewhat hackish. Do we want to introduce 128*9458f82dSDouglas Gregor // some kind of "umbrella directory" here? 129*9458f82dSDouglas Gregor Result = findOrCreateModule("Private", Result, 130*9458f82dSDouglas Gregor /*IsFramework=*/false, 131*9458f82dSDouglas Gregor /*IsExplicit=*/true).first; 132*9458f82dSDouglas Gregor Explicit = true; 133*9458f82dSDouglas Gregor } 134*9458f82dSDouglas Gregor 135a89c5ac4SDouglas Gregor --LastSkippedDir; 136*9458f82dSDouglas Gregor } 137a89c5ac4SDouglas Gregor 138a89c5ac4SDouglas Gregor for (unsigned I = LastSkippedDir; I != 0; --I) { 139a89c5ac4SDouglas Gregor // Find or create the module that corresponds to this directory name. 140a89c5ac4SDouglas Gregor StringRef Name = llvm::sys::path::stem(SkippedDirs[I-1]->getName()); 141a89c5ac4SDouglas Gregor Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 142*9458f82dSDouglas Gregor Explicit).first; 143a89c5ac4SDouglas Gregor 144a89c5ac4SDouglas Gregor // Associate the module and the directory. 145a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I-1]] = Result; 146a89c5ac4SDouglas Gregor 147a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 148a89c5ac4SDouglas Gregor // wildcard to the set of exports. 149930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 150a89c5ac4SDouglas Gregor Result->Exports.push_back(Module::ExportDecl(0, true)); 151a89c5ac4SDouglas Gregor } 152a89c5ac4SDouglas Gregor 153a89c5ac4SDouglas Gregor // Infer a submodule with the same name as this header file. 154a89c5ac4SDouglas Gregor StringRef Name = llvm::sys::path::stem(File->getName()); 155a89c5ac4SDouglas Gregor Result = findOrCreateModule(Name, Result, /*IsFramework=*/false, 156*9458f82dSDouglas Gregor Explicit).first; 157a89c5ac4SDouglas Gregor 158a89c5ac4SDouglas Gregor // If inferred submodules export everything they import, add a 159a89c5ac4SDouglas Gregor // wildcard to the set of exports. 160930a85ccSDouglas Gregor if (UmbrellaModule->InferExportWildcard && Result->Exports.empty()) 161a89c5ac4SDouglas Gregor Result->Exports.push_back(Module::ExportDecl(0, true)); 162a89c5ac4SDouglas Gregor } else { 163a89c5ac4SDouglas Gregor // Record each of the directories we stepped through as being part of 164a89c5ac4SDouglas Gregor // the module we found, since the umbrella header covers them all. 165a89c5ac4SDouglas Gregor for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I) 166a89c5ac4SDouglas Gregor UmbrellaDirs[SkippedDirs[I]] = Result; 167a89c5ac4SDouglas Gregor } 168a89c5ac4SDouglas Gregor 169a89c5ac4SDouglas Gregor Headers[File] = Result; 170a89c5ac4SDouglas Gregor return Result; 171a89c5ac4SDouglas Gregor } 172a89c5ac4SDouglas Gregor 173a89c5ac4SDouglas Gregor SkippedDirs.push_back(Dir); 174a89c5ac4SDouglas Gregor 175b65dbfffSDouglas Gregor // Retrieve our parent path. 176b65dbfffSDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 177b65dbfffSDouglas Gregor if (DirName.empty()) 178b65dbfffSDouglas Gregor break; 179b65dbfffSDouglas Gregor 180b65dbfffSDouglas Gregor // Resolve the parent path to a directory entry. 181b65dbfffSDouglas Gregor Dir = SourceMgr->getFileManager().getDirectory(DirName); 182a89c5ac4SDouglas Gregor } while (Dir); 183b65dbfffSDouglas Gregor 184ab0c8a84SDouglas Gregor return 0; 185ab0c8a84SDouglas Gregor } 186ab0c8a84SDouglas Gregor 187de3ef502SDouglas Gregor Module *ModuleMap::findModule(StringRef Name) { 18888bdfb0eSDouglas Gregor llvm::StringMap<Module *>::iterator Known = Modules.find(Name); 18988bdfb0eSDouglas Gregor if (Known != Modules.end()) 19088bdfb0eSDouglas Gregor return Known->getValue(); 19188bdfb0eSDouglas Gregor 19288bdfb0eSDouglas Gregor return 0; 19388bdfb0eSDouglas Gregor } 19488bdfb0eSDouglas Gregor 1952b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) { 1962b82c2a5SDouglas Gregor for(; Context; Context = Context->Parent) { 1972b82c2a5SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Context)) 1982b82c2a5SDouglas Gregor return Sub; 1992b82c2a5SDouglas Gregor } 2002b82c2a5SDouglas Gregor 2012b82c2a5SDouglas Gregor return findModule(Name); 2022b82c2a5SDouglas Gregor } 2032b82c2a5SDouglas Gregor 2042b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) { 2052b82c2a5SDouglas Gregor if (!Context) 2062b82c2a5SDouglas Gregor return findModule(Name); 2072b82c2a5SDouglas Gregor 2082b82c2a5SDouglas Gregor llvm::StringMap<Module *>::iterator Sub = Context->SubModules.find(Name); 2092b82c2a5SDouglas Gregor if (Sub != Context->SubModules.end()) 2102b82c2a5SDouglas Gregor return Sub->getValue(); 2112b82c2a5SDouglas Gregor 2122b82c2a5SDouglas Gregor return 0; 2132b82c2a5SDouglas Gregor } 2142b82c2a5SDouglas Gregor 215de3ef502SDouglas Gregor std::pair<Module *, bool> 21669021974SDouglas Gregor ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework, 21769021974SDouglas Gregor bool IsExplicit) { 21869021974SDouglas Gregor // Try to find an existing module with this name. 21969021974SDouglas Gregor if (Module *Found = Parent? Parent->SubModules[Name] : Modules[Name]) 22069021974SDouglas Gregor return std::make_pair(Found, false); 22169021974SDouglas Gregor 22269021974SDouglas Gregor // Create a new module with this name. 22369021974SDouglas Gregor Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, 22469021974SDouglas Gregor IsExplicit); 22569021974SDouglas Gregor if (Parent) 22669021974SDouglas Gregor Parent->SubModules[Name] = Result; 22769021974SDouglas Gregor else 22869021974SDouglas Gregor Modules[Name] = Result; 22969021974SDouglas Gregor return std::make_pair(Result, true); 23069021974SDouglas Gregor } 23169021974SDouglas Gregor 232de3ef502SDouglas Gregor Module * 23356c64013SDouglas Gregor ModuleMap::inferFrameworkModule(StringRef ModuleName, 234e89dbc1dSDouglas Gregor const DirectoryEntry *FrameworkDir, 235e89dbc1dSDouglas Gregor Module *Parent) { 23656c64013SDouglas Gregor // Check whether we've already found this module. 237e89dbc1dSDouglas Gregor if (Module *Mod = lookupModuleQualified(ModuleName, Parent)) 238e89dbc1dSDouglas Gregor return Mod; 239e89dbc1dSDouglas Gregor 240e89dbc1dSDouglas Gregor FileManager &FileMgr = SourceMgr->getFileManager(); 24156c64013SDouglas Gregor 24256c64013SDouglas Gregor // Look for an umbrella header. 24356c64013SDouglas Gregor llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 24456c64013SDouglas Gregor llvm::sys::path::append(UmbrellaName, "Headers"); 24556c64013SDouglas Gregor llvm::sys::path::append(UmbrellaName, ModuleName + ".h"); 246e89dbc1dSDouglas Gregor const FileEntry *UmbrellaHeader = FileMgr.getFile(UmbrellaName); 24756c64013SDouglas Gregor 24856c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the 24956c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good 25056c64013SDouglas Gregor // idea. 25156c64013SDouglas Gregor if (!UmbrellaHeader) 25256c64013SDouglas Gregor return 0; 25356c64013SDouglas Gregor 254e89dbc1dSDouglas Gregor Module *Result = new Module(ModuleName, SourceLocation(), Parent, 255e89dbc1dSDouglas Gregor /*IsFramework=*/true, /*IsExplicit=*/false); 256e89dbc1dSDouglas Gregor 257e89dbc1dSDouglas Gregor if (Parent) 258e89dbc1dSDouglas Gregor Parent->SubModules[ModuleName] = Result; 259e89dbc1dSDouglas Gregor else 260e89dbc1dSDouglas Gregor Modules[ModuleName] = Result; 261e89dbc1dSDouglas Gregor 262d8bd7537SDouglas Gregor // umbrella "umbrella-header-name" 26356c64013SDouglas Gregor Result->UmbrellaHeader = UmbrellaHeader; 26456c64013SDouglas Gregor Headers[UmbrellaHeader] = Result; 26556c64013SDouglas Gregor UmbrellaDirs[FrameworkDir] = Result; 266d8bd7537SDouglas Gregor 267d8bd7537SDouglas Gregor // export * 268d8bd7537SDouglas Gregor Result->Exports.push_back(Module::ExportDecl(0, true)); 269d8bd7537SDouglas Gregor 270a89c5ac4SDouglas Gregor // module * { export * } 271a89c5ac4SDouglas Gregor Result->InferSubmodules = true; 272a89c5ac4SDouglas Gregor Result->InferExportWildcard = true; 273a89c5ac4SDouglas Gregor 274e89dbc1dSDouglas Gregor // Look for subframeworks. 275e89dbc1dSDouglas Gregor llvm::error_code EC; 276e89dbc1dSDouglas Gregor llvm::SmallString<128> SubframeworksDirName = StringRef(FrameworkDir->getName()); 277e89dbc1dSDouglas Gregor llvm::sys::path::append(SubframeworksDirName, "Frameworks"); 278e89dbc1dSDouglas Gregor for (llvm::sys::fs::directory_iterator Dir(SubframeworksDirName.str(), EC), 279e89dbc1dSDouglas Gregor DirEnd; 280e89dbc1dSDouglas Gregor Dir != DirEnd && !EC; Dir.increment(EC)) { 281e89dbc1dSDouglas Gregor if (!StringRef(Dir->path()).endswith(".framework")) 282e89dbc1dSDouglas Gregor continue; 283f2161a70SDouglas Gregor 284e89dbc1dSDouglas Gregor if (const DirectoryEntry *SubframeworkDir 285e89dbc1dSDouglas Gregor = FileMgr.getDirectory(Dir->path())) { 286e89dbc1dSDouglas Gregor // FIXME: Do we want to warn about subframeworks without umbrella headers? 287e89dbc1dSDouglas Gregor inferFrameworkModule(llvm::sys::path::stem(Dir->path()), SubframeworkDir, 288e89dbc1dSDouglas Gregor Result); 289e89dbc1dSDouglas Gregor } 290e89dbc1dSDouglas Gregor } 291e89dbc1dSDouglas Gregor 292*9458f82dSDouglas Gregor // Look for private headers. 293*9458f82dSDouglas Gregor Module *ModulePrivate = 0; 294*9458f82dSDouglas Gregor llvm::SmallString<128> PrivateHeadersDirName(FrameworkDir->getName()); 295*9458f82dSDouglas Gregor llvm::sys::path::append(PrivateHeadersDirName, "PrivateHeaders"); 296*9458f82dSDouglas Gregor for (llvm::sys::fs::directory_iterator Dir(PrivateHeadersDirName.str(), EC), 297*9458f82dSDouglas Gregor DirEnd; 298*9458f82dSDouglas Gregor Dir != DirEnd && !EC; Dir.increment(EC)) { 299*9458f82dSDouglas Gregor // Check whether this entry has an extension typically associated with 300*9458f82dSDouglas Gregor // headers. 301*9458f82dSDouglas Gregor if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->path())) 302*9458f82dSDouglas Gregor .Cases(".h", ".H", ".hh", ".hpp", true) 303*9458f82dSDouglas Gregor .Default(false)) 304*9458f82dSDouglas Gregor continue; 305*9458f82dSDouglas Gregor 306*9458f82dSDouglas Gregor if (const FileEntry *PrivateHeader = FileMgr.getFile(Dir->path())) { 307*9458f82dSDouglas Gregor // Create the "private" submodule, if we haven't done so already. 308*9458f82dSDouglas Gregor if (!ModulePrivate) { 309*9458f82dSDouglas Gregor ModulePrivate = findOrCreateModule("Private", Result, 310*9458f82dSDouglas Gregor /*IsFramework=*/false, 311*9458f82dSDouglas Gregor /*IsExplicit=*/true).first; 312*9458f82dSDouglas Gregor } 313*9458f82dSDouglas Gregor 314*9458f82dSDouglas Gregor Module *Sub = findOrCreateModule(llvm::sys::path::stem(Dir->path()), 315*9458f82dSDouglas Gregor ModulePrivate, /*IsFramework=*/false, 316*9458f82dSDouglas Gregor /*IsExplicit=*/true).first; 317*9458f82dSDouglas Gregor // header "the private header" 318*9458f82dSDouglas Gregor Sub->Headers.push_back(PrivateHeader); 319*9458f82dSDouglas Gregor 320*9458f82dSDouglas Gregor // export * 321*9458f82dSDouglas Gregor Sub->Exports.push_back(Module::ExportDecl(0, true)); 322*9458f82dSDouglas Gregor 323*9458f82dSDouglas Gregor Headers[PrivateHeader] = Sub; 324*9458f82dSDouglas Gregor } 325*9458f82dSDouglas Gregor } 326*9458f82dSDouglas Gregor 32756c64013SDouglas Gregor return Result; 32856c64013SDouglas Gregor } 32956c64013SDouglas Gregor 330a89c5ac4SDouglas Gregor void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){ 331a89c5ac4SDouglas Gregor Headers[UmbrellaHeader] = Mod; 332a89c5ac4SDouglas Gregor Mod->UmbrellaHeader = UmbrellaHeader; 333a89c5ac4SDouglas Gregor 334a89c5ac4SDouglas Gregor const DirectoryEntry *UmbrellaDir = UmbrellaHeader->getDir(); 335a89c5ac4SDouglas Gregor if (Mod->IsFramework) 336a89c5ac4SDouglas Gregor UmbrellaDir = SourceMgr->getFileManager().getDirectory( 337a89c5ac4SDouglas Gregor llvm::sys::path::parent_path(UmbrellaDir->getName())); 338a89c5ac4SDouglas Gregor 339a89c5ac4SDouglas Gregor UmbrellaDirs[UmbrellaDir] = Mod; 340a89c5ac4SDouglas Gregor } 341a89c5ac4SDouglas Gregor 342a89c5ac4SDouglas Gregor void ModuleMap::addHeader(Module *Mod, const FileEntry *Header) { 343a89c5ac4SDouglas Gregor Mod->Headers.push_back(Header); 344a89c5ac4SDouglas Gregor Headers[Header] = Mod; 345a89c5ac4SDouglas Gregor } 346a89c5ac4SDouglas Gregor 347514b636aSDouglas Gregor const FileEntry * 348de3ef502SDouglas Gregor ModuleMap::getContainingModuleMapFile(Module *Module) { 349514b636aSDouglas Gregor if (Module->DefinitionLoc.isInvalid() || !SourceMgr) 350514b636aSDouglas Gregor return 0; 351514b636aSDouglas Gregor 352514b636aSDouglas Gregor return SourceMgr->getFileEntryForID( 353514b636aSDouglas Gregor SourceMgr->getFileID(Module->DefinitionLoc)); 354514b636aSDouglas Gregor } 355514b636aSDouglas Gregor 356718292f2SDouglas Gregor void ModuleMap::dump() { 357718292f2SDouglas Gregor llvm::errs() << "Modules:"; 358718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 359718292f2SDouglas Gregor MEnd = Modules.end(); 360718292f2SDouglas Gregor M != MEnd; ++M) 361d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 362718292f2SDouglas Gregor 363718292f2SDouglas Gregor llvm::errs() << "Headers:"; 364718292f2SDouglas Gregor for (llvm::DenseMap<const FileEntry *, Module *>::iterator 365718292f2SDouglas Gregor H = Headers.begin(), 366718292f2SDouglas Gregor HEnd = Headers.end(); 367718292f2SDouglas Gregor H != HEnd; ++H) { 368718292f2SDouglas Gregor llvm::errs() << " \"" << H->first->getName() << "\" -> " 369718292f2SDouglas Gregor << H->second->getFullModuleName() << "\n"; 370718292f2SDouglas Gregor } 371718292f2SDouglas Gregor } 372718292f2SDouglas Gregor 3732b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) { 3742b82c2a5SDouglas Gregor bool HadError = false; 3752b82c2a5SDouglas Gregor for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) { 3762b82c2a5SDouglas Gregor Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I], 3772b82c2a5SDouglas Gregor Complain); 378f5eedd05SDouglas Gregor if (Export.getPointer() || Export.getInt()) 3792b82c2a5SDouglas Gregor Mod->Exports.push_back(Export); 3802b82c2a5SDouglas Gregor else 3812b82c2a5SDouglas Gregor HadError = true; 3822b82c2a5SDouglas Gregor } 3832b82c2a5SDouglas Gregor Mod->UnresolvedExports.clear(); 3842b82c2a5SDouglas Gregor return HadError; 3852b82c2a5SDouglas Gregor } 3862b82c2a5SDouglas Gregor 3870093b3c7SDouglas Gregor Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) { 3880093b3c7SDouglas Gregor if (Loc.isInvalid()) 3890093b3c7SDouglas Gregor return 0; 3900093b3c7SDouglas Gregor 3910093b3c7SDouglas Gregor // Use the expansion location to determine which module we're in. 3920093b3c7SDouglas Gregor FullSourceLoc ExpansionLoc = Loc.getExpansionLoc(); 3930093b3c7SDouglas Gregor if (!ExpansionLoc.isFileID()) 3940093b3c7SDouglas Gregor return 0; 3950093b3c7SDouglas Gregor 3960093b3c7SDouglas Gregor 3970093b3c7SDouglas Gregor const SourceManager &SrcMgr = Loc.getManager(); 3980093b3c7SDouglas Gregor FileID ExpansionFileID = ExpansionLoc.getFileID(); 3990093b3c7SDouglas Gregor const FileEntry *ExpansionFile = SrcMgr.getFileEntryForID(ExpansionFileID); 4000093b3c7SDouglas Gregor if (!ExpansionFile) 4010093b3c7SDouglas Gregor return 0; 4020093b3c7SDouglas Gregor 4030093b3c7SDouglas Gregor // Find the module that owns this header. 4040093b3c7SDouglas Gregor return findModuleForHeader(ExpansionFile); 4050093b3c7SDouglas Gregor } 4060093b3c7SDouglas Gregor 407718292f2SDouglas Gregor //----------------------------------------------------------------------------// 408718292f2SDouglas Gregor // Module map file parser 409718292f2SDouglas Gregor //----------------------------------------------------------------------------// 410718292f2SDouglas Gregor 411718292f2SDouglas Gregor namespace clang { 412718292f2SDouglas Gregor /// \brief A token in a module map file. 413718292f2SDouglas Gregor struct MMToken { 414718292f2SDouglas Gregor enum TokenKind { 415718292f2SDouglas Gregor EndOfFile, 416718292f2SDouglas Gregor HeaderKeyword, 417718292f2SDouglas Gregor Identifier, 418718292f2SDouglas Gregor ExplicitKeyword, 4192b82c2a5SDouglas Gregor ExportKeyword, 420755b2055SDouglas Gregor FrameworkKeyword, 421718292f2SDouglas Gregor ModuleKeyword, 4222b82c2a5SDouglas Gregor Period, 423718292f2SDouglas Gregor UmbrellaKeyword, 4242b82c2a5SDouglas Gregor Star, 425718292f2SDouglas Gregor StringLiteral, 426718292f2SDouglas Gregor LBrace, 427718292f2SDouglas Gregor RBrace 428718292f2SDouglas Gregor } Kind; 429718292f2SDouglas Gregor 430718292f2SDouglas Gregor unsigned Location; 431718292f2SDouglas Gregor unsigned StringLength; 432718292f2SDouglas Gregor const char *StringData; 433718292f2SDouglas Gregor 434718292f2SDouglas Gregor void clear() { 435718292f2SDouglas Gregor Kind = EndOfFile; 436718292f2SDouglas Gregor Location = 0; 437718292f2SDouglas Gregor StringLength = 0; 438718292f2SDouglas Gregor StringData = 0; 439718292f2SDouglas Gregor } 440718292f2SDouglas Gregor 441718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 442718292f2SDouglas Gregor 443718292f2SDouglas Gregor SourceLocation getLocation() const { 444718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 445718292f2SDouglas Gregor } 446718292f2SDouglas Gregor 447718292f2SDouglas Gregor StringRef getString() const { 448718292f2SDouglas Gregor return StringRef(StringData, StringLength); 449718292f2SDouglas Gregor } 450718292f2SDouglas Gregor }; 451718292f2SDouglas Gregor 452718292f2SDouglas Gregor class ModuleMapParser { 453718292f2SDouglas Gregor Lexer &L; 454718292f2SDouglas Gregor SourceManager &SourceMgr; 455718292f2SDouglas Gregor DiagnosticsEngine &Diags; 456718292f2SDouglas Gregor ModuleMap ⤅ 457718292f2SDouglas Gregor 4585257fc63SDouglas Gregor /// \brief The directory that this module map resides in. 4595257fc63SDouglas Gregor const DirectoryEntry *Directory; 4605257fc63SDouglas Gregor 461718292f2SDouglas Gregor /// \brief Whether an error occurred. 462718292f2SDouglas Gregor bool HadError; 463718292f2SDouglas Gregor 464718292f2SDouglas Gregor /// \brief Default target information, used only for string literal 465718292f2SDouglas Gregor /// parsing. 466718292f2SDouglas Gregor TargetInfo *Target; 467718292f2SDouglas Gregor 468718292f2SDouglas Gregor /// \brief Stores string data for the various string literals referenced 469718292f2SDouglas Gregor /// during parsing. 470718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 471718292f2SDouglas Gregor 472718292f2SDouglas Gregor /// \brief The current token. 473718292f2SDouglas Gregor MMToken Tok; 474718292f2SDouglas Gregor 475718292f2SDouglas Gregor /// \brief The active module. 476de3ef502SDouglas Gregor Module *ActiveModule; 477718292f2SDouglas Gregor 478718292f2SDouglas Gregor /// \brief Consume the current token and return its location. 479718292f2SDouglas Gregor SourceLocation consumeToken(); 480718292f2SDouglas Gregor 481718292f2SDouglas Gregor /// \brief Skip tokens until we reach the a token with the given kind 482718292f2SDouglas Gregor /// (or the end of the file). 483718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 484718292f2SDouglas Gregor 485e7ab3669SDouglas Gregor typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2> 486e7ab3669SDouglas Gregor ModuleId; 487e7ab3669SDouglas Gregor bool parseModuleId(ModuleId &Id); 488718292f2SDouglas Gregor void parseModuleDecl(); 489718292f2SDouglas Gregor void parseUmbrellaDecl(); 490718292f2SDouglas Gregor void parseHeaderDecl(); 4912b82c2a5SDouglas Gregor void parseExportDecl(); 49273441091SDouglas Gregor void parseInferredSubmoduleDecl(bool Explicit); 493718292f2SDouglas Gregor 494718292f2SDouglas Gregor public: 495718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 496718292f2SDouglas Gregor DiagnosticsEngine &Diags, 4975257fc63SDouglas Gregor ModuleMap &Map, 4985257fc63SDouglas Gregor const DirectoryEntry *Directory) 4995257fc63SDouglas Gregor : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map), 5005257fc63SDouglas Gregor Directory(Directory), HadError(false), ActiveModule(0) 501718292f2SDouglas Gregor { 502718292f2SDouglas Gregor TargetOptions TargetOpts; 503718292f2SDouglas Gregor TargetOpts.Triple = llvm::sys::getDefaultTargetTriple(); 504718292f2SDouglas Gregor Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); 505718292f2SDouglas Gregor 506718292f2SDouglas Gregor Tok.clear(); 507718292f2SDouglas Gregor consumeToken(); 508718292f2SDouglas Gregor } 509718292f2SDouglas Gregor 510718292f2SDouglas Gregor bool parseModuleMapFile(); 511718292f2SDouglas Gregor }; 512718292f2SDouglas Gregor } 513718292f2SDouglas Gregor 514718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 515718292f2SDouglas Gregor retry: 516718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 517718292f2SDouglas Gregor Tok.clear(); 518718292f2SDouglas Gregor 519718292f2SDouglas Gregor Token LToken; 520718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 521718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 522718292f2SDouglas Gregor switch (LToken.getKind()) { 523718292f2SDouglas Gregor case tok::raw_identifier: 524718292f2SDouglas Gregor Tok.StringData = LToken.getRawIdentifierData(); 525718292f2SDouglas Gregor Tok.StringLength = LToken.getLength(); 526718292f2SDouglas Gregor Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString()) 527718292f2SDouglas Gregor .Case("header", MMToken::HeaderKeyword) 528718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 5292b82c2a5SDouglas Gregor .Case("export", MMToken::ExportKeyword) 530755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 531718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 532718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 533718292f2SDouglas Gregor .Default(MMToken::Identifier); 534718292f2SDouglas Gregor break; 535718292f2SDouglas Gregor 536718292f2SDouglas Gregor case tok::eof: 537718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 538718292f2SDouglas Gregor break; 539718292f2SDouglas Gregor 540718292f2SDouglas Gregor case tok::l_brace: 541718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 542718292f2SDouglas Gregor break; 543718292f2SDouglas Gregor 5442b82c2a5SDouglas Gregor case tok::period: 5452b82c2a5SDouglas Gregor Tok.Kind = MMToken::Period; 5462b82c2a5SDouglas Gregor break; 5472b82c2a5SDouglas Gregor 548718292f2SDouglas Gregor case tok::r_brace: 549718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 550718292f2SDouglas Gregor break; 551718292f2SDouglas Gregor 5522b82c2a5SDouglas Gregor case tok::star: 5532b82c2a5SDouglas Gregor Tok.Kind = MMToken::Star; 5542b82c2a5SDouglas Gregor break; 5552b82c2a5SDouglas Gregor 556718292f2SDouglas Gregor case tok::string_literal: { 557718292f2SDouglas Gregor // Parse the string literal. 558718292f2SDouglas Gregor LangOptions LangOpts; 559718292f2SDouglas Gregor StringLiteralParser StringLiteral(<oken, 1, SourceMgr, LangOpts, *Target); 560718292f2SDouglas Gregor if (StringLiteral.hadError) 561718292f2SDouglas Gregor goto retry; 562718292f2SDouglas Gregor 563718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 564718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 565718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 566718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 567718292f2SDouglas Gregor Saved[Length] = 0; 568718292f2SDouglas Gregor 569718292f2SDouglas Gregor // Form the token. 570718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 571718292f2SDouglas Gregor Tok.StringData = Saved; 572718292f2SDouglas Gregor Tok.StringLength = Length; 573718292f2SDouglas Gregor break; 574718292f2SDouglas Gregor } 575718292f2SDouglas Gregor 576718292f2SDouglas Gregor case tok::comment: 577718292f2SDouglas Gregor goto retry; 578718292f2SDouglas Gregor 579718292f2SDouglas Gregor default: 580718292f2SDouglas Gregor Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token); 581718292f2SDouglas Gregor HadError = true; 582718292f2SDouglas Gregor goto retry; 583718292f2SDouglas Gregor } 584718292f2SDouglas Gregor 585718292f2SDouglas Gregor return Result; 586718292f2SDouglas Gregor } 587718292f2SDouglas Gregor 588718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 589718292f2SDouglas Gregor unsigned braceDepth = 0; 590718292f2SDouglas Gregor do { 591718292f2SDouglas Gregor switch (Tok.Kind) { 592718292f2SDouglas Gregor case MMToken::EndOfFile: 593718292f2SDouglas Gregor return; 594718292f2SDouglas Gregor 595718292f2SDouglas Gregor case MMToken::LBrace: 596718292f2SDouglas Gregor if (Tok.is(K) && braceDepth == 0) 597718292f2SDouglas Gregor return; 598718292f2SDouglas Gregor 599718292f2SDouglas Gregor ++braceDepth; 600718292f2SDouglas Gregor break; 601718292f2SDouglas Gregor 602718292f2SDouglas Gregor case MMToken::RBrace: 603718292f2SDouglas Gregor if (braceDepth > 0) 604718292f2SDouglas Gregor --braceDepth; 605718292f2SDouglas Gregor else if (Tok.is(K)) 606718292f2SDouglas Gregor return; 607718292f2SDouglas Gregor break; 608718292f2SDouglas Gregor 609718292f2SDouglas Gregor default: 610718292f2SDouglas Gregor if (braceDepth == 0 && Tok.is(K)) 611718292f2SDouglas Gregor return; 612718292f2SDouglas Gregor break; 613718292f2SDouglas Gregor } 614718292f2SDouglas Gregor 615718292f2SDouglas Gregor consumeToken(); 616718292f2SDouglas Gregor } while (true); 617718292f2SDouglas Gregor } 618718292f2SDouglas Gregor 619e7ab3669SDouglas Gregor /// \brief Parse a module-id. 620e7ab3669SDouglas Gregor /// 621e7ab3669SDouglas Gregor /// module-id: 622e7ab3669SDouglas Gregor /// identifier 623e7ab3669SDouglas Gregor /// identifier '.' module-id 624e7ab3669SDouglas Gregor /// 625e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise. 626e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) { 627e7ab3669SDouglas Gregor Id.clear(); 628e7ab3669SDouglas Gregor do { 629e7ab3669SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 630e7ab3669SDouglas Gregor Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation())); 631e7ab3669SDouglas Gregor consumeToken(); 632e7ab3669SDouglas Gregor } else { 633e7ab3669SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 634e7ab3669SDouglas Gregor return true; 635e7ab3669SDouglas Gregor } 636e7ab3669SDouglas Gregor 637e7ab3669SDouglas Gregor if (!Tok.is(MMToken::Period)) 638e7ab3669SDouglas Gregor break; 639e7ab3669SDouglas Gregor 640e7ab3669SDouglas Gregor consumeToken(); 641e7ab3669SDouglas Gregor } while (true); 642e7ab3669SDouglas Gregor 643e7ab3669SDouglas Gregor return false; 644e7ab3669SDouglas Gregor } 645e7ab3669SDouglas Gregor 646718292f2SDouglas Gregor /// \brief Parse a module declaration. 647718292f2SDouglas Gregor /// 648718292f2SDouglas Gregor /// module-declaration: 649e7ab3669SDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' module-id { module-member* } 650718292f2SDouglas Gregor /// 651718292f2SDouglas Gregor /// module-member: 652718292f2SDouglas Gregor /// umbrella-declaration 653718292f2SDouglas Gregor /// header-declaration 654e7ab3669SDouglas Gregor /// submodule-declaration 6552b82c2a5SDouglas Gregor /// export-declaration 65673441091SDouglas Gregor /// 65773441091SDouglas Gregor /// submodule-declaration: 65873441091SDouglas Gregor /// module-declaration 65973441091SDouglas Gregor /// inferred-submodule-declaration 660718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 661755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 662755b2055SDouglas Gregor Tok.is(MMToken::FrameworkKeyword)); 663f2161a70SDouglas Gregor // Parse 'explicit' or 'framework' keyword, if present. 664e7ab3669SDouglas Gregor SourceLocation ExplicitLoc; 665718292f2SDouglas Gregor bool Explicit = false; 666f2161a70SDouglas Gregor bool Framework = false; 667755b2055SDouglas Gregor 668f2161a70SDouglas Gregor // Parse 'explicit' keyword, if present. 669f2161a70SDouglas Gregor if (Tok.is(MMToken::ExplicitKeyword)) { 670e7ab3669SDouglas Gregor ExplicitLoc = consumeToken(); 671f2161a70SDouglas Gregor Explicit = true; 672f2161a70SDouglas Gregor } 673f2161a70SDouglas Gregor 674f2161a70SDouglas Gregor // Parse 'framework' keyword, if present. 675755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 676755b2055SDouglas Gregor consumeToken(); 677755b2055SDouglas Gregor Framework = true; 678755b2055SDouglas Gregor } 679718292f2SDouglas Gregor 680718292f2SDouglas Gregor // Parse 'module' keyword. 681718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 682d6343c99SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 683718292f2SDouglas Gregor consumeToken(); 684718292f2SDouglas Gregor HadError = true; 685718292f2SDouglas Gregor return; 686718292f2SDouglas Gregor } 687718292f2SDouglas Gregor consumeToken(); // 'module' keyword 688718292f2SDouglas Gregor 68973441091SDouglas Gregor // If we have a wildcard for the module name, this is an inferred submodule. 69073441091SDouglas Gregor // Parse it. 69173441091SDouglas Gregor if (Tok.is(MMToken::Star)) 69273441091SDouglas Gregor return parseInferredSubmoduleDecl(Explicit); 69373441091SDouglas Gregor 694718292f2SDouglas Gregor // Parse the module name. 695e7ab3669SDouglas Gregor ModuleId Id; 696e7ab3669SDouglas Gregor if (parseModuleId(Id)) { 697718292f2SDouglas Gregor HadError = true; 698718292f2SDouglas Gregor return; 699718292f2SDouglas Gregor } 700e7ab3669SDouglas Gregor 701e7ab3669SDouglas Gregor if (ActiveModule) { 702e7ab3669SDouglas Gregor if (Id.size() > 1) { 703e7ab3669SDouglas Gregor Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id) 704e7ab3669SDouglas Gregor << SourceRange(Id.front().second, Id.back().second); 705e7ab3669SDouglas Gregor 706e7ab3669SDouglas Gregor HadError = true; 707e7ab3669SDouglas Gregor return; 708e7ab3669SDouglas Gregor } 709e7ab3669SDouglas Gregor } else if (Id.size() == 1 && Explicit) { 710e7ab3669SDouglas Gregor // Top-level modules can't be explicit. 711e7ab3669SDouglas Gregor Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level); 712e7ab3669SDouglas Gregor Explicit = false; 713e7ab3669SDouglas Gregor ExplicitLoc = SourceLocation(); 714e7ab3669SDouglas Gregor HadError = true; 715e7ab3669SDouglas Gregor } 716e7ab3669SDouglas Gregor 717e7ab3669SDouglas Gregor Module *PreviousActiveModule = ActiveModule; 718e7ab3669SDouglas Gregor if (Id.size() > 1) { 719e7ab3669SDouglas Gregor // This module map defines a submodule. Go find the module of which it 720e7ab3669SDouglas Gregor // is a submodule. 721e7ab3669SDouglas Gregor ActiveModule = 0; 722e7ab3669SDouglas Gregor for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) { 723e7ab3669SDouglas Gregor if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) { 724e7ab3669SDouglas Gregor ActiveModule = Next; 725e7ab3669SDouglas Gregor continue; 726e7ab3669SDouglas Gregor } 727e7ab3669SDouglas Gregor 728e7ab3669SDouglas Gregor if (ActiveModule) { 729e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified) 730e7ab3669SDouglas Gregor << Id[I].first << ActiveModule->getTopLevelModule(); 731e7ab3669SDouglas Gregor } else { 732e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_expected_module_name); 733e7ab3669SDouglas Gregor } 734e7ab3669SDouglas Gregor HadError = true; 735e7ab3669SDouglas Gregor return; 736e7ab3669SDouglas Gregor } 737e7ab3669SDouglas Gregor } 738e7ab3669SDouglas Gregor 739e7ab3669SDouglas Gregor StringRef ModuleName = Id.back().first; 740e7ab3669SDouglas Gregor SourceLocation ModuleNameLoc = Id.back().second; 741718292f2SDouglas Gregor 742718292f2SDouglas Gregor // Parse the opening brace. 743718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 744718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 745718292f2SDouglas Gregor << ModuleName; 746718292f2SDouglas Gregor HadError = true; 747718292f2SDouglas Gregor return; 748718292f2SDouglas Gregor } 749718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 750718292f2SDouglas Gregor 751718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 752718292f2SDouglas Gregor llvm::StringMap<Module *> &ModuleSpace 753718292f2SDouglas Gregor = ActiveModule? ActiveModule->SubModules : Map.Modules; 754718292f2SDouglas Gregor llvm::StringMap<Module *>::iterator ExistingModule 755718292f2SDouglas Gregor = ModuleSpace.find(ModuleName); 756718292f2SDouglas Gregor if (ExistingModule != ModuleSpace.end()) { 757718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 758718292f2SDouglas Gregor << ModuleName; 759718292f2SDouglas Gregor Diags.Report(ExistingModule->getValue()->DefinitionLoc, 760718292f2SDouglas Gregor diag::note_mmap_prev_definition); 761718292f2SDouglas Gregor 762718292f2SDouglas Gregor // Skip the module definition. 763718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 764718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 765718292f2SDouglas Gregor consumeToken(); 766718292f2SDouglas Gregor 767718292f2SDouglas Gregor HadError = true; 768718292f2SDouglas Gregor return; 769718292f2SDouglas Gregor } 770718292f2SDouglas Gregor 771718292f2SDouglas Gregor // Start defining this module. 772755b2055SDouglas Gregor ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework, 773755b2055SDouglas Gregor Explicit); 774718292f2SDouglas Gregor ModuleSpace[ModuleName] = ActiveModule; 775718292f2SDouglas Gregor 776718292f2SDouglas Gregor bool Done = false; 777718292f2SDouglas Gregor do { 778718292f2SDouglas Gregor switch (Tok.Kind) { 779718292f2SDouglas Gregor case MMToken::EndOfFile: 780718292f2SDouglas Gregor case MMToken::RBrace: 781718292f2SDouglas Gregor Done = true; 782718292f2SDouglas Gregor break; 783718292f2SDouglas Gregor 784718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 785f2161a70SDouglas Gregor case MMToken::FrameworkKeyword: 786718292f2SDouglas Gregor case MMToken::ModuleKeyword: 787718292f2SDouglas Gregor parseModuleDecl(); 788718292f2SDouglas Gregor break; 789718292f2SDouglas Gregor 7902b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 7912b82c2a5SDouglas Gregor parseExportDecl(); 7922b82c2a5SDouglas Gregor break; 7932b82c2a5SDouglas Gregor 794718292f2SDouglas Gregor case MMToken::HeaderKeyword: 795718292f2SDouglas Gregor parseHeaderDecl(); 796718292f2SDouglas Gregor break; 797718292f2SDouglas Gregor 798718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 799718292f2SDouglas Gregor parseUmbrellaDecl(); 800718292f2SDouglas Gregor break; 801718292f2SDouglas Gregor 802718292f2SDouglas Gregor default: 803718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 804718292f2SDouglas Gregor consumeToken(); 805718292f2SDouglas Gregor break; 806718292f2SDouglas Gregor } 807718292f2SDouglas Gregor } while (!Done); 808718292f2SDouglas Gregor 809718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 810718292f2SDouglas Gregor consumeToken(); 811718292f2SDouglas Gregor else { 812718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 813718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 814718292f2SDouglas Gregor HadError = true; 815718292f2SDouglas Gregor } 816718292f2SDouglas Gregor 817e7ab3669SDouglas Gregor // We're done parsing this module. Pop back to the previous module. 818e7ab3669SDouglas Gregor ActiveModule = PreviousActiveModule; 819718292f2SDouglas Gregor } 820718292f2SDouglas Gregor 821f2161a70SDouglas Gregor /// \brief Append to \p Paths the set of paths needed to get to the 822f2161a70SDouglas Gregor /// subframework in which the given module lives. 823f2161a70SDouglas Gregor void appendSubframeworkPaths(Module *Mod, llvm::SmallVectorImpl<char> &Path) { 824f2161a70SDouglas Gregor // Collect the framework names from the given module to the top-level module. 825f2161a70SDouglas Gregor llvm::SmallVector<StringRef, 2> Paths; 826f2161a70SDouglas Gregor for (; Mod; Mod = Mod->Parent) { 827f2161a70SDouglas Gregor if (Mod->IsFramework) 828f2161a70SDouglas Gregor Paths.push_back(Mod->Name); 829f2161a70SDouglas Gregor } 830f2161a70SDouglas Gregor 831f2161a70SDouglas Gregor if (Paths.empty()) 832f2161a70SDouglas Gregor return; 833f2161a70SDouglas Gregor 834f2161a70SDouglas Gregor // Add Frameworks/Name.framework for each subframework. 835f2161a70SDouglas Gregor for (unsigned I = Paths.size() - 1; I != 0; --I) { 836f2161a70SDouglas Gregor llvm::sys::path::append(Path, "Frameworks"); 837f2161a70SDouglas Gregor llvm::sys::path::append(Path, Paths[I-1] + ".framework"); 838f2161a70SDouglas Gregor } 839f2161a70SDouglas Gregor } 840f2161a70SDouglas Gregor 841718292f2SDouglas Gregor /// \brief Parse an umbrella header declaration. 842718292f2SDouglas Gregor /// 843718292f2SDouglas Gregor /// umbrella-declaration: 844718292f2SDouglas Gregor /// 'umbrella' string-literal 845718292f2SDouglas Gregor void ModuleMapParser::parseUmbrellaDecl() { 846718292f2SDouglas Gregor assert(Tok.is(MMToken::UmbrellaKeyword)); 847718292f2SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 848718292f2SDouglas Gregor 849718292f2SDouglas Gregor // Parse the header name. 850718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 851718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 852718292f2SDouglas Gregor << "umbrella"; 853718292f2SDouglas Gregor HadError = true; 854718292f2SDouglas Gregor return; 855718292f2SDouglas Gregor } 856e7ab3669SDouglas Gregor std::string FileName = Tok.getString(); 857718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 858718292f2SDouglas Gregor 8595257fc63SDouglas Gregor // Check whether we already have an umbrella header. 8605257fc63SDouglas Gregor if (ActiveModule->UmbrellaHeader) { 8615257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict) 8625257fc63SDouglas Gregor << ActiveModule->getFullModuleName() 8635257fc63SDouglas Gregor << ActiveModule->UmbrellaHeader->getName(); 8645257fc63SDouglas Gregor HadError = true; 8655257fc63SDouglas Gregor return; 8665257fc63SDouglas Gregor } 8675257fc63SDouglas Gregor 8685257fc63SDouglas Gregor // Look for this file. 8695257fc63SDouglas Gregor llvm::SmallString<128> PathName; 870f545f67dSDouglas Gregor const FileEntry *File = 0; 871f545f67dSDouglas Gregor 872f545f67dSDouglas Gregor if (llvm::sys::path::is_absolute(FileName)) { 873f545f67dSDouglas Gregor PathName = FileName; 874f545f67dSDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 875f545f67dSDouglas Gregor } else { 876f545f67dSDouglas Gregor // Search for the header file within the search directory. 8775257fc63SDouglas Gregor PathName += Directory->getName(); 878755b2055SDouglas Gregor unsigned PathLength = PathName.size(); 879f2161a70SDouglas Gregor 880755b2055SDouglas Gregor if (ActiveModule->isPartOfFramework()) { 881f2161a70SDouglas Gregor appendSubframeworkPaths(ActiveModule, PathName); 882f2161a70SDouglas Gregor 883755b2055SDouglas Gregor // Check whether this file is in the public headers. 884755b2055SDouglas Gregor llvm::sys::path::append(PathName, "Headers"); 8855257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 886755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 887755b2055SDouglas Gregor 888755b2055SDouglas Gregor if (!File) { 889755b2055SDouglas Gregor // Check whether this file is in the private headers. 890755b2055SDouglas Gregor PathName.resize(PathLength); 891755b2055SDouglas Gregor llvm::sys::path::append(PathName, "PrivateHeaders"); 892755b2055SDouglas Gregor llvm::sys::path::append(PathName, FileName); 893755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 894755b2055SDouglas Gregor } 895755b2055SDouglas Gregor } else { 896755b2055SDouglas Gregor // Lookup for normal headers. 897755b2055SDouglas Gregor llvm::sys::path::append(PathName, FileName); 898755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 899755b2055SDouglas Gregor } 900f545f67dSDouglas Gregor } 9015257fc63SDouglas Gregor 9025257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 9035257fc63SDouglas Gregor // Come up with a lazy way to do this. 904755b2055SDouglas Gregor if (File) { 905a89c5ac4SDouglas Gregor const DirectoryEntry *UmbrellaDir = File->getDir(); 906a89c5ac4SDouglas Gregor if (ActiveModule->IsFramework) { 907a89c5ac4SDouglas Gregor // For framework modules, use the framework directory as the umbrella 908a89c5ac4SDouglas Gregor // directory. 909a89c5ac4SDouglas Gregor UmbrellaDir = SourceMgr.getFileManager().getDirectory( 910a89c5ac4SDouglas Gregor llvm::sys::path::parent_path(UmbrellaDir->getName())); 911a89c5ac4SDouglas Gregor } 912a89c5ac4SDouglas Gregor 9135257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 9145257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 9155257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 9165257fc63SDouglas Gregor HadError = true; 917a89c5ac4SDouglas Gregor } else if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) { 918b65dbfffSDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 919b65dbfffSDouglas Gregor << OwningModule->getFullModuleName(); 920b65dbfffSDouglas Gregor HadError = true; 9215257fc63SDouglas Gregor } else { 9225257fc63SDouglas Gregor // Record this umbrella header. 923a89c5ac4SDouglas Gregor Map.setUmbrellaHeader(ActiveModule, File); 9245257fc63SDouglas Gregor } 9255257fc63SDouglas Gregor } else { 9265257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 9275257fc63SDouglas Gregor << true << FileName; 9285257fc63SDouglas Gregor HadError = true; 9295257fc63SDouglas Gregor } 930718292f2SDouglas Gregor } 931718292f2SDouglas Gregor 932718292f2SDouglas Gregor /// \brief Parse a header declaration. 933718292f2SDouglas Gregor /// 934718292f2SDouglas Gregor /// header-declaration: 935718292f2SDouglas Gregor /// 'header' string-literal 936718292f2SDouglas Gregor void ModuleMapParser::parseHeaderDecl() { 937718292f2SDouglas Gregor assert(Tok.is(MMToken::HeaderKeyword)); 9381871ed3dSBenjamin Kramer consumeToken(); 939718292f2SDouglas Gregor 940718292f2SDouglas Gregor // Parse the header name. 941718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 942718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 943718292f2SDouglas Gregor << "header"; 944718292f2SDouglas Gregor HadError = true; 945718292f2SDouglas Gregor return; 946718292f2SDouglas Gregor } 947e7ab3669SDouglas Gregor std::string FileName = Tok.getString(); 948718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 949718292f2SDouglas Gregor 9505257fc63SDouglas Gregor // Look for this file. 951e7ab3669SDouglas Gregor const FileEntry *File = 0; 9525257fc63SDouglas Gregor llvm::SmallString<128> PathName; 953e7ab3669SDouglas Gregor if (llvm::sys::path::is_absolute(FileName)) { 954e7ab3669SDouglas Gregor PathName = FileName; 955e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 956e7ab3669SDouglas Gregor } else { 957e7ab3669SDouglas Gregor // Search for the header file within the search directory. 9585257fc63SDouglas Gregor PathName += Directory->getName(); 959e7ab3669SDouglas Gregor unsigned PathLength = PathName.size(); 960755b2055SDouglas Gregor 961f2161a70SDouglas Gregor if (ActiveModule->isPartOfFramework()) { 962f2161a70SDouglas Gregor appendSubframeworkPaths(ActiveModule, PathName); 963755b2055SDouglas Gregor 964e7ab3669SDouglas Gregor // Check whether this file is in the public headers. 965e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, "Headers"); 9665257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 967e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 968e7ab3669SDouglas Gregor 969e7ab3669SDouglas Gregor if (!File) { 970e7ab3669SDouglas Gregor // Check whether this file is in the private headers. 971e7ab3669SDouglas Gregor PathName.resize(PathLength); 972e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, "PrivateHeaders"); 973e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, FileName); 974e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 975e7ab3669SDouglas Gregor } 976e7ab3669SDouglas Gregor } else { 977e7ab3669SDouglas Gregor // Lookup for normal headers. 978e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, FileName); 979e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 980e7ab3669SDouglas Gregor } 981e7ab3669SDouglas Gregor } 9825257fc63SDouglas Gregor 9835257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 9845257fc63SDouglas Gregor // Come up with a lazy way to do this. 985e7ab3669SDouglas Gregor if (File) { 9865257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 9875257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 9885257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 9895257fc63SDouglas Gregor HadError = true; 9905257fc63SDouglas Gregor } else { 9915257fc63SDouglas Gregor // Record this file. 992a89c5ac4SDouglas Gregor Map.addHeader(ActiveModule, File); 9935257fc63SDouglas Gregor } 9945257fc63SDouglas Gregor } else { 9955257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 9965257fc63SDouglas Gregor << false << FileName; 9975257fc63SDouglas Gregor HadError = true; 9985257fc63SDouglas Gregor } 999718292f2SDouglas Gregor } 1000718292f2SDouglas Gregor 10012b82c2a5SDouglas Gregor /// \brief Parse a module export declaration. 10022b82c2a5SDouglas Gregor /// 10032b82c2a5SDouglas Gregor /// export-declaration: 10042b82c2a5SDouglas Gregor /// 'export' wildcard-module-id 10052b82c2a5SDouglas Gregor /// 10062b82c2a5SDouglas Gregor /// wildcard-module-id: 10072b82c2a5SDouglas Gregor /// identifier 10082b82c2a5SDouglas Gregor /// '*' 10092b82c2a5SDouglas Gregor /// identifier '.' wildcard-module-id 10102b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() { 10112b82c2a5SDouglas Gregor assert(Tok.is(MMToken::ExportKeyword)); 10122b82c2a5SDouglas Gregor SourceLocation ExportLoc = consumeToken(); 10132b82c2a5SDouglas Gregor 10142b82c2a5SDouglas Gregor // Parse the module-id with an optional wildcard at the end. 10152b82c2a5SDouglas Gregor ModuleId ParsedModuleId; 10162b82c2a5SDouglas Gregor bool Wildcard = false; 10172b82c2a5SDouglas Gregor do { 10182b82c2a5SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 10192b82c2a5SDouglas Gregor ParsedModuleId.push_back(std::make_pair(Tok.getString(), 10202b82c2a5SDouglas Gregor Tok.getLocation())); 10212b82c2a5SDouglas Gregor consumeToken(); 10222b82c2a5SDouglas Gregor 10232b82c2a5SDouglas Gregor if (Tok.is(MMToken::Period)) { 10242b82c2a5SDouglas Gregor consumeToken(); 10252b82c2a5SDouglas Gregor continue; 10262b82c2a5SDouglas Gregor } 10272b82c2a5SDouglas Gregor 10282b82c2a5SDouglas Gregor break; 10292b82c2a5SDouglas Gregor } 10302b82c2a5SDouglas Gregor 10312b82c2a5SDouglas Gregor if(Tok.is(MMToken::Star)) { 10322b82c2a5SDouglas Gregor Wildcard = true; 1033f5eedd05SDouglas Gregor consumeToken(); 10342b82c2a5SDouglas Gregor break; 10352b82c2a5SDouglas Gregor } 10362b82c2a5SDouglas Gregor 10372b82c2a5SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id); 10382b82c2a5SDouglas Gregor HadError = true; 10392b82c2a5SDouglas Gregor return; 10402b82c2a5SDouglas Gregor } while (true); 10412b82c2a5SDouglas Gregor 10422b82c2a5SDouglas Gregor Module::UnresolvedExportDecl Unresolved = { 10432b82c2a5SDouglas Gregor ExportLoc, ParsedModuleId, Wildcard 10442b82c2a5SDouglas Gregor }; 10452b82c2a5SDouglas Gregor ActiveModule->UnresolvedExports.push_back(Unresolved); 10462b82c2a5SDouglas Gregor } 10472b82c2a5SDouglas Gregor 104873441091SDouglas Gregor void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) { 104973441091SDouglas Gregor assert(Tok.is(MMToken::Star)); 105073441091SDouglas Gregor SourceLocation StarLoc = consumeToken(); 105173441091SDouglas Gregor bool Failed = false; 105273441091SDouglas Gregor 105373441091SDouglas Gregor // Inferred modules must be submodules. 105473441091SDouglas Gregor if (!ActiveModule) { 105573441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule); 105673441091SDouglas Gregor Failed = true; 105773441091SDouglas Gregor } 105873441091SDouglas Gregor 105973441091SDouglas Gregor // Inferred modules must have umbrella headers. 1060dd005f69SDouglas Gregor if (!Failed && !ActiveModule->UmbrellaHeader) { 106173441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); 106273441091SDouglas Gregor Failed = true; 106373441091SDouglas Gregor } 106473441091SDouglas Gregor 106573441091SDouglas Gregor // Check for redefinition of an inferred module. 1066dd005f69SDouglas Gregor if (!Failed && ActiveModule->InferSubmodules) { 106773441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_redef); 1068dd005f69SDouglas Gregor if (ActiveModule->InferredSubmoduleLoc.isValid()) 1069dd005f69SDouglas Gregor Diags.Report(ActiveModule->InferredSubmoduleLoc, 107073441091SDouglas Gregor diag::note_mmap_prev_definition); 107173441091SDouglas Gregor Failed = true; 107273441091SDouglas Gregor } 107373441091SDouglas Gregor 107473441091SDouglas Gregor // If there were any problems with this inferred submodule, skip its body. 107573441091SDouglas Gregor if (Failed) { 107673441091SDouglas Gregor if (Tok.is(MMToken::LBrace)) { 107773441091SDouglas Gregor consumeToken(); 107873441091SDouglas Gregor skipUntil(MMToken::RBrace); 107973441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 108073441091SDouglas Gregor consumeToken(); 108173441091SDouglas Gregor } 108273441091SDouglas Gregor HadError = true; 108373441091SDouglas Gregor return; 108473441091SDouglas Gregor } 108573441091SDouglas Gregor 108673441091SDouglas Gregor // Note that we have an inferred submodule. 1087dd005f69SDouglas Gregor ActiveModule->InferSubmodules = true; 1088dd005f69SDouglas Gregor ActiveModule->InferredSubmoduleLoc = StarLoc; 1089dd005f69SDouglas Gregor ActiveModule->InferExplicitSubmodules = Explicit; 109073441091SDouglas Gregor 109173441091SDouglas Gregor // Parse the opening brace. 109273441091SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 109373441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard); 109473441091SDouglas Gregor HadError = true; 109573441091SDouglas Gregor return; 109673441091SDouglas Gregor } 109773441091SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 109873441091SDouglas Gregor 109973441091SDouglas Gregor // Parse the body of the inferred submodule. 110073441091SDouglas Gregor bool Done = false; 110173441091SDouglas Gregor do { 110273441091SDouglas Gregor switch (Tok.Kind) { 110373441091SDouglas Gregor case MMToken::EndOfFile: 110473441091SDouglas Gregor case MMToken::RBrace: 110573441091SDouglas Gregor Done = true; 110673441091SDouglas Gregor break; 110773441091SDouglas Gregor 110873441091SDouglas Gregor case MMToken::ExportKeyword: { 110973441091SDouglas Gregor consumeToken(); 111073441091SDouglas Gregor if (Tok.is(MMToken::Star)) 1111dd005f69SDouglas Gregor ActiveModule->InferExportWildcard = true; 111273441091SDouglas Gregor else 111373441091SDouglas Gregor Diags.Report(Tok.getLocation(), 111473441091SDouglas Gregor diag::err_mmap_expected_export_wildcard); 111573441091SDouglas Gregor consumeToken(); 111673441091SDouglas Gregor break; 111773441091SDouglas Gregor } 111873441091SDouglas Gregor 111973441091SDouglas Gregor case MMToken::ExplicitKeyword: 112073441091SDouglas Gregor case MMToken::ModuleKeyword: 112173441091SDouglas Gregor case MMToken::HeaderKeyword: 112273441091SDouglas Gregor case MMToken::UmbrellaKeyword: 112373441091SDouglas Gregor default: 112473441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_wildcard_member); 112573441091SDouglas Gregor consumeToken(); 112673441091SDouglas Gregor break; 112773441091SDouglas Gregor } 112873441091SDouglas Gregor } while (!Done); 112973441091SDouglas Gregor 113073441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 113173441091SDouglas Gregor consumeToken(); 113273441091SDouglas Gregor else { 113373441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 113473441091SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 113573441091SDouglas Gregor HadError = true; 113673441091SDouglas Gregor } 113773441091SDouglas Gregor } 113873441091SDouglas Gregor 1139718292f2SDouglas Gregor /// \brief Parse a module map file. 1140718292f2SDouglas Gregor /// 1141718292f2SDouglas Gregor /// module-map-file: 1142718292f2SDouglas Gregor /// module-declaration* 1143718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 1144718292f2SDouglas Gregor do { 1145718292f2SDouglas Gregor switch (Tok.Kind) { 1146718292f2SDouglas Gregor case MMToken::EndOfFile: 1147718292f2SDouglas Gregor return HadError; 1148718292f2SDouglas Gregor 1149e7ab3669SDouglas Gregor case MMToken::ExplicitKeyword: 1150718292f2SDouglas Gregor case MMToken::ModuleKeyword: 1151755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 1152718292f2SDouglas Gregor parseModuleDecl(); 1153718292f2SDouglas Gregor break; 1154718292f2SDouglas Gregor 11552b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 1156718292f2SDouglas Gregor case MMToken::HeaderKeyword: 1157718292f2SDouglas Gregor case MMToken::Identifier: 1158718292f2SDouglas Gregor case MMToken::LBrace: 11592b82c2a5SDouglas Gregor case MMToken::Period: 1160718292f2SDouglas Gregor case MMToken::RBrace: 11612b82c2a5SDouglas Gregor case MMToken::Star: 1162718292f2SDouglas Gregor case MMToken::StringLiteral: 1163718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 1164718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 1165718292f2SDouglas Gregor HadError = true; 1166718292f2SDouglas Gregor consumeToken(); 1167718292f2SDouglas Gregor break; 1168718292f2SDouglas Gregor } 1169718292f2SDouglas Gregor } while (true); 1170718292f2SDouglas Gregor 1171718292f2SDouglas Gregor return HadError; 1172718292f2SDouglas Gregor } 1173718292f2SDouglas Gregor 1174718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) { 1175718292f2SDouglas Gregor FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User); 1176718292f2SDouglas Gregor const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID); 1177718292f2SDouglas Gregor if (!Buffer) 1178718292f2SDouglas Gregor return true; 1179718292f2SDouglas Gregor 1180718292f2SDouglas Gregor // Parse this module map file. 1181718292f2SDouglas Gregor Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts); 1182718292f2SDouglas Gregor Diags->getClient()->BeginSourceFile(LangOpts); 11835257fc63SDouglas Gregor ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir()); 1184718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 1185718292f2SDouglas Gregor Diags->getClient()->EndSourceFile(); 1186718292f2SDouglas Gregor 1187718292f2SDouglas Gregor return Result; 1188718292f2SDouglas Gregor } 1189