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". 1219458f82dSDouglas Gregor bool Explicit = UmbrellaModule->InferExplicitSubmodules; 122a89c5ac4SDouglas Gregor unsigned LastSkippedDir = SkippedDirs.size(); 1239458f82dSDouglas Gregor if (LastSkippedDir && UmbrellaModule->IsFramework) { 1249458f82dSDouglas Gregor if (llvm::sys::path::filename(SkippedDirs.back()->getName()) 1259458f82dSDouglas Gregor == "PrivateHeaders") { 1269458f82dSDouglas Gregor // For private headers, add an explicit "Private" module. 1279458f82dSDouglas Gregor // FIXME: This feels somewhat hackish. Do we want to introduce 1289458f82dSDouglas Gregor // some kind of "umbrella directory" here? 1299458f82dSDouglas Gregor Result = findOrCreateModule("Private", Result, 1309458f82dSDouglas Gregor /*IsFramework=*/false, 1319458f82dSDouglas Gregor /*IsExplicit=*/true).first; 1329458f82dSDouglas Gregor Explicit = true; 1339458f82dSDouglas Gregor } 1349458f82dSDouglas Gregor 135a89c5ac4SDouglas Gregor --LastSkippedDir; 1369458f82dSDouglas 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, 1429458f82dSDouglas 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, 1569458f82dSDouglas 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; 276*ddaa69cbSDouglas Gregor llvm::SmallString<128> SubframeworksDirName 277*ddaa69cbSDouglas Gregor = StringRef(FrameworkDir->getName()); 278e89dbc1dSDouglas Gregor llvm::sys::path::append(SubframeworksDirName, "Frameworks"); 279*ddaa69cbSDouglas Gregor llvm::SmallString<128> SubframeworksDirNameNative; 280*ddaa69cbSDouglas Gregor llvm::sys::path::native(SubframeworksDirName.str(), 281*ddaa69cbSDouglas Gregor SubframeworksDirNameNative); 282*ddaa69cbSDouglas Gregor for (llvm::sys::fs::directory_iterator 283*ddaa69cbSDouglas Gregor Dir(SubframeworksDirNameNative.str(), EC), DirEnd; 284e89dbc1dSDouglas Gregor Dir != DirEnd && !EC; Dir.increment(EC)) { 285e89dbc1dSDouglas Gregor if (!StringRef(Dir->path()).endswith(".framework")) 286e89dbc1dSDouglas Gregor continue; 287f2161a70SDouglas Gregor 288e89dbc1dSDouglas Gregor if (const DirectoryEntry *SubframeworkDir 289e89dbc1dSDouglas Gregor = FileMgr.getDirectory(Dir->path())) { 290e89dbc1dSDouglas Gregor // FIXME: Do we want to warn about subframeworks without umbrella headers? 291e89dbc1dSDouglas Gregor inferFrameworkModule(llvm::sys::path::stem(Dir->path()), SubframeworkDir, 292e89dbc1dSDouglas Gregor Result); 293e89dbc1dSDouglas Gregor } 294e89dbc1dSDouglas Gregor } 295e89dbc1dSDouglas Gregor 2969458f82dSDouglas Gregor // Look for private headers. 2979458f82dSDouglas Gregor Module *ModulePrivate = 0; 2989458f82dSDouglas Gregor llvm::SmallString<128> PrivateHeadersDirName(FrameworkDir->getName()); 2999458f82dSDouglas Gregor llvm::sys::path::append(PrivateHeadersDirName, "PrivateHeaders"); 300*ddaa69cbSDouglas Gregor llvm::SmallString<128> PrivateHeadersDirNameNative; 301*ddaa69cbSDouglas Gregor llvm::sys::path::native(PrivateHeadersDirName.str(), 302*ddaa69cbSDouglas Gregor PrivateHeadersDirNameNative); 303*ddaa69cbSDouglas Gregor for (llvm::sys::fs::directory_iterator 304*ddaa69cbSDouglas Gregor Dir(PrivateHeadersDirNameNative.str(), EC), DirEnd; 3059458f82dSDouglas Gregor Dir != DirEnd && !EC; Dir.increment(EC)) { 3069458f82dSDouglas Gregor // Check whether this entry has an extension typically associated with 3079458f82dSDouglas Gregor // headers. 3089458f82dSDouglas Gregor if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->path())) 3099458f82dSDouglas Gregor .Cases(".h", ".H", ".hh", ".hpp", true) 3109458f82dSDouglas Gregor .Default(false)) 3119458f82dSDouglas Gregor continue; 3129458f82dSDouglas Gregor 3139458f82dSDouglas Gregor if (const FileEntry *PrivateHeader = FileMgr.getFile(Dir->path())) { 3149458f82dSDouglas Gregor // Create the "private" submodule, if we haven't done so already. 3159458f82dSDouglas Gregor if (!ModulePrivate) { 3169458f82dSDouglas Gregor ModulePrivate = findOrCreateModule("Private", Result, 3179458f82dSDouglas Gregor /*IsFramework=*/false, 3189458f82dSDouglas Gregor /*IsExplicit=*/true).first; 3199458f82dSDouglas Gregor } 3209458f82dSDouglas Gregor 3219458f82dSDouglas Gregor Module *Sub = findOrCreateModule(llvm::sys::path::stem(Dir->path()), 3229458f82dSDouglas Gregor ModulePrivate, /*IsFramework=*/false, 3239458f82dSDouglas Gregor /*IsExplicit=*/true).first; 3249458f82dSDouglas Gregor // header "the private header" 3259458f82dSDouglas Gregor Sub->Headers.push_back(PrivateHeader); 3269458f82dSDouglas Gregor 3279458f82dSDouglas Gregor // export * 3289458f82dSDouglas Gregor Sub->Exports.push_back(Module::ExportDecl(0, true)); 3299458f82dSDouglas Gregor 3309458f82dSDouglas Gregor Headers[PrivateHeader] = Sub; 3319458f82dSDouglas Gregor } 3329458f82dSDouglas Gregor } 3339458f82dSDouglas Gregor 33456c64013SDouglas Gregor return Result; 33556c64013SDouglas Gregor } 33656c64013SDouglas Gregor 337a89c5ac4SDouglas Gregor void ModuleMap::setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader){ 338a89c5ac4SDouglas Gregor Headers[UmbrellaHeader] = Mod; 339a89c5ac4SDouglas Gregor Mod->UmbrellaHeader = UmbrellaHeader; 340a89c5ac4SDouglas Gregor 341a89c5ac4SDouglas Gregor const DirectoryEntry *UmbrellaDir = UmbrellaHeader->getDir(); 342a89c5ac4SDouglas Gregor if (Mod->IsFramework) 343a89c5ac4SDouglas Gregor UmbrellaDir = SourceMgr->getFileManager().getDirectory( 344a89c5ac4SDouglas Gregor llvm::sys::path::parent_path(UmbrellaDir->getName())); 345a89c5ac4SDouglas Gregor 346a89c5ac4SDouglas Gregor UmbrellaDirs[UmbrellaDir] = Mod; 347a89c5ac4SDouglas Gregor } 348a89c5ac4SDouglas Gregor 349a89c5ac4SDouglas Gregor void ModuleMap::addHeader(Module *Mod, const FileEntry *Header) { 350a89c5ac4SDouglas Gregor Mod->Headers.push_back(Header); 351a89c5ac4SDouglas Gregor Headers[Header] = Mod; 352a89c5ac4SDouglas Gregor } 353a89c5ac4SDouglas Gregor 354514b636aSDouglas Gregor const FileEntry * 355de3ef502SDouglas Gregor ModuleMap::getContainingModuleMapFile(Module *Module) { 356514b636aSDouglas Gregor if (Module->DefinitionLoc.isInvalid() || !SourceMgr) 357514b636aSDouglas Gregor return 0; 358514b636aSDouglas Gregor 359514b636aSDouglas Gregor return SourceMgr->getFileEntryForID( 360514b636aSDouglas Gregor SourceMgr->getFileID(Module->DefinitionLoc)); 361514b636aSDouglas Gregor } 362514b636aSDouglas Gregor 363718292f2SDouglas Gregor void ModuleMap::dump() { 364718292f2SDouglas Gregor llvm::errs() << "Modules:"; 365718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 366718292f2SDouglas Gregor MEnd = Modules.end(); 367718292f2SDouglas Gregor M != MEnd; ++M) 368d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 369718292f2SDouglas Gregor 370718292f2SDouglas Gregor llvm::errs() << "Headers:"; 371718292f2SDouglas Gregor for (llvm::DenseMap<const FileEntry *, Module *>::iterator 372718292f2SDouglas Gregor H = Headers.begin(), 373718292f2SDouglas Gregor HEnd = Headers.end(); 374718292f2SDouglas Gregor H != HEnd; ++H) { 375718292f2SDouglas Gregor llvm::errs() << " \"" << H->first->getName() << "\" -> " 376718292f2SDouglas Gregor << H->second->getFullModuleName() << "\n"; 377718292f2SDouglas Gregor } 378718292f2SDouglas Gregor } 379718292f2SDouglas Gregor 3802b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) { 3812b82c2a5SDouglas Gregor bool HadError = false; 3822b82c2a5SDouglas Gregor for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) { 3832b82c2a5SDouglas Gregor Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I], 3842b82c2a5SDouglas Gregor Complain); 385f5eedd05SDouglas Gregor if (Export.getPointer() || Export.getInt()) 3862b82c2a5SDouglas Gregor Mod->Exports.push_back(Export); 3872b82c2a5SDouglas Gregor else 3882b82c2a5SDouglas Gregor HadError = true; 3892b82c2a5SDouglas Gregor } 3902b82c2a5SDouglas Gregor Mod->UnresolvedExports.clear(); 3912b82c2a5SDouglas Gregor return HadError; 3922b82c2a5SDouglas Gregor } 3932b82c2a5SDouglas Gregor 3940093b3c7SDouglas Gregor Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) { 3950093b3c7SDouglas Gregor if (Loc.isInvalid()) 3960093b3c7SDouglas Gregor return 0; 3970093b3c7SDouglas Gregor 3980093b3c7SDouglas Gregor // Use the expansion location to determine which module we're in. 3990093b3c7SDouglas Gregor FullSourceLoc ExpansionLoc = Loc.getExpansionLoc(); 4000093b3c7SDouglas Gregor if (!ExpansionLoc.isFileID()) 4010093b3c7SDouglas Gregor return 0; 4020093b3c7SDouglas Gregor 4030093b3c7SDouglas Gregor 4040093b3c7SDouglas Gregor const SourceManager &SrcMgr = Loc.getManager(); 4050093b3c7SDouglas Gregor FileID ExpansionFileID = ExpansionLoc.getFileID(); 4060093b3c7SDouglas Gregor const FileEntry *ExpansionFile = SrcMgr.getFileEntryForID(ExpansionFileID); 4070093b3c7SDouglas Gregor if (!ExpansionFile) 4080093b3c7SDouglas Gregor return 0; 4090093b3c7SDouglas Gregor 4100093b3c7SDouglas Gregor // Find the module that owns this header. 4110093b3c7SDouglas Gregor return findModuleForHeader(ExpansionFile); 4120093b3c7SDouglas Gregor } 4130093b3c7SDouglas Gregor 414718292f2SDouglas Gregor //----------------------------------------------------------------------------// 415718292f2SDouglas Gregor // Module map file parser 416718292f2SDouglas Gregor //----------------------------------------------------------------------------// 417718292f2SDouglas Gregor 418718292f2SDouglas Gregor namespace clang { 419718292f2SDouglas Gregor /// \brief A token in a module map file. 420718292f2SDouglas Gregor struct MMToken { 421718292f2SDouglas Gregor enum TokenKind { 422718292f2SDouglas Gregor EndOfFile, 423718292f2SDouglas Gregor HeaderKeyword, 424718292f2SDouglas Gregor Identifier, 425718292f2SDouglas Gregor ExplicitKeyword, 4262b82c2a5SDouglas Gregor ExportKeyword, 427755b2055SDouglas Gregor FrameworkKeyword, 428718292f2SDouglas Gregor ModuleKeyword, 4292b82c2a5SDouglas Gregor Period, 430718292f2SDouglas Gregor UmbrellaKeyword, 4312b82c2a5SDouglas Gregor Star, 432718292f2SDouglas Gregor StringLiteral, 433718292f2SDouglas Gregor LBrace, 434718292f2SDouglas Gregor RBrace 435718292f2SDouglas Gregor } Kind; 436718292f2SDouglas Gregor 437718292f2SDouglas Gregor unsigned Location; 438718292f2SDouglas Gregor unsigned StringLength; 439718292f2SDouglas Gregor const char *StringData; 440718292f2SDouglas Gregor 441718292f2SDouglas Gregor void clear() { 442718292f2SDouglas Gregor Kind = EndOfFile; 443718292f2SDouglas Gregor Location = 0; 444718292f2SDouglas Gregor StringLength = 0; 445718292f2SDouglas Gregor StringData = 0; 446718292f2SDouglas Gregor } 447718292f2SDouglas Gregor 448718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 449718292f2SDouglas Gregor 450718292f2SDouglas Gregor SourceLocation getLocation() const { 451718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 452718292f2SDouglas Gregor } 453718292f2SDouglas Gregor 454718292f2SDouglas Gregor StringRef getString() const { 455718292f2SDouglas Gregor return StringRef(StringData, StringLength); 456718292f2SDouglas Gregor } 457718292f2SDouglas Gregor }; 458718292f2SDouglas Gregor 459718292f2SDouglas Gregor class ModuleMapParser { 460718292f2SDouglas Gregor Lexer &L; 461718292f2SDouglas Gregor SourceManager &SourceMgr; 462718292f2SDouglas Gregor DiagnosticsEngine &Diags; 463718292f2SDouglas Gregor ModuleMap ⤅ 464718292f2SDouglas Gregor 4655257fc63SDouglas Gregor /// \brief The directory that this module map resides in. 4665257fc63SDouglas Gregor const DirectoryEntry *Directory; 4675257fc63SDouglas Gregor 468718292f2SDouglas Gregor /// \brief Whether an error occurred. 469718292f2SDouglas Gregor bool HadError; 470718292f2SDouglas Gregor 471718292f2SDouglas Gregor /// \brief Default target information, used only for string literal 472718292f2SDouglas Gregor /// parsing. 473718292f2SDouglas Gregor TargetInfo *Target; 474718292f2SDouglas Gregor 475718292f2SDouglas Gregor /// \brief Stores string data for the various string literals referenced 476718292f2SDouglas Gregor /// during parsing. 477718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 478718292f2SDouglas Gregor 479718292f2SDouglas Gregor /// \brief The current token. 480718292f2SDouglas Gregor MMToken Tok; 481718292f2SDouglas Gregor 482718292f2SDouglas Gregor /// \brief The active module. 483de3ef502SDouglas Gregor Module *ActiveModule; 484718292f2SDouglas Gregor 485718292f2SDouglas Gregor /// \brief Consume the current token and return its location. 486718292f2SDouglas Gregor SourceLocation consumeToken(); 487718292f2SDouglas Gregor 488718292f2SDouglas Gregor /// \brief Skip tokens until we reach the a token with the given kind 489718292f2SDouglas Gregor /// (or the end of the file). 490718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 491718292f2SDouglas Gregor 492e7ab3669SDouglas Gregor typedef llvm::SmallVector<std::pair<std::string, SourceLocation>, 2> 493e7ab3669SDouglas Gregor ModuleId; 494e7ab3669SDouglas Gregor bool parseModuleId(ModuleId &Id); 495718292f2SDouglas Gregor void parseModuleDecl(); 496718292f2SDouglas Gregor void parseUmbrellaDecl(); 497718292f2SDouglas Gregor void parseHeaderDecl(); 4982b82c2a5SDouglas Gregor void parseExportDecl(); 49973441091SDouglas Gregor void parseInferredSubmoduleDecl(bool Explicit); 500718292f2SDouglas Gregor 501718292f2SDouglas Gregor public: 502718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 503718292f2SDouglas Gregor DiagnosticsEngine &Diags, 5045257fc63SDouglas Gregor ModuleMap &Map, 5055257fc63SDouglas Gregor const DirectoryEntry *Directory) 5065257fc63SDouglas Gregor : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map), 5075257fc63SDouglas Gregor Directory(Directory), HadError(false), ActiveModule(0) 508718292f2SDouglas Gregor { 509718292f2SDouglas Gregor TargetOptions TargetOpts; 510718292f2SDouglas Gregor TargetOpts.Triple = llvm::sys::getDefaultTargetTriple(); 511718292f2SDouglas Gregor Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); 512718292f2SDouglas Gregor 513718292f2SDouglas Gregor Tok.clear(); 514718292f2SDouglas Gregor consumeToken(); 515718292f2SDouglas Gregor } 516718292f2SDouglas Gregor 517718292f2SDouglas Gregor bool parseModuleMapFile(); 518718292f2SDouglas Gregor }; 519718292f2SDouglas Gregor } 520718292f2SDouglas Gregor 521718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 522718292f2SDouglas Gregor retry: 523718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 524718292f2SDouglas Gregor Tok.clear(); 525718292f2SDouglas Gregor 526718292f2SDouglas Gregor Token LToken; 527718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 528718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 529718292f2SDouglas Gregor switch (LToken.getKind()) { 530718292f2SDouglas Gregor case tok::raw_identifier: 531718292f2SDouglas Gregor Tok.StringData = LToken.getRawIdentifierData(); 532718292f2SDouglas Gregor Tok.StringLength = LToken.getLength(); 533718292f2SDouglas Gregor Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString()) 534718292f2SDouglas Gregor .Case("header", MMToken::HeaderKeyword) 535718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 5362b82c2a5SDouglas Gregor .Case("export", MMToken::ExportKeyword) 537755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 538718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 539718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 540718292f2SDouglas Gregor .Default(MMToken::Identifier); 541718292f2SDouglas Gregor break; 542718292f2SDouglas Gregor 543718292f2SDouglas Gregor case tok::eof: 544718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 545718292f2SDouglas Gregor break; 546718292f2SDouglas Gregor 547718292f2SDouglas Gregor case tok::l_brace: 548718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 549718292f2SDouglas Gregor break; 550718292f2SDouglas Gregor 5512b82c2a5SDouglas Gregor case tok::period: 5522b82c2a5SDouglas Gregor Tok.Kind = MMToken::Period; 5532b82c2a5SDouglas Gregor break; 5542b82c2a5SDouglas Gregor 555718292f2SDouglas Gregor case tok::r_brace: 556718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 557718292f2SDouglas Gregor break; 558718292f2SDouglas Gregor 5592b82c2a5SDouglas Gregor case tok::star: 5602b82c2a5SDouglas Gregor Tok.Kind = MMToken::Star; 5612b82c2a5SDouglas Gregor break; 5622b82c2a5SDouglas Gregor 563718292f2SDouglas Gregor case tok::string_literal: { 564718292f2SDouglas Gregor // Parse the string literal. 565718292f2SDouglas Gregor LangOptions LangOpts; 566718292f2SDouglas Gregor StringLiteralParser StringLiteral(<oken, 1, SourceMgr, LangOpts, *Target); 567718292f2SDouglas Gregor if (StringLiteral.hadError) 568718292f2SDouglas Gregor goto retry; 569718292f2SDouglas Gregor 570718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 571718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 572718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 573718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 574718292f2SDouglas Gregor Saved[Length] = 0; 575718292f2SDouglas Gregor 576718292f2SDouglas Gregor // Form the token. 577718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 578718292f2SDouglas Gregor Tok.StringData = Saved; 579718292f2SDouglas Gregor Tok.StringLength = Length; 580718292f2SDouglas Gregor break; 581718292f2SDouglas Gregor } 582718292f2SDouglas Gregor 583718292f2SDouglas Gregor case tok::comment: 584718292f2SDouglas Gregor goto retry; 585718292f2SDouglas Gregor 586718292f2SDouglas Gregor default: 587718292f2SDouglas Gregor Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token); 588718292f2SDouglas Gregor HadError = true; 589718292f2SDouglas Gregor goto retry; 590718292f2SDouglas Gregor } 591718292f2SDouglas Gregor 592718292f2SDouglas Gregor return Result; 593718292f2SDouglas Gregor } 594718292f2SDouglas Gregor 595718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 596718292f2SDouglas Gregor unsigned braceDepth = 0; 597718292f2SDouglas Gregor do { 598718292f2SDouglas Gregor switch (Tok.Kind) { 599718292f2SDouglas Gregor case MMToken::EndOfFile: 600718292f2SDouglas Gregor return; 601718292f2SDouglas Gregor 602718292f2SDouglas Gregor case MMToken::LBrace: 603718292f2SDouglas Gregor if (Tok.is(K) && braceDepth == 0) 604718292f2SDouglas Gregor return; 605718292f2SDouglas Gregor 606718292f2SDouglas Gregor ++braceDepth; 607718292f2SDouglas Gregor break; 608718292f2SDouglas Gregor 609718292f2SDouglas Gregor case MMToken::RBrace: 610718292f2SDouglas Gregor if (braceDepth > 0) 611718292f2SDouglas Gregor --braceDepth; 612718292f2SDouglas Gregor else if (Tok.is(K)) 613718292f2SDouglas Gregor return; 614718292f2SDouglas Gregor break; 615718292f2SDouglas Gregor 616718292f2SDouglas Gregor default: 617718292f2SDouglas Gregor if (braceDepth == 0 && Tok.is(K)) 618718292f2SDouglas Gregor return; 619718292f2SDouglas Gregor break; 620718292f2SDouglas Gregor } 621718292f2SDouglas Gregor 622718292f2SDouglas Gregor consumeToken(); 623718292f2SDouglas Gregor } while (true); 624718292f2SDouglas Gregor } 625718292f2SDouglas Gregor 626e7ab3669SDouglas Gregor /// \brief Parse a module-id. 627e7ab3669SDouglas Gregor /// 628e7ab3669SDouglas Gregor /// module-id: 629e7ab3669SDouglas Gregor /// identifier 630e7ab3669SDouglas Gregor /// identifier '.' module-id 631e7ab3669SDouglas Gregor /// 632e7ab3669SDouglas Gregor /// \returns true if an error occurred, false otherwise. 633e7ab3669SDouglas Gregor bool ModuleMapParser::parseModuleId(ModuleId &Id) { 634e7ab3669SDouglas Gregor Id.clear(); 635e7ab3669SDouglas Gregor do { 636e7ab3669SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 637e7ab3669SDouglas Gregor Id.push_back(std::make_pair(Tok.getString(), Tok.getLocation())); 638e7ab3669SDouglas Gregor consumeToken(); 639e7ab3669SDouglas Gregor } else { 640e7ab3669SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 641e7ab3669SDouglas Gregor return true; 642e7ab3669SDouglas Gregor } 643e7ab3669SDouglas Gregor 644e7ab3669SDouglas Gregor if (!Tok.is(MMToken::Period)) 645e7ab3669SDouglas Gregor break; 646e7ab3669SDouglas Gregor 647e7ab3669SDouglas Gregor consumeToken(); 648e7ab3669SDouglas Gregor } while (true); 649e7ab3669SDouglas Gregor 650e7ab3669SDouglas Gregor return false; 651e7ab3669SDouglas Gregor } 652e7ab3669SDouglas Gregor 653718292f2SDouglas Gregor /// \brief Parse a module declaration. 654718292f2SDouglas Gregor /// 655718292f2SDouglas Gregor /// module-declaration: 656e7ab3669SDouglas Gregor /// 'explicit'[opt] 'framework'[opt] 'module' module-id { module-member* } 657718292f2SDouglas Gregor /// 658718292f2SDouglas Gregor /// module-member: 659718292f2SDouglas Gregor /// umbrella-declaration 660718292f2SDouglas Gregor /// header-declaration 661e7ab3669SDouglas Gregor /// submodule-declaration 6622b82c2a5SDouglas Gregor /// export-declaration 66373441091SDouglas Gregor /// 66473441091SDouglas Gregor /// submodule-declaration: 66573441091SDouglas Gregor /// module-declaration 66673441091SDouglas Gregor /// inferred-submodule-declaration 667718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 668755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 669755b2055SDouglas Gregor Tok.is(MMToken::FrameworkKeyword)); 670f2161a70SDouglas Gregor // Parse 'explicit' or 'framework' keyword, if present. 671e7ab3669SDouglas Gregor SourceLocation ExplicitLoc; 672718292f2SDouglas Gregor bool Explicit = false; 673f2161a70SDouglas Gregor bool Framework = false; 674755b2055SDouglas Gregor 675f2161a70SDouglas Gregor // Parse 'explicit' keyword, if present. 676f2161a70SDouglas Gregor if (Tok.is(MMToken::ExplicitKeyword)) { 677e7ab3669SDouglas Gregor ExplicitLoc = consumeToken(); 678f2161a70SDouglas Gregor Explicit = true; 679f2161a70SDouglas Gregor } 680f2161a70SDouglas Gregor 681f2161a70SDouglas Gregor // Parse 'framework' keyword, if present. 682755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 683755b2055SDouglas Gregor consumeToken(); 684755b2055SDouglas Gregor Framework = true; 685755b2055SDouglas Gregor } 686718292f2SDouglas Gregor 687718292f2SDouglas Gregor // Parse 'module' keyword. 688718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 689d6343c99SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 690718292f2SDouglas Gregor consumeToken(); 691718292f2SDouglas Gregor HadError = true; 692718292f2SDouglas Gregor return; 693718292f2SDouglas Gregor } 694718292f2SDouglas Gregor consumeToken(); // 'module' keyword 695718292f2SDouglas Gregor 69673441091SDouglas Gregor // If we have a wildcard for the module name, this is an inferred submodule. 69773441091SDouglas Gregor // Parse it. 69873441091SDouglas Gregor if (Tok.is(MMToken::Star)) 69973441091SDouglas Gregor return parseInferredSubmoduleDecl(Explicit); 70073441091SDouglas Gregor 701718292f2SDouglas Gregor // Parse the module name. 702e7ab3669SDouglas Gregor ModuleId Id; 703e7ab3669SDouglas Gregor if (parseModuleId(Id)) { 704718292f2SDouglas Gregor HadError = true; 705718292f2SDouglas Gregor return; 706718292f2SDouglas Gregor } 707e7ab3669SDouglas Gregor 708e7ab3669SDouglas Gregor if (ActiveModule) { 709e7ab3669SDouglas Gregor if (Id.size() > 1) { 710e7ab3669SDouglas Gregor Diags.Report(Id.front().second, diag::err_mmap_nested_submodule_id) 711e7ab3669SDouglas Gregor << SourceRange(Id.front().second, Id.back().second); 712e7ab3669SDouglas Gregor 713e7ab3669SDouglas Gregor HadError = true; 714e7ab3669SDouglas Gregor return; 715e7ab3669SDouglas Gregor } 716e7ab3669SDouglas Gregor } else if (Id.size() == 1 && Explicit) { 717e7ab3669SDouglas Gregor // Top-level modules can't be explicit. 718e7ab3669SDouglas Gregor Diags.Report(ExplicitLoc, diag::err_mmap_explicit_top_level); 719e7ab3669SDouglas Gregor Explicit = false; 720e7ab3669SDouglas Gregor ExplicitLoc = SourceLocation(); 721e7ab3669SDouglas Gregor HadError = true; 722e7ab3669SDouglas Gregor } 723e7ab3669SDouglas Gregor 724e7ab3669SDouglas Gregor Module *PreviousActiveModule = ActiveModule; 725e7ab3669SDouglas Gregor if (Id.size() > 1) { 726e7ab3669SDouglas Gregor // This module map defines a submodule. Go find the module of which it 727e7ab3669SDouglas Gregor // is a submodule. 728e7ab3669SDouglas Gregor ActiveModule = 0; 729e7ab3669SDouglas Gregor for (unsigned I = 0, N = Id.size() - 1; I != N; ++I) { 730e7ab3669SDouglas Gregor if (Module *Next = Map.lookupModuleQualified(Id[I].first, ActiveModule)) { 731e7ab3669SDouglas Gregor ActiveModule = Next; 732e7ab3669SDouglas Gregor continue; 733e7ab3669SDouglas Gregor } 734e7ab3669SDouglas Gregor 735e7ab3669SDouglas Gregor if (ActiveModule) { 736e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_missing_module_qualified) 737e7ab3669SDouglas Gregor << Id[I].first << ActiveModule->getTopLevelModule(); 738e7ab3669SDouglas Gregor } else { 739e7ab3669SDouglas Gregor Diags.Report(Id[I].second, diag::err_mmap_expected_module_name); 740e7ab3669SDouglas Gregor } 741e7ab3669SDouglas Gregor HadError = true; 742e7ab3669SDouglas Gregor return; 743e7ab3669SDouglas Gregor } 744e7ab3669SDouglas Gregor } 745e7ab3669SDouglas Gregor 746e7ab3669SDouglas Gregor StringRef ModuleName = Id.back().first; 747e7ab3669SDouglas Gregor SourceLocation ModuleNameLoc = Id.back().second; 748718292f2SDouglas Gregor 749718292f2SDouglas Gregor // Parse the opening brace. 750718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 751718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 752718292f2SDouglas Gregor << ModuleName; 753718292f2SDouglas Gregor HadError = true; 754718292f2SDouglas Gregor return; 755718292f2SDouglas Gregor } 756718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 757718292f2SDouglas Gregor 758718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 759718292f2SDouglas Gregor llvm::StringMap<Module *> &ModuleSpace 760718292f2SDouglas Gregor = ActiveModule? ActiveModule->SubModules : Map.Modules; 761718292f2SDouglas Gregor llvm::StringMap<Module *>::iterator ExistingModule 762718292f2SDouglas Gregor = ModuleSpace.find(ModuleName); 763718292f2SDouglas Gregor if (ExistingModule != ModuleSpace.end()) { 764718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 765718292f2SDouglas Gregor << ModuleName; 766718292f2SDouglas Gregor Diags.Report(ExistingModule->getValue()->DefinitionLoc, 767718292f2SDouglas Gregor diag::note_mmap_prev_definition); 768718292f2SDouglas Gregor 769718292f2SDouglas Gregor // Skip the module definition. 770718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 771718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 772718292f2SDouglas Gregor consumeToken(); 773718292f2SDouglas Gregor 774718292f2SDouglas Gregor HadError = true; 775718292f2SDouglas Gregor return; 776718292f2SDouglas Gregor } 777718292f2SDouglas Gregor 778718292f2SDouglas Gregor // Start defining this module. 779755b2055SDouglas Gregor ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework, 780755b2055SDouglas Gregor Explicit); 781718292f2SDouglas Gregor ModuleSpace[ModuleName] = ActiveModule; 782718292f2SDouglas Gregor 783718292f2SDouglas Gregor bool Done = false; 784718292f2SDouglas Gregor do { 785718292f2SDouglas Gregor switch (Tok.Kind) { 786718292f2SDouglas Gregor case MMToken::EndOfFile: 787718292f2SDouglas Gregor case MMToken::RBrace: 788718292f2SDouglas Gregor Done = true; 789718292f2SDouglas Gregor break; 790718292f2SDouglas Gregor 791718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 792f2161a70SDouglas Gregor case MMToken::FrameworkKeyword: 793718292f2SDouglas Gregor case MMToken::ModuleKeyword: 794718292f2SDouglas Gregor parseModuleDecl(); 795718292f2SDouglas Gregor break; 796718292f2SDouglas Gregor 7972b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 7982b82c2a5SDouglas Gregor parseExportDecl(); 7992b82c2a5SDouglas Gregor break; 8002b82c2a5SDouglas Gregor 801718292f2SDouglas Gregor case MMToken::HeaderKeyword: 802718292f2SDouglas Gregor parseHeaderDecl(); 803718292f2SDouglas Gregor break; 804718292f2SDouglas Gregor 805718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 806718292f2SDouglas Gregor parseUmbrellaDecl(); 807718292f2SDouglas Gregor break; 808718292f2SDouglas Gregor 809718292f2SDouglas Gregor default: 810718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 811718292f2SDouglas Gregor consumeToken(); 812718292f2SDouglas Gregor break; 813718292f2SDouglas Gregor } 814718292f2SDouglas Gregor } while (!Done); 815718292f2SDouglas Gregor 816718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 817718292f2SDouglas Gregor consumeToken(); 818718292f2SDouglas Gregor else { 819718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 820718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 821718292f2SDouglas Gregor HadError = true; 822718292f2SDouglas Gregor } 823718292f2SDouglas Gregor 824e7ab3669SDouglas Gregor // We're done parsing this module. Pop back to the previous module. 825e7ab3669SDouglas Gregor ActiveModule = PreviousActiveModule; 826718292f2SDouglas Gregor } 827718292f2SDouglas Gregor 828f2161a70SDouglas Gregor /// \brief Append to \p Paths the set of paths needed to get to the 829f2161a70SDouglas Gregor /// subframework in which the given module lives. 830f2161a70SDouglas Gregor void appendSubframeworkPaths(Module *Mod, llvm::SmallVectorImpl<char> &Path) { 831f2161a70SDouglas Gregor // Collect the framework names from the given module to the top-level module. 832f2161a70SDouglas Gregor llvm::SmallVector<StringRef, 2> Paths; 833f2161a70SDouglas Gregor for (; Mod; Mod = Mod->Parent) { 834f2161a70SDouglas Gregor if (Mod->IsFramework) 835f2161a70SDouglas Gregor Paths.push_back(Mod->Name); 836f2161a70SDouglas Gregor } 837f2161a70SDouglas Gregor 838f2161a70SDouglas Gregor if (Paths.empty()) 839f2161a70SDouglas Gregor return; 840f2161a70SDouglas Gregor 841f2161a70SDouglas Gregor // Add Frameworks/Name.framework for each subframework. 842f2161a70SDouglas Gregor for (unsigned I = Paths.size() - 1; I != 0; --I) { 843f2161a70SDouglas Gregor llvm::sys::path::append(Path, "Frameworks"); 844f2161a70SDouglas Gregor llvm::sys::path::append(Path, Paths[I-1] + ".framework"); 845f2161a70SDouglas Gregor } 846f2161a70SDouglas Gregor } 847f2161a70SDouglas Gregor 848718292f2SDouglas Gregor /// \brief Parse an umbrella header declaration. 849718292f2SDouglas Gregor /// 850718292f2SDouglas Gregor /// umbrella-declaration: 851718292f2SDouglas Gregor /// 'umbrella' string-literal 852718292f2SDouglas Gregor void ModuleMapParser::parseUmbrellaDecl() { 853718292f2SDouglas Gregor assert(Tok.is(MMToken::UmbrellaKeyword)); 854718292f2SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 855718292f2SDouglas Gregor 856718292f2SDouglas Gregor // Parse the header name. 857718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 858718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 859718292f2SDouglas Gregor << "umbrella"; 860718292f2SDouglas Gregor HadError = true; 861718292f2SDouglas Gregor return; 862718292f2SDouglas Gregor } 863e7ab3669SDouglas Gregor std::string FileName = Tok.getString(); 864718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 865718292f2SDouglas Gregor 8665257fc63SDouglas Gregor // Check whether we already have an umbrella header. 8675257fc63SDouglas Gregor if (ActiveModule->UmbrellaHeader) { 8685257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict) 8695257fc63SDouglas Gregor << ActiveModule->getFullModuleName() 8705257fc63SDouglas Gregor << ActiveModule->UmbrellaHeader->getName(); 8715257fc63SDouglas Gregor HadError = true; 8725257fc63SDouglas Gregor return; 8735257fc63SDouglas Gregor } 8745257fc63SDouglas Gregor 8755257fc63SDouglas Gregor // Look for this file. 8765257fc63SDouglas Gregor llvm::SmallString<128> PathName; 877f545f67dSDouglas Gregor const FileEntry *File = 0; 878f545f67dSDouglas Gregor 879f545f67dSDouglas Gregor if (llvm::sys::path::is_absolute(FileName)) { 880f545f67dSDouglas Gregor PathName = FileName; 881f545f67dSDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 882f545f67dSDouglas Gregor } else { 883f545f67dSDouglas Gregor // Search for the header file within the search directory. 8845257fc63SDouglas Gregor PathName += Directory->getName(); 885755b2055SDouglas Gregor unsigned PathLength = PathName.size(); 886f2161a70SDouglas Gregor 887755b2055SDouglas Gregor if (ActiveModule->isPartOfFramework()) { 888f2161a70SDouglas Gregor appendSubframeworkPaths(ActiveModule, PathName); 889f2161a70SDouglas Gregor 890755b2055SDouglas Gregor // Check whether this file is in the public headers. 891755b2055SDouglas Gregor llvm::sys::path::append(PathName, "Headers"); 8925257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 893755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 894755b2055SDouglas Gregor 895755b2055SDouglas Gregor if (!File) { 896755b2055SDouglas Gregor // Check whether this file is in the private headers. 897755b2055SDouglas Gregor PathName.resize(PathLength); 898755b2055SDouglas Gregor llvm::sys::path::append(PathName, "PrivateHeaders"); 899755b2055SDouglas Gregor llvm::sys::path::append(PathName, FileName); 900755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 901755b2055SDouglas Gregor } 902755b2055SDouglas Gregor } else { 903755b2055SDouglas Gregor // Lookup for normal headers. 904755b2055SDouglas Gregor llvm::sys::path::append(PathName, FileName); 905755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 906755b2055SDouglas Gregor } 907f545f67dSDouglas Gregor } 9085257fc63SDouglas Gregor 9095257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 9105257fc63SDouglas Gregor // Come up with a lazy way to do this. 911755b2055SDouglas Gregor if (File) { 912a89c5ac4SDouglas Gregor const DirectoryEntry *UmbrellaDir = File->getDir(); 913a89c5ac4SDouglas Gregor if (ActiveModule->IsFramework) { 914a89c5ac4SDouglas Gregor // For framework modules, use the framework directory as the umbrella 915a89c5ac4SDouglas Gregor // directory. 916a89c5ac4SDouglas Gregor UmbrellaDir = SourceMgr.getFileManager().getDirectory( 917a89c5ac4SDouglas Gregor llvm::sys::path::parent_path(UmbrellaDir->getName())); 918a89c5ac4SDouglas Gregor } 919a89c5ac4SDouglas Gregor 9205257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 9215257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 9225257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 9235257fc63SDouglas Gregor HadError = true; 924a89c5ac4SDouglas Gregor } else if ((OwningModule = Map.UmbrellaDirs[UmbrellaDir])) { 925b65dbfffSDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 926b65dbfffSDouglas Gregor << OwningModule->getFullModuleName(); 927b65dbfffSDouglas Gregor HadError = true; 9285257fc63SDouglas Gregor } else { 9295257fc63SDouglas Gregor // Record this umbrella header. 930a89c5ac4SDouglas Gregor Map.setUmbrellaHeader(ActiveModule, File); 9315257fc63SDouglas Gregor } 9325257fc63SDouglas Gregor } else { 9335257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 9345257fc63SDouglas Gregor << true << FileName; 9355257fc63SDouglas Gregor HadError = true; 9365257fc63SDouglas Gregor } 937718292f2SDouglas Gregor } 938718292f2SDouglas Gregor 939718292f2SDouglas Gregor /// \brief Parse a header declaration. 940718292f2SDouglas Gregor /// 941718292f2SDouglas Gregor /// header-declaration: 942718292f2SDouglas Gregor /// 'header' string-literal 943718292f2SDouglas Gregor void ModuleMapParser::parseHeaderDecl() { 944718292f2SDouglas Gregor assert(Tok.is(MMToken::HeaderKeyword)); 9451871ed3dSBenjamin Kramer consumeToken(); 946718292f2SDouglas Gregor 947718292f2SDouglas Gregor // Parse the header name. 948718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 949718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 950718292f2SDouglas Gregor << "header"; 951718292f2SDouglas Gregor HadError = true; 952718292f2SDouglas Gregor return; 953718292f2SDouglas Gregor } 954e7ab3669SDouglas Gregor std::string FileName = Tok.getString(); 955718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 956718292f2SDouglas Gregor 9575257fc63SDouglas Gregor // Look for this file. 958e7ab3669SDouglas Gregor const FileEntry *File = 0; 9595257fc63SDouglas Gregor llvm::SmallString<128> PathName; 960e7ab3669SDouglas Gregor if (llvm::sys::path::is_absolute(FileName)) { 961e7ab3669SDouglas Gregor PathName = FileName; 962e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 963e7ab3669SDouglas Gregor } else { 964e7ab3669SDouglas Gregor // Search for the header file within the search directory. 9655257fc63SDouglas Gregor PathName += Directory->getName(); 966e7ab3669SDouglas Gregor unsigned PathLength = PathName.size(); 967755b2055SDouglas Gregor 968f2161a70SDouglas Gregor if (ActiveModule->isPartOfFramework()) { 969f2161a70SDouglas Gregor appendSubframeworkPaths(ActiveModule, PathName); 970755b2055SDouglas Gregor 971e7ab3669SDouglas Gregor // Check whether this file is in the public headers. 972e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, "Headers"); 9735257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 974e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 975e7ab3669SDouglas Gregor 976e7ab3669SDouglas Gregor if (!File) { 977e7ab3669SDouglas Gregor // Check whether this file is in the private headers. 978e7ab3669SDouglas Gregor PathName.resize(PathLength); 979e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, "PrivateHeaders"); 980e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, FileName); 981e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 982e7ab3669SDouglas Gregor } 983e7ab3669SDouglas Gregor } else { 984e7ab3669SDouglas Gregor // Lookup for normal headers. 985e7ab3669SDouglas Gregor llvm::sys::path::append(PathName, FileName); 986e7ab3669SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 987e7ab3669SDouglas Gregor } 988e7ab3669SDouglas Gregor } 9895257fc63SDouglas Gregor 9905257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 9915257fc63SDouglas Gregor // Come up with a lazy way to do this. 992e7ab3669SDouglas Gregor if (File) { 9935257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 9945257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 9955257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 9965257fc63SDouglas Gregor HadError = true; 9975257fc63SDouglas Gregor } else { 9985257fc63SDouglas Gregor // Record this file. 999a89c5ac4SDouglas Gregor Map.addHeader(ActiveModule, File); 10005257fc63SDouglas Gregor } 10015257fc63SDouglas Gregor } else { 10025257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 10035257fc63SDouglas Gregor << false << FileName; 10045257fc63SDouglas Gregor HadError = true; 10055257fc63SDouglas Gregor } 1006718292f2SDouglas Gregor } 1007718292f2SDouglas Gregor 10082b82c2a5SDouglas Gregor /// \brief Parse a module export declaration. 10092b82c2a5SDouglas Gregor /// 10102b82c2a5SDouglas Gregor /// export-declaration: 10112b82c2a5SDouglas Gregor /// 'export' wildcard-module-id 10122b82c2a5SDouglas Gregor /// 10132b82c2a5SDouglas Gregor /// wildcard-module-id: 10142b82c2a5SDouglas Gregor /// identifier 10152b82c2a5SDouglas Gregor /// '*' 10162b82c2a5SDouglas Gregor /// identifier '.' wildcard-module-id 10172b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() { 10182b82c2a5SDouglas Gregor assert(Tok.is(MMToken::ExportKeyword)); 10192b82c2a5SDouglas Gregor SourceLocation ExportLoc = consumeToken(); 10202b82c2a5SDouglas Gregor 10212b82c2a5SDouglas Gregor // Parse the module-id with an optional wildcard at the end. 10222b82c2a5SDouglas Gregor ModuleId ParsedModuleId; 10232b82c2a5SDouglas Gregor bool Wildcard = false; 10242b82c2a5SDouglas Gregor do { 10252b82c2a5SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 10262b82c2a5SDouglas Gregor ParsedModuleId.push_back(std::make_pair(Tok.getString(), 10272b82c2a5SDouglas Gregor Tok.getLocation())); 10282b82c2a5SDouglas Gregor consumeToken(); 10292b82c2a5SDouglas Gregor 10302b82c2a5SDouglas Gregor if (Tok.is(MMToken::Period)) { 10312b82c2a5SDouglas Gregor consumeToken(); 10322b82c2a5SDouglas Gregor continue; 10332b82c2a5SDouglas Gregor } 10342b82c2a5SDouglas Gregor 10352b82c2a5SDouglas Gregor break; 10362b82c2a5SDouglas Gregor } 10372b82c2a5SDouglas Gregor 10382b82c2a5SDouglas Gregor if(Tok.is(MMToken::Star)) { 10392b82c2a5SDouglas Gregor Wildcard = true; 1040f5eedd05SDouglas Gregor consumeToken(); 10412b82c2a5SDouglas Gregor break; 10422b82c2a5SDouglas Gregor } 10432b82c2a5SDouglas Gregor 10442b82c2a5SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id); 10452b82c2a5SDouglas Gregor HadError = true; 10462b82c2a5SDouglas Gregor return; 10472b82c2a5SDouglas Gregor } while (true); 10482b82c2a5SDouglas Gregor 10492b82c2a5SDouglas Gregor Module::UnresolvedExportDecl Unresolved = { 10502b82c2a5SDouglas Gregor ExportLoc, ParsedModuleId, Wildcard 10512b82c2a5SDouglas Gregor }; 10522b82c2a5SDouglas Gregor ActiveModule->UnresolvedExports.push_back(Unresolved); 10532b82c2a5SDouglas Gregor } 10542b82c2a5SDouglas Gregor 105573441091SDouglas Gregor void ModuleMapParser::parseInferredSubmoduleDecl(bool Explicit) { 105673441091SDouglas Gregor assert(Tok.is(MMToken::Star)); 105773441091SDouglas Gregor SourceLocation StarLoc = consumeToken(); 105873441091SDouglas Gregor bool Failed = false; 105973441091SDouglas Gregor 106073441091SDouglas Gregor // Inferred modules must be submodules. 106173441091SDouglas Gregor if (!ActiveModule) { 106273441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_top_level_inferred_submodule); 106373441091SDouglas Gregor Failed = true; 106473441091SDouglas Gregor } 106573441091SDouglas Gregor 106673441091SDouglas Gregor // Inferred modules must have umbrella headers. 1067dd005f69SDouglas Gregor if (!Failed && !ActiveModule->UmbrellaHeader) { 106873441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_no_umbrella); 106973441091SDouglas Gregor Failed = true; 107073441091SDouglas Gregor } 107173441091SDouglas Gregor 107273441091SDouglas Gregor // Check for redefinition of an inferred module. 1073dd005f69SDouglas Gregor if (!Failed && ActiveModule->InferSubmodules) { 107473441091SDouglas Gregor Diags.Report(StarLoc, diag::err_mmap_inferred_redef); 1075dd005f69SDouglas Gregor if (ActiveModule->InferredSubmoduleLoc.isValid()) 1076dd005f69SDouglas Gregor Diags.Report(ActiveModule->InferredSubmoduleLoc, 107773441091SDouglas Gregor diag::note_mmap_prev_definition); 107873441091SDouglas Gregor Failed = true; 107973441091SDouglas Gregor } 108073441091SDouglas Gregor 108173441091SDouglas Gregor // If there were any problems with this inferred submodule, skip its body. 108273441091SDouglas Gregor if (Failed) { 108373441091SDouglas Gregor if (Tok.is(MMToken::LBrace)) { 108473441091SDouglas Gregor consumeToken(); 108573441091SDouglas Gregor skipUntil(MMToken::RBrace); 108673441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 108773441091SDouglas Gregor consumeToken(); 108873441091SDouglas Gregor } 108973441091SDouglas Gregor HadError = true; 109073441091SDouglas Gregor return; 109173441091SDouglas Gregor } 109273441091SDouglas Gregor 109373441091SDouglas Gregor // Note that we have an inferred submodule. 1094dd005f69SDouglas Gregor ActiveModule->InferSubmodules = true; 1095dd005f69SDouglas Gregor ActiveModule->InferredSubmoduleLoc = StarLoc; 1096dd005f69SDouglas Gregor ActiveModule->InferExplicitSubmodules = Explicit; 109773441091SDouglas Gregor 109873441091SDouglas Gregor // Parse the opening brace. 109973441091SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 110073441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace_wildcard); 110173441091SDouglas Gregor HadError = true; 110273441091SDouglas Gregor return; 110373441091SDouglas Gregor } 110473441091SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 110573441091SDouglas Gregor 110673441091SDouglas Gregor // Parse the body of the inferred submodule. 110773441091SDouglas Gregor bool Done = false; 110873441091SDouglas Gregor do { 110973441091SDouglas Gregor switch (Tok.Kind) { 111073441091SDouglas Gregor case MMToken::EndOfFile: 111173441091SDouglas Gregor case MMToken::RBrace: 111273441091SDouglas Gregor Done = true; 111373441091SDouglas Gregor break; 111473441091SDouglas Gregor 111573441091SDouglas Gregor case MMToken::ExportKeyword: { 111673441091SDouglas Gregor consumeToken(); 111773441091SDouglas Gregor if (Tok.is(MMToken::Star)) 1118dd005f69SDouglas Gregor ActiveModule->InferExportWildcard = true; 111973441091SDouglas Gregor else 112073441091SDouglas Gregor Diags.Report(Tok.getLocation(), 112173441091SDouglas Gregor diag::err_mmap_expected_export_wildcard); 112273441091SDouglas Gregor consumeToken(); 112373441091SDouglas Gregor break; 112473441091SDouglas Gregor } 112573441091SDouglas Gregor 112673441091SDouglas Gregor case MMToken::ExplicitKeyword: 112773441091SDouglas Gregor case MMToken::ModuleKeyword: 112873441091SDouglas Gregor case MMToken::HeaderKeyword: 112973441091SDouglas Gregor case MMToken::UmbrellaKeyword: 113073441091SDouglas Gregor default: 113173441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_wildcard_member); 113273441091SDouglas Gregor consumeToken(); 113373441091SDouglas Gregor break; 113473441091SDouglas Gregor } 113573441091SDouglas Gregor } while (!Done); 113673441091SDouglas Gregor 113773441091SDouglas Gregor if (Tok.is(MMToken::RBrace)) 113873441091SDouglas Gregor consumeToken(); 113973441091SDouglas Gregor else { 114073441091SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 114173441091SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 114273441091SDouglas Gregor HadError = true; 114373441091SDouglas Gregor } 114473441091SDouglas Gregor } 114573441091SDouglas Gregor 1146718292f2SDouglas Gregor /// \brief Parse a module map file. 1147718292f2SDouglas Gregor /// 1148718292f2SDouglas Gregor /// module-map-file: 1149718292f2SDouglas Gregor /// module-declaration* 1150718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 1151718292f2SDouglas Gregor do { 1152718292f2SDouglas Gregor switch (Tok.Kind) { 1153718292f2SDouglas Gregor case MMToken::EndOfFile: 1154718292f2SDouglas Gregor return HadError; 1155718292f2SDouglas Gregor 1156e7ab3669SDouglas Gregor case MMToken::ExplicitKeyword: 1157718292f2SDouglas Gregor case MMToken::ModuleKeyword: 1158755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 1159718292f2SDouglas Gregor parseModuleDecl(); 1160718292f2SDouglas Gregor break; 1161718292f2SDouglas Gregor 11622b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 1163718292f2SDouglas Gregor case MMToken::HeaderKeyword: 1164718292f2SDouglas Gregor case MMToken::Identifier: 1165718292f2SDouglas Gregor case MMToken::LBrace: 11662b82c2a5SDouglas Gregor case MMToken::Period: 1167718292f2SDouglas Gregor case MMToken::RBrace: 11682b82c2a5SDouglas Gregor case MMToken::Star: 1169718292f2SDouglas Gregor case MMToken::StringLiteral: 1170718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 1171718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 1172718292f2SDouglas Gregor HadError = true; 1173718292f2SDouglas Gregor consumeToken(); 1174718292f2SDouglas Gregor break; 1175718292f2SDouglas Gregor } 1176718292f2SDouglas Gregor } while (true); 1177718292f2SDouglas Gregor 1178718292f2SDouglas Gregor return HadError; 1179718292f2SDouglas Gregor } 1180718292f2SDouglas Gregor 1181718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) { 1182718292f2SDouglas Gregor FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User); 1183718292f2SDouglas Gregor const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID); 1184718292f2SDouglas Gregor if (!Buffer) 1185718292f2SDouglas Gregor return true; 1186718292f2SDouglas Gregor 1187718292f2SDouglas Gregor // Parse this module map file. 1188718292f2SDouglas Gregor Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts); 1189718292f2SDouglas Gregor Diags->getClient()->BeginSourceFile(LangOpts); 11905257fc63SDouglas Gregor ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir()); 1191718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 1192718292f2SDouglas Gregor Diags->getClient()->EndSourceFile(); 1193718292f2SDouglas Gregor 1194718292f2SDouglas Gregor return Result; 1195718292f2SDouglas Gregor } 1196