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" 23718292f2SDouglas Gregor #include "llvm/Support/Host.h" 245257fc63SDouglas Gregor #include "llvm/Support/PathV2.h" 25718292f2SDouglas Gregor #include "llvm/Support/raw_ostream.h" 26718292f2SDouglas Gregor #include "llvm/ADT/StringRef.h" 27718292f2SDouglas Gregor #include "llvm/ADT/StringSwitch.h" 28718292f2SDouglas Gregor using namespace clang; 29718292f2SDouglas Gregor 302b82c2a5SDouglas Gregor Module::ExportDecl 312b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod, 322b82c2a5SDouglas Gregor const Module::UnresolvedExportDecl &Unresolved, 332b82c2a5SDouglas Gregor bool Complain) { 34f5eedd05SDouglas Gregor // We may have just a wildcard. 35f5eedd05SDouglas Gregor if (Unresolved.Id.empty()) { 36f5eedd05SDouglas Gregor assert(Unresolved.Wildcard && "Invalid unresolved export"); 37f5eedd05SDouglas Gregor return Module::ExportDecl(0, true); 38f5eedd05SDouglas Gregor } 39f5eedd05SDouglas Gregor 402b82c2a5SDouglas Gregor // Find the starting module. 412b82c2a5SDouglas Gregor Module *Context = lookupModuleUnqualified(Unresolved.Id[0].first, Mod); 422b82c2a5SDouglas Gregor if (!Context) { 432b82c2a5SDouglas Gregor if (Complain) 442b82c2a5SDouglas Gregor Diags->Report(Unresolved.Id[0].second, 452b82c2a5SDouglas Gregor diag::err_mmap_missing_module_unqualified) 462b82c2a5SDouglas Gregor << Unresolved.Id[0].first << Mod->getFullModuleName(); 472b82c2a5SDouglas Gregor 482b82c2a5SDouglas Gregor return Module::ExportDecl(); 492b82c2a5SDouglas Gregor } 502b82c2a5SDouglas Gregor 512b82c2a5SDouglas Gregor // Dig into the module path. 522b82c2a5SDouglas Gregor for (unsigned I = 1, N = Unresolved.Id.size(); I != N; ++I) { 532b82c2a5SDouglas Gregor Module *Sub = lookupModuleQualified(Unresolved.Id[I].first, 542b82c2a5SDouglas Gregor Context); 552b82c2a5SDouglas Gregor if (!Sub) { 562b82c2a5SDouglas Gregor if (Complain) 572b82c2a5SDouglas Gregor Diags->Report(Unresolved.Id[I].second, 582b82c2a5SDouglas Gregor diag::err_mmap_missing_module_qualified) 592b82c2a5SDouglas Gregor << Unresolved.Id[I].first << Context->getFullModuleName() 602b82c2a5SDouglas Gregor << SourceRange(Unresolved.Id[0].second, Unresolved.Id[I-1].second); 612b82c2a5SDouglas Gregor 622b82c2a5SDouglas Gregor return Module::ExportDecl(); 632b82c2a5SDouglas Gregor } 642b82c2a5SDouglas Gregor 652b82c2a5SDouglas Gregor Context = Sub; 662b82c2a5SDouglas Gregor } 672b82c2a5SDouglas Gregor 682b82c2a5SDouglas Gregor return Module::ExportDecl(Context, Unresolved.Wildcard); 692b82c2a5SDouglas Gregor } 702b82c2a5SDouglas Gregor 71718292f2SDouglas Gregor ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) { 72718292f2SDouglas Gregor llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs); 73718292f2SDouglas Gregor Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>( 74718292f2SDouglas Gregor new DiagnosticsEngine(DiagIDs)); 75718292f2SDouglas Gregor Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true); 76718292f2SDouglas Gregor SourceMgr = new SourceManager(*Diags, FileMgr); 77718292f2SDouglas Gregor } 78718292f2SDouglas Gregor 79718292f2SDouglas Gregor ModuleMap::~ModuleMap() { 805acdf59eSDouglas Gregor for (llvm::StringMap<Module *>::iterator I = Modules.begin(), 815acdf59eSDouglas Gregor IEnd = Modules.end(); 825acdf59eSDouglas Gregor I != IEnd; ++I) { 835acdf59eSDouglas Gregor delete I->getValue(); 845acdf59eSDouglas Gregor } 855acdf59eSDouglas Gregor 86718292f2SDouglas Gregor delete SourceMgr; 87718292f2SDouglas Gregor } 88718292f2SDouglas Gregor 89de3ef502SDouglas Gregor Module *ModuleMap::findModuleForHeader(const FileEntry *File) { 90ab0c8a84SDouglas Gregor llvm::DenseMap<const FileEntry *, Module *>::iterator Known 91ab0c8a84SDouglas Gregor = Headers.find(File); 92ab0c8a84SDouglas Gregor if (Known != Headers.end()) 93ab0c8a84SDouglas Gregor return Known->second; 94ab0c8a84SDouglas Gregor 95b65dbfffSDouglas Gregor const DirectoryEntry *Dir = File->getDir(); 96b65dbfffSDouglas Gregor llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir 97b65dbfffSDouglas Gregor = UmbrellaDirs.find(Dir); 98b65dbfffSDouglas Gregor if (KnownDir != UmbrellaDirs.end()) 99b65dbfffSDouglas Gregor return KnownDir->second; 100b65dbfffSDouglas Gregor 101b65dbfffSDouglas Gregor // Walk up the directory hierarchy looking for umbrella headers. 102b65dbfffSDouglas Gregor llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs; 103b65dbfffSDouglas Gregor StringRef DirName = Dir->getName(); 104b65dbfffSDouglas Gregor do { 105b65dbfffSDouglas Gregor // Retrieve our parent path. 106b65dbfffSDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 107b65dbfffSDouglas Gregor if (DirName.empty()) 108b65dbfffSDouglas Gregor break; 109b65dbfffSDouglas Gregor 110b65dbfffSDouglas Gregor // Resolve the parent path to a directory entry. 111b65dbfffSDouglas Gregor Dir = SourceMgr->getFileManager().getDirectory(DirName); 112b65dbfffSDouglas Gregor if (!Dir) 113b65dbfffSDouglas Gregor break; 114b65dbfffSDouglas Gregor 115b65dbfffSDouglas Gregor KnownDir = UmbrellaDirs.find(Dir); 116b65dbfffSDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 117b65dbfffSDouglas Gregor Module *Result = KnownDir->second; 118b65dbfffSDouglas Gregor 119b65dbfffSDouglas Gregor // Record each of the directories we stepped through as being part of 120b65dbfffSDouglas Gregor // the module we found, since the umbrella header covers them all. 121b65dbfffSDouglas Gregor for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I) 122b65dbfffSDouglas Gregor UmbrellaDirs[SkippedDirs[I]] = Result; 123b65dbfffSDouglas Gregor 124b65dbfffSDouglas Gregor return Result; 125b65dbfffSDouglas Gregor } 126b65dbfffSDouglas Gregor 127b65dbfffSDouglas Gregor SkippedDirs.push_back(Dir); 128b65dbfffSDouglas Gregor } while (true); 129b65dbfffSDouglas Gregor 130ab0c8a84SDouglas Gregor return 0; 131ab0c8a84SDouglas Gregor } 132ab0c8a84SDouglas Gregor 133de3ef502SDouglas Gregor Module *ModuleMap::findModule(StringRef Name) { 13488bdfb0eSDouglas Gregor llvm::StringMap<Module *>::iterator Known = Modules.find(Name); 13588bdfb0eSDouglas Gregor if (Known != Modules.end()) 13688bdfb0eSDouglas Gregor return Known->getValue(); 13788bdfb0eSDouglas Gregor 13888bdfb0eSDouglas Gregor return 0; 13988bdfb0eSDouglas Gregor } 14088bdfb0eSDouglas Gregor 1412b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) { 1422b82c2a5SDouglas Gregor for(; Context; Context = Context->Parent) { 1432b82c2a5SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Context)) 1442b82c2a5SDouglas Gregor return Sub; 1452b82c2a5SDouglas Gregor } 1462b82c2a5SDouglas Gregor 1472b82c2a5SDouglas Gregor return findModule(Name); 1482b82c2a5SDouglas Gregor } 1492b82c2a5SDouglas Gregor 1502b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) { 1512b82c2a5SDouglas Gregor if (!Context) 1522b82c2a5SDouglas Gregor return findModule(Name); 1532b82c2a5SDouglas Gregor 1542b82c2a5SDouglas Gregor llvm::StringMap<Module *>::iterator Sub = Context->SubModules.find(Name); 1552b82c2a5SDouglas Gregor if (Sub != Context->SubModules.end()) 1562b82c2a5SDouglas Gregor return Sub->getValue(); 1572b82c2a5SDouglas Gregor 1582b82c2a5SDouglas Gregor return 0; 1592b82c2a5SDouglas Gregor } 1602b82c2a5SDouglas Gregor 161de3ef502SDouglas Gregor std::pair<Module *, bool> 16269021974SDouglas Gregor ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework, 16369021974SDouglas Gregor bool IsExplicit) { 16469021974SDouglas Gregor // Try to find an existing module with this name. 16569021974SDouglas Gregor if (Module *Found = Parent? Parent->SubModules[Name] : Modules[Name]) 16669021974SDouglas Gregor return std::make_pair(Found, false); 16769021974SDouglas Gregor 16869021974SDouglas Gregor // Create a new module with this name. 16969021974SDouglas Gregor Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, 17069021974SDouglas Gregor IsExplicit); 17169021974SDouglas Gregor if (Parent) 17269021974SDouglas Gregor Parent->SubModules[Name] = Result; 17369021974SDouglas Gregor else 17469021974SDouglas Gregor Modules[Name] = Result; 17569021974SDouglas Gregor return std::make_pair(Result, true); 17669021974SDouglas Gregor } 17769021974SDouglas Gregor 178de3ef502SDouglas Gregor Module * 17956c64013SDouglas Gregor ModuleMap::inferFrameworkModule(StringRef ModuleName, 18056c64013SDouglas Gregor const DirectoryEntry *FrameworkDir) { 18156c64013SDouglas Gregor // Check whether we've already found this module. 18256c64013SDouglas Gregor if (Module *Module = findModule(ModuleName)) 18356c64013SDouglas Gregor return Module; 18456c64013SDouglas Gregor 18556c64013SDouglas Gregor // Look for an umbrella header. 18656c64013SDouglas Gregor llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 18756c64013SDouglas Gregor llvm::sys::path::append(UmbrellaName, "Headers"); 18856c64013SDouglas Gregor llvm::sys::path::append(UmbrellaName, ModuleName + ".h"); 18956c64013SDouglas Gregor const FileEntry *UmbrellaHeader 19056c64013SDouglas Gregor = SourceMgr->getFileManager().getFile(UmbrellaName); 19156c64013SDouglas Gregor 19256c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the 19356c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good 19456c64013SDouglas Gregor // idea. 19556c64013SDouglas Gregor if (!UmbrellaHeader) 19656c64013SDouglas Gregor return 0; 19756c64013SDouglas Gregor 198755b2055SDouglas Gregor Module *Result = new Module(ModuleName, SourceLocation(), 199755b2055SDouglas Gregor /*IsFramework=*/true); 200*d8bd7537SDouglas Gregor // umbrella "umbrella-header-name" 20156c64013SDouglas Gregor Result->UmbrellaHeader = UmbrellaHeader; 20256c64013SDouglas Gregor Headers[UmbrellaHeader] = Result; 20356c64013SDouglas Gregor UmbrellaDirs[FrameworkDir] = Result; 204*d8bd7537SDouglas Gregor 205*d8bd7537SDouglas Gregor // export * 206*d8bd7537SDouglas Gregor Result->Exports.push_back(Module::ExportDecl(0, true)); 207*d8bd7537SDouglas Gregor 20856c64013SDouglas Gregor Modules[ModuleName] = Result; 20956c64013SDouglas Gregor return Result; 21056c64013SDouglas Gregor } 21156c64013SDouglas Gregor 212514b636aSDouglas Gregor const FileEntry * 213de3ef502SDouglas Gregor ModuleMap::getContainingModuleMapFile(Module *Module) { 214514b636aSDouglas Gregor if (Module->DefinitionLoc.isInvalid() || !SourceMgr) 215514b636aSDouglas Gregor return 0; 216514b636aSDouglas Gregor 217514b636aSDouglas Gregor return SourceMgr->getFileEntryForID( 218514b636aSDouglas Gregor SourceMgr->getFileID(Module->DefinitionLoc)); 219514b636aSDouglas Gregor } 220514b636aSDouglas Gregor 221718292f2SDouglas Gregor void ModuleMap::dump() { 222718292f2SDouglas Gregor llvm::errs() << "Modules:"; 223718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 224718292f2SDouglas Gregor MEnd = Modules.end(); 225718292f2SDouglas Gregor M != MEnd; ++M) 226d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 227718292f2SDouglas Gregor 228718292f2SDouglas Gregor llvm::errs() << "Headers:"; 229718292f2SDouglas Gregor for (llvm::DenseMap<const FileEntry *, Module *>::iterator 230718292f2SDouglas Gregor H = Headers.begin(), 231718292f2SDouglas Gregor HEnd = Headers.end(); 232718292f2SDouglas Gregor H != HEnd; ++H) { 233718292f2SDouglas Gregor llvm::errs() << " \"" << H->first->getName() << "\" -> " 234718292f2SDouglas Gregor << H->second->getFullModuleName() << "\n"; 235718292f2SDouglas Gregor } 236718292f2SDouglas Gregor } 237718292f2SDouglas Gregor 2382b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) { 2392b82c2a5SDouglas Gregor bool HadError = false; 2402b82c2a5SDouglas Gregor for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) { 2412b82c2a5SDouglas Gregor Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I], 2422b82c2a5SDouglas Gregor Complain); 243f5eedd05SDouglas Gregor if (Export.getPointer() || Export.getInt()) 2442b82c2a5SDouglas Gregor Mod->Exports.push_back(Export); 2452b82c2a5SDouglas Gregor else 2462b82c2a5SDouglas Gregor HadError = true; 2472b82c2a5SDouglas Gregor } 2482b82c2a5SDouglas Gregor Mod->UnresolvedExports.clear(); 2492b82c2a5SDouglas Gregor return HadError; 2502b82c2a5SDouglas Gregor } 2512b82c2a5SDouglas Gregor 2520093b3c7SDouglas Gregor Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) { 2530093b3c7SDouglas Gregor if (Loc.isInvalid()) 2540093b3c7SDouglas Gregor return 0; 2550093b3c7SDouglas Gregor 2560093b3c7SDouglas Gregor // Use the expansion location to determine which module we're in. 2570093b3c7SDouglas Gregor FullSourceLoc ExpansionLoc = Loc.getExpansionLoc(); 2580093b3c7SDouglas Gregor if (!ExpansionLoc.isFileID()) 2590093b3c7SDouglas Gregor return 0; 2600093b3c7SDouglas Gregor 2610093b3c7SDouglas Gregor 2620093b3c7SDouglas Gregor const SourceManager &SrcMgr = Loc.getManager(); 2630093b3c7SDouglas Gregor FileID ExpansionFileID = ExpansionLoc.getFileID(); 2640093b3c7SDouglas Gregor const FileEntry *ExpansionFile = SrcMgr.getFileEntryForID(ExpansionFileID); 2650093b3c7SDouglas Gregor if (!ExpansionFile) 2660093b3c7SDouglas Gregor return 0; 2670093b3c7SDouglas Gregor 2680093b3c7SDouglas Gregor // Find the module that owns this header. 2690093b3c7SDouglas Gregor return findModuleForHeader(ExpansionFile); 2700093b3c7SDouglas Gregor } 2710093b3c7SDouglas Gregor 272718292f2SDouglas Gregor //----------------------------------------------------------------------------// 273718292f2SDouglas Gregor // Module map file parser 274718292f2SDouglas Gregor //----------------------------------------------------------------------------// 275718292f2SDouglas Gregor 276718292f2SDouglas Gregor namespace clang { 277718292f2SDouglas Gregor /// \brief A token in a module map file. 278718292f2SDouglas Gregor struct MMToken { 279718292f2SDouglas Gregor enum TokenKind { 280718292f2SDouglas Gregor EndOfFile, 281718292f2SDouglas Gregor HeaderKeyword, 282718292f2SDouglas Gregor Identifier, 283718292f2SDouglas Gregor ExplicitKeyword, 2842b82c2a5SDouglas Gregor ExportKeyword, 285755b2055SDouglas Gregor FrameworkKeyword, 286718292f2SDouglas Gregor ModuleKeyword, 2872b82c2a5SDouglas Gregor Period, 288718292f2SDouglas Gregor UmbrellaKeyword, 2892b82c2a5SDouglas Gregor Star, 290718292f2SDouglas Gregor StringLiteral, 291718292f2SDouglas Gregor LBrace, 292718292f2SDouglas Gregor RBrace 293718292f2SDouglas Gregor } Kind; 294718292f2SDouglas Gregor 295718292f2SDouglas Gregor unsigned Location; 296718292f2SDouglas Gregor unsigned StringLength; 297718292f2SDouglas Gregor const char *StringData; 298718292f2SDouglas Gregor 299718292f2SDouglas Gregor void clear() { 300718292f2SDouglas Gregor Kind = EndOfFile; 301718292f2SDouglas Gregor Location = 0; 302718292f2SDouglas Gregor StringLength = 0; 303718292f2SDouglas Gregor StringData = 0; 304718292f2SDouglas Gregor } 305718292f2SDouglas Gregor 306718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 307718292f2SDouglas Gregor 308718292f2SDouglas Gregor SourceLocation getLocation() const { 309718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 310718292f2SDouglas Gregor } 311718292f2SDouglas Gregor 312718292f2SDouglas Gregor StringRef getString() const { 313718292f2SDouglas Gregor return StringRef(StringData, StringLength); 314718292f2SDouglas Gregor } 315718292f2SDouglas Gregor }; 316718292f2SDouglas Gregor 317718292f2SDouglas Gregor class ModuleMapParser { 318718292f2SDouglas Gregor Lexer &L; 319718292f2SDouglas Gregor SourceManager &SourceMgr; 320718292f2SDouglas Gregor DiagnosticsEngine &Diags; 321718292f2SDouglas Gregor ModuleMap ⤅ 322718292f2SDouglas Gregor 3235257fc63SDouglas Gregor /// \brief The directory that this module map resides in. 3245257fc63SDouglas Gregor const DirectoryEntry *Directory; 3255257fc63SDouglas Gregor 326718292f2SDouglas Gregor /// \brief Whether an error occurred. 327718292f2SDouglas Gregor bool HadError; 328718292f2SDouglas Gregor 329718292f2SDouglas Gregor /// \brief Default target information, used only for string literal 330718292f2SDouglas Gregor /// parsing. 331718292f2SDouglas Gregor TargetInfo *Target; 332718292f2SDouglas Gregor 333718292f2SDouglas Gregor /// \brief Stores string data for the various string literals referenced 334718292f2SDouglas Gregor /// during parsing. 335718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 336718292f2SDouglas Gregor 337718292f2SDouglas Gregor /// \brief The current token. 338718292f2SDouglas Gregor MMToken Tok; 339718292f2SDouglas Gregor 340718292f2SDouglas Gregor /// \brief The active module. 341de3ef502SDouglas Gregor Module *ActiveModule; 342718292f2SDouglas Gregor 343718292f2SDouglas Gregor /// \brief Consume the current token and return its location. 344718292f2SDouglas Gregor SourceLocation consumeToken(); 345718292f2SDouglas Gregor 346718292f2SDouglas Gregor /// \brief Skip tokens until we reach the a token with the given kind 347718292f2SDouglas Gregor /// (or the end of the file). 348718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 349718292f2SDouglas Gregor 350718292f2SDouglas Gregor void parseModuleDecl(); 351718292f2SDouglas Gregor void parseUmbrellaDecl(); 352718292f2SDouglas Gregor void parseHeaderDecl(); 3532b82c2a5SDouglas Gregor void parseExportDecl(); 354718292f2SDouglas Gregor 355718292f2SDouglas Gregor public: 356718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 357718292f2SDouglas Gregor DiagnosticsEngine &Diags, 3585257fc63SDouglas Gregor ModuleMap &Map, 3595257fc63SDouglas Gregor const DirectoryEntry *Directory) 3605257fc63SDouglas Gregor : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map), 3615257fc63SDouglas Gregor Directory(Directory), HadError(false), ActiveModule(0) 362718292f2SDouglas Gregor { 363718292f2SDouglas Gregor TargetOptions TargetOpts; 364718292f2SDouglas Gregor TargetOpts.Triple = llvm::sys::getDefaultTargetTriple(); 365718292f2SDouglas Gregor Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); 366718292f2SDouglas Gregor 367718292f2SDouglas Gregor Tok.clear(); 368718292f2SDouglas Gregor consumeToken(); 369718292f2SDouglas Gregor } 370718292f2SDouglas Gregor 371718292f2SDouglas Gregor bool parseModuleMapFile(); 372718292f2SDouglas Gregor }; 373718292f2SDouglas Gregor } 374718292f2SDouglas Gregor 375718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 376718292f2SDouglas Gregor retry: 377718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 378718292f2SDouglas Gregor Tok.clear(); 379718292f2SDouglas Gregor 380718292f2SDouglas Gregor Token LToken; 381718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 382718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 383718292f2SDouglas Gregor switch (LToken.getKind()) { 384718292f2SDouglas Gregor case tok::raw_identifier: 385718292f2SDouglas Gregor Tok.StringData = LToken.getRawIdentifierData(); 386718292f2SDouglas Gregor Tok.StringLength = LToken.getLength(); 387718292f2SDouglas Gregor Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString()) 388718292f2SDouglas Gregor .Case("header", MMToken::HeaderKeyword) 389718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 3902b82c2a5SDouglas Gregor .Case("export", MMToken::ExportKeyword) 391755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 392718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 393718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 394718292f2SDouglas Gregor .Default(MMToken::Identifier); 395718292f2SDouglas Gregor break; 396718292f2SDouglas Gregor 397718292f2SDouglas Gregor case tok::eof: 398718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 399718292f2SDouglas Gregor break; 400718292f2SDouglas Gregor 401718292f2SDouglas Gregor case tok::l_brace: 402718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 403718292f2SDouglas Gregor break; 404718292f2SDouglas Gregor 4052b82c2a5SDouglas Gregor case tok::period: 4062b82c2a5SDouglas Gregor Tok.Kind = MMToken::Period; 4072b82c2a5SDouglas Gregor break; 4082b82c2a5SDouglas Gregor 409718292f2SDouglas Gregor case tok::r_brace: 410718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 411718292f2SDouglas Gregor break; 412718292f2SDouglas Gregor 4132b82c2a5SDouglas Gregor case tok::star: 4142b82c2a5SDouglas Gregor Tok.Kind = MMToken::Star; 4152b82c2a5SDouglas Gregor break; 4162b82c2a5SDouglas Gregor 417718292f2SDouglas Gregor case tok::string_literal: { 418718292f2SDouglas Gregor // Parse the string literal. 419718292f2SDouglas Gregor LangOptions LangOpts; 420718292f2SDouglas Gregor StringLiteralParser StringLiteral(<oken, 1, SourceMgr, LangOpts, *Target); 421718292f2SDouglas Gregor if (StringLiteral.hadError) 422718292f2SDouglas Gregor goto retry; 423718292f2SDouglas Gregor 424718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 425718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 426718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 427718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 428718292f2SDouglas Gregor Saved[Length] = 0; 429718292f2SDouglas Gregor 430718292f2SDouglas Gregor // Form the token. 431718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 432718292f2SDouglas Gregor Tok.StringData = Saved; 433718292f2SDouglas Gregor Tok.StringLength = Length; 434718292f2SDouglas Gregor break; 435718292f2SDouglas Gregor } 436718292f2SDouglas Gregor 437718292f2SDouglas Gregor case tok::comment: 438718292f2SDouglas Gregor goto retry; 439718292f2SDouglas Gregor 440718292f2SDouglas Gregor default: 441718292f2SDouglas Gregor Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token); 442718292f2SDouglas Gregor HadError = true; 443718292f2SDouglas Gregor goto retry; 444718292f2SDouglas Gregor } 445718292f2SDouglas Gregor 446718292f2SDouglas Gregor return Result; 447718292f2SDouglas Gregor } 448718292f2SDouglas Gregor 449718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 450718292f2SDouglas Gregor unsigned braceDepth = 0; 451718292f2SDouglas Gregor do { 452718292f2SDouglas Gregor switch (Tok.Kind) { 453718292f2SDouglas Gregor case MMToken::EndOfFile: 454718292f2SDouglas Gregor return; 455718292f2SDouglas Gregor 456718292f2SDouglas Gregor case MMToken::LBrace: 457718292f2SDouglas Gregor if (Tok.is(K) && braceDepth == 0) 458718292f2SDouglas Gregor return; 459718292f2SDouglas Gregor 460718292f2SDouglas Gregor ++braceDepth; 461718292f2SDouglas Gregor break; 462718292f2SDouglas Gregor 463718292f2SDouglas Gregor case MMToken::RBrace: 464718292f2SDouglas Gregor if (braceDepth > 0) 465718292f2SDouglas Gregor --braceDepth; 466718292f2SDouglas Gregor else if (Tok.is(K)) 467718292f2SDouglas Gregor return; 468718292f2SDouglas Gregor break; 469718292f2SDouglas Gregor 470718292f2SDouglas Gregor default: 471718292f2SDouglas Gregor if (braceDepth == 0 && Tok.is(K)) 472718292f2SDouglas Gregor return; 473718292f2SDouglas Gregor break; 474718292f2SDouglas Gregor } 475718292f2SDouglas Gregor 476718292f2SDouglas Gregor consumeToken(); 477718292f2SDouglas Gregor } while (true); 478718292f2SDouglas Gregor } 479718292f2SDouglas Gregor 480718292f2SDouglas Gregor /// \brief Parse a module declaration. 481718292f2SDouglas Gregor /// 482718292f2SDouglas Gregor /// module-declaration: 483755b2055SDouglas Gregor /// 'framework'[opt] 'module' identifier { module-member* } 484718292f2SDouglas Gregor /// 485718292f2SDouglas Gregor /// module-member: 486718292f2SDouglas Gregor /// umbrella-declaration 487718292f2SDouglas Gregor /// header-declaration 488718292f2SDouglas Gregor /// 'explicit'[opt] module-declaration 4892b82c2a5SDouglas Gregor /// export-declaration 490718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 491755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 492755b2055SDouglas Gregor Tok.is(MMToken::FrameworkKeyword)); 493718292f2SDouglas Gregor 494755b2055SDouglas Gregor // Parse 'framework' or 'explicit' keyword, if present. 495755b2055SDouglas Gregor bool Framework = false; 496718292f2SDouglas Gregor bool Explicit = false; 497755b2055SDouglas Gregor 498755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 499755b2055SDouglas Gregor consumeToken(); 500755b2055SDouglas Gregor Framework = true; 501755b2055SDouglas Gregor } 502755b2055SDouglas Gregor // Parse 'explicit' keyword, if present. 503755b2055SDouglas Gregor else if (Tok.is(MMToken::ExplicitKeyword)) { 504718292f2SDouglas Gregor consumeToken(); 505718292f2SDouglas Gregor Explicit = true; 506718292f2SDouglas Gregor } 507718292f2SDouglas Gregor 508718292f2SDouglas Gregor // Parse 'module' keyword. 509718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 510718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), 511718292f2SDouglas Gregor diag::err_mmap_expected_module_after_explicit); 512718292f2SDouglas Gregor consumeToken(); 513718292f2SDouglas Gregor HadError = true; 514718292f2SDouglas Gregor return; 515718292f2SDouglas Gregor } 516718292f2SDouglas Gregor consumeToken(); // 'module' keyword 517718292f2SDouglas Gregor 518718292f2SDouglas Gregor // Parse the module name. 519718292f2SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 520718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 521718292f2SDouglas Gregor HadError = true; 522718292f2SDouglas Gregor return; 523718292f2SDouglas Gregor } 524718292f2SDouglas Gregor StringRef ModuleName = Tok.getString(); 525718292f2SDouglas Gregor SourceLocation ModuleNameLoc = consumeToken(); 526718292f2SDouglas Gregor 527718292f2SDouglas Gregor // Parse the opening brace. 528718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 529718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 530718292f2SDouglas Gregor << ModuleName; 531718292f2SDouglas Gregor HadError = true; 532718292f2SDouglas Gregor return; 533718292f2SDouglas Gregor } 534718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 535718292f2SDouglas Gregor 536718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 537718292f2SDouglas Gregor llvm::StringMap<Module *> &ModuleSpace 538718292f2SDouglas Gregor = ActiveModule? ActiveModule->SubModules : Map.Modules; 539718292f2SDouglas Gregor llvm::StringMap<Module *>::iterator ExistingModule 540718292f2SDouglas Gregor = ModuleSpace.find(ModuleName); 541718292f2SDouglas Gregor if (ExistingModule != ModuleSpace.end()) { 542718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 543718292f2SDouglas Gregor << ModuleName; 544718292f2SDouglas Gregor Diags.Report(ExistingModule->getValue()->DefinitionLoc, 545718292f2SDouglas Gregor diag::note_mmap_prev_definition); 546718292f2SDouglas Gregor 547718292f2SDouglas Gregor // Skip the module definition. 548718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 549718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 550718292f2SDouglas Gregor consumeToken(); 551718292f2SDouglas Gregor 552718292f2SDouglas Gregor HadError = true; 553718292f2SDouglas Gregor return; 554718292f2SDouglas Gregor } 555718292f2SDouglas Gregor 556718292f2SDouglas Gregor // Start defining this module. 557755b2055SDouglas Gregor ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework, 558755b2055SDouglas Gregor Explicit); 559718292f2SDouglas Gregor ModuleSpace[ModuleName] = ActiveModule; 560718292f2SDouglas Gregor 561718292f2SDouglas Gregor bool Done = false; 562718292f2SDouglas Gregor do { 563718292f2SDouglas Gregor switch (Tok.Kind) { 564718292f2SDouglas Gregor case MMToken::EndOfFile: 565718292f2SDouglas Gregor case MMToken::RBrace: 566718292f2SDouglas Gregor Done = true; 567718292f2SDouglas Gregor break; 568718292f2SDouglas Gregor 569718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 570718292f2SDouglas Gregor case MMToken::ModuleKeyword: 571718292f2SDouglas Gregor parseModuleDecl(); 572718292f2SDouglas Gregor break; 573718292f2SDouglas Gregor 5742b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 5752b82c2a5SDouglas Gregor parseExportDecl(); 5762b82c2a5SDouglas Gregor break; 5772b82c2a5SDouglas Gregor 578718292f2SDouglas Gregor case MMToken::HeaderKeyword: 579718292f2SDouglas Gregor parseHeaderDecl(); 580718292f2SDouglas Gregor break; 581718292f2SDouglas Gregor 582718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 583718292f2SDouglas Gregor parseUmbrellaDecl(); 584718292f2SDouglas Gregor break; 585718292f2SDouglas Gregor 586718292f2SDouglas Gregor default: 587718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 588718292f2SDouglas Gregor consumeToken(); 589718292f2SDouglas Gregor break; 590718292f2SDouglas Gregor } 591718292f2SDouglas Gregor } while (!Done); 592718292f2SDouglas Gregor 593718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 594718292f2SDouglas Gregor consumeToken(); 595718292f2SDouglas Gregor else { 596718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 597718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 598718292f2SDouglas Gregor HadError = true; 599718292f2SDouglas Gregor } 600718292f2SDouglas Gregor 601718292f2SDouglas Gregor // We're done parsing this module. Pop back to our parent scope. 602718292f2SDouglas Gregor ActiveModule = ActiveModule->Parent; 603718292f2SDouglas Gregor } 604718292f2SDouglas Gregor 605718292f2SDouglas Gregor /// \brief Parse an umbrella header declaration. 606718292f2SDouglas Gregor /// 607718292f2SDouglas Gregor /// umbrella-declaration: 608718292f2SDouglas Gregor /// 'umbrella' string-literal 609718292f2SDouglas Gregor void ModuleMapParser::parseUmbrellaDecl() { 610718292f2SDouglas Gregor assert(Tok.is(MMToken::UmbrellaKeyword)); 611718292f2SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 612718292f2SDouglas Gregor 613718292f2SDouglas Gregor // Parse the header name. 614718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 615718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 616718292f2SDouglas Gregor << "umbrella"; 617718292f2SDouglas Gregor HadError = true; 618718292f2SDouglas Gregor return; 619718292f2SDouglas Gregor } 620718292f2SDouglas Gregor StringRef FileName = Tok.getString(); 621718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 622718292f2SDouglas Gregor 6235257fc63SDouglas Gregor // Check whether we already have an umbrella header. 6245257fc63SDouglas Gregor if (ActiveModule->UmbrellaHeader) { 6255257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict) 6265257fc63SDouglas Gregor << ActiveModule->getFullModuleName() 6275257fc63SDouglas Gregor << ActiveModule->UmbrellaHeader->getName(); 6285257fc63SDouglas Gregor HadError = true; 6295257fc63SDouglas Gregor return; 6305257fc63SDouglas Gregor } 6315257fc63SDouglas Gregor 6325257fc63SDouglas Gregor // Only top-level modules can have umbrella headers. 6335257fc63SDouglas Gregor if (ActiveModule->Parent) { 6345257fc63SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule) 6355257fc63SDouglas Gregor << ActiveModule->getFullModuleName(); 6365257fc63SDouglas Gregor HadError = true; 6375257fc63SDouglas Gregor return; 6385257fc63SDouglas Gregor } 6395257fc63SDouglas Gregor 6405257fc63SDouglas Gregor // Look for this file. 6415257fc63SDouglas Gregor llvm::SmallString<128> PathName; 642f545f67dSDouglas Gregor const FileEntry *File = 0; 643f545f67dSDouglas Gregor 644f545f67dSDouglas Gregor if (llvm::sys::path::is_absolute(FileName)) { 645f545f67dSDouglas Gregor PathName = FileName; 646f545f67dSDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 647f545f67dSDouglas Gregor } else { 648f545f67dSDouglas Gregor // Search for the header file within the search directory. 6495257fc63SDouglas Gregor PathName += Directory->getName(); 650755b2055SDouglas Gregor unsigned PathLength = PathName.size(); 651755b2055SDouglas Gregor if (ActiveModule->isPartOfFramework()) { 652755b2055SDouglas Gregor // Check whether this file is in the public headers. 653755b2055SDouglas Gregor llvm::sys::path::append(PathName, "Headers"); 6545257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 655755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 656755b2055SDouglas Gregor 657755b2055SDouglas Gregor if (!File) { 658755b2055SDouglas Gregor // Check whether this file is in the private headers. 659755b2055SDouglas Gregor PathName.resize(PathLength); 660755b2055SDouglas Gregor llvm::sys::path::append(PathName, "PrivateHeaders"); 661755b2055SDouglas Gregor llvm::sys::path::append(PathName, FileName); 662755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 663755b2055SDouglas Gregor } 664755b2055SDouglas Gregor 665755b2055SDouglas Gregor // FIXME: Deal with subframeworks. 666755b2055SDouglas Gregor } else { 667755b2055SDouglas Gregor // Lookup for normal headers. 668755b2055SDouglas Gregor llvm::sys::path::append(PathName, FileName); 669755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 670755b2055SDouglas Gregor } 671f545f67dSDouglas Gregor } 6725257fc63SDouglas Gregor 6735257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 6745257fc63SDouglas Gregor // Come up with a lazy way to do this. 675755b2055SDouglas Gregor if (File) { 6765257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 6775257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 6785257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 6795257fc63SDouglas Gregor HadError = true; 680b65dbfffSDouglas Gregor } else if ((OwningModule = Map.UmbrellaDirs[Directory])) { 681b65dbfffSDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 682b65dbfffSDouglas Gregor << OwningModule->getFullModuleName(); 683b65dbfffSDouglas Gregor HadError = true; 6845257fc63SDouglas Gregor } else { 6855257fc63SDouglas Gregor // Record this umbrella header. 6865257fc63SDouglas Gregor ActiveModule->UmbrellaHeader = File; 6875257fc63SDouglas Gregor Map.Headers[File] = ActiveModule; 688b65dbfffSDouglas Gregor Map.UmbrellaDirs[Directory] = ActiveModule; 6895257fc63SDouglas Gregor } 6905257fc63SDouglas Gregor } else { 6915257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 6925257fc63SDouglas Gregor << true << FileName; 6935257fc63SDouglas Gregor HadError = true; 6945257fc63SDouglas Gregor } 695718292f2SDouglas Gregor } 696718292f2SDouglas Gregor 697718292f2SDouglas Gregor /// \brief Parse a header declaration. 698718292f2SDouglas Gregor /// 699718292f2SDouglas Gregor /// header-declaration: 700718292f2SDouglas Gregor /// 'header' string-literal 701718292f2SDouglas Gregor void ModuleMapParser::parseHeaderDecl() { 702718292f2SDouglas Gregor assert(Tok.is(MMToken::HeaderKeyword)); 7031871ed3dSBenjamin Kramer consumeToken(); 704718292f2SDouglas Gregor 705718292f2SDouglas Gregor // Parse the header name. 706718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 707718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 708718292f2SDouglas Gregor << "header"; 709718292f2SDouglas Gregor HadError = true; 710718292f2SDouglas Gregor return; 711718292f2SDouglas Gregor } 712718292f2SDouglas Gregor StringRef FileName = Tok.getString(); 713718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 714718292f2SDouglas Gregor 7155257fc63SDouglas Gregor // Look for this file. 7165257fc63SDouglas Gregor llvm::SmallString<128> PathName; 717f545f67dSDouglas Gregor if (llvm::sys::path::is_relative(FileName)) { 718f545f67dSDouglas Gregor // FIXME: Change this search to also look for private headers! 7195257fc63SDouglas Gregor PathName += Directory->getName(); 720755b2055SDouglas Gregor 721755b2055SDouglas Gregor if (ActiveModule->isPartOfFramework()) 722755b2055SDouglas Gregor llvm::sys::path::append(PathName, "Headers"); 723f545f67dSDouglas Gregor } 724755b2055SDouglas Gregor 7255257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 7265257fc63SDouglas Gregor 7275257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 7285257fc63SDouglas Gregor // Come up with a lazy way to do this. 7295257fc63SDouglas Gregor if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) { 7305257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 7315257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 7325257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 7335257fc63SDouglas Gregor HadError = true; 7345257fc63SDouglas Gregor } else { 7355257fc63SDouglas Gregor // Record this file. 7365257fc63SDouglas Gregor ActiveModule->Headers.push_back(File); 7375257fc63SDouglas Gregor Map.Headers[File] = ActiveModule; 7385257fc63SDouglas Gregor } 7395257fc63SDouglas Gregor } else { 7405257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 7415257fc63SDouglas Gregor << false << FileName; 7425257fc63SDouglas Gregor HadError = true; 7435257fc63SDouglas Gregor } 744718292f2SDouglas Gregor } 745718292f2SDouglas Gregor 7462b82c2a5SDouglas Gregor /// \brief Parse a module export declaration. 7472b82c2a5SDouglas Gregor /// 7482b82c2a5SDouglas Gregor /// export-declaration: 7492b82c2a5SDouglas Gregor /// 'export' wildcard-module-id 7502b82c2a5SDouglas Gregor /// 7512b82c2a5SDouglas Gregor /// wildcard-module-id: 7522b82c2a5SDouglas Gregor /// identifier 7532b82c2a5SDouglas Gregor /// '*' 7542b82c2a5SDouglas Gregor /// identifier '.' wildcard-module-id 7552b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() { 7562b82c2a5SDouglas Gregor assert(Tok.is(MMToken::ExportKeyword)); 7572b82c2a5SDouglas Gregor SourceLocation ExportLoc = consumeToken(); 7582b82c2a5SDouglas Gregor 7592b82c2a5SDouglas Gregor // Parse the module-id with an optional wildcard at the end. 7602b82c2a5SDouglas Gregor ModuleId ParsedModuleId; 7612b82c2a5SDouglas Gregor bool Wildcard = false; 7622b82c2a5SDouglas Gregor do { 7632b82c2a5SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 7642b82c2a5SDouglas Gregor ParsedModuleId.push_back(std::make_pair(Tok.getString(), 7652b82c2a5SDouglas Gregor Tok.getLocation())); 7662b82c2a5SDouglas Gregor consumeToken(); 7672b82c2a5SDouglas Gregor 7682b82c2a5SDouglas Gregor if (Tok.is(MMToken::Period)) { 7692b82c2a5SDouglas Gregor consumeToken(); 7702b82c2a5SDouglas Gregor continue; 7712b82c2a5SDouglas Gregor } 7722b82c2a5SDouglas Gregor 7732b82c2a5SDouglas Gregor break; 7742b82c2a5SDouglas Gregor } 7752b82c2a5SDouglas Gregor 7762b82c2a5SDouglas Gregor if(Tok.is(MMToken::Star)) { 7772b82c2a5SDouglas Gregor Wildcard = true; 778f5eedd05SDouglas Gregor consumeToken(); 7792b82c2a5SDouglas Gregor break; 7802b82c2a5SDouglas Gregor } 7812b82c2a5SDouglas Gregor 7822b82c2a5SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id); 7832b82c2a5SDouglas Gregor HadError = true; 7842b82c2a5SDouglas Gregor return; 7852b82c2a5SDouglas Gregor } while (true); 7862b82c2a5SDouglas Gregor 7872b82c2a5SDouglas Gregor Module::UnresolvedExportDecl Unresolved = { 7882b82c2a5SDouglas Gregor ExportLoc, ParsedModuleId, Wildcard 7892b82c2a5SDouglas Gregor }; 7902b82c2a5SDouglas Gregor ActiveModule->UnresolvedExports.push_back(Unresolved); 7912b82c2a5SDouglas Gregor } 7922b82c2a5SDouglas Gregor 793718292f2SDouglas Gregor /// \brief Parse a module map file. 794718292f2SDouglas Gregor /// 795718292f2SDouglas Gregor /// module-map-file: 796718292f2SDouglas Gregor /// module-declaration* 797718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 798718292f2SDouglas Gregor do { 799718292f2SDouglas Gregor switch (Tok.Kind) { 800718292f2SDouglas Gregor case MMToken::EndOfFile: 801718292f2SDouglas Gregor return HadError; 802718292f2SDouglas Gregor 803718292f2SDouglas Gregor case MMToken::ModuleKeyword: 804755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 805718292f2SDouglas Gregor parseModuleDecl(); 806718292f2SDouglas Gregor break; 807718292f2SDouglas Gregor 808718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 8092b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 810718292f2SDouglas Gregor case MMToken::HeaderKeyword: 811718292f2SDouglas Gregor case MMToken::Identifier: 812718292f2SDouglas Gregor case MMToken::LBrace: 8132b82c2a5SDouglas Gregor case MMToken::Period: 814718292f2SDouglas Gregor case MMToken::RBrace: 8152b82c2a5SDouglas Gregor case MMToken::Star: 816718292f2SDouglas Gregor case MMToken::StringLiteral: 817718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 818718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 819718292f2SDouglas Gregor HadError = true; 820718292f2SDouglas Gregor consumeToken(); 821718292f2SDouglas Gregor break; 822718292f2SDouglas Gregor } 823718292f2SDouglas Gregor } while (true); 824718292f2SDouglas Gregor 825718292f2SDouglas Gregor return HadError; 826718292f2SDouglas Gregor } 827718292f2SDouglas Gregor 828718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) { 829718292f2SDouglas Gregor FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User); 830718292f2SDouglas Gregor const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID); 831718292f2SDouglas Gregor if (!Buffer) 832718292f2SDouglas Gregor return true; 833718292f2SDouglas Gregor 834718292f2SDouglas Gregor // Parse this module map file. 835718292f2SDouglas Gregor Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts); 836718292f2SDouglas Gregor Diags->getClient()->BeginSourceFile(LangOpts); 8375257fc63SDouglas Gregor ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir()); 838718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 839718292f2SDouglas Gregor Diags->getClient()->EndSourceFile(); 840718292f2SDouglas Gregor 841718292f2SDouglas Gregor return Result; 842718292f2SDouglas Gregor } 843