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) { 34*f5eedd05SDouglas Gregor // We may have just a wildcard. 35*f5eedd05SDouglas Gregor if (Unresolved.Id.empty()) { 36*f5eedd05SDouglas Gregor assert(Unresolved.Wildcard && "Invalid unresolved export"); 37*f5eedd05SDouglas Gregor return Module::ExportDecl(0, true); 38*f5eedd05SDouglas Gregor } 39*f5eedd05SDouglas 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); 20056c64013SDouglas Gregor Result->UmbrellaHeader = UmbrellaHeader; 20156c64013SDouglas Gregor Headers[UmbrellaHeader] = Result; 20256c64013SDouglas Gregor UmbrellaDirs[FrameworkDir] = Result; 20356c64013SDouglas Gregor Modules[ModuleName] = Result; 20456c64013SDouglas Gregor return Result; 20556c64013SDouglas Gregor } 20656c64013SDouglas Gregor 207514b636aSDouglas Gregor const FileEntry * 208de3ef502SDouglas Gregor ModuleMap::getContainingModuleMapFile(Module *Module) { 209514b636aSDouglas Gregor if (Module->DefinitionLoc.isInvalid() || !SourceMgr) 210514b636aSDouglas Gregor return 0; 211514b636aSDouglas Gregor 212514b636aSDouglas Gregor return SourceMgr->getFileEntryForID( 213514b636aSDouglas Gregor SourceMgr->getFileID(Module->DefinitionLoc)); 214514b636aSDouglas Gregor } 215514b636aSDouglas Gregor 216718292f2SDouglas Gregor void ModuleMap::dump() { 217718292f2SDouglas Gregor llvm::errs() << "Modules:"; 218718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 219718292f2SDouglas Gregor MEnd = Modules.end(); 220718292f2SDouglas Gregor M != MEnd; ++M) 221d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 222718292f2SDouglas Gregor 223718292f2SDouglas Gregor llvm::errs() << "Headers:"; 224718292f2SDouglas Gregor for (llvm::DenseMap<const FileEntry *, Module *>::iterator 225718292f2SDouglas Gregor H = Headers.begin(), 226718292f2SDouglas Gregor HEnd = Headers.end(); 227718292f2SDouglas Gregor H != HEnd; ++H) { 228718292f2SDouglas Gregor llvm::errs() << " \"" << H->first->getName() << "\" -> " 229718292f2SDouglas Gregor << H->second->getFullModuleName() << "\n"; 230718292f2SDouglas Gregor } 231718292f2SDouglas Gregor } 232718292f2SDouglas Gregor 2332b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) { 2342b82c2a5SDouglas Gregor bool HadError = false; 2352b82c2a5SDouglas Gregor for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) { 2362b82c2a5SDouglas Gregor Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I], 2372b82c2a5SDouglas Gregor Complain); 238*f5eedd05SDouglas Gregor if (Export.getPointer() || Export.getInt()) 2392b82c2a5SDouglas Gregor Mod->Exports.push_back(Export); 2402b82c2a5SDouglas Gregor else 2412b82c2a5SDouglas Gregor HadError = true; 2422b82c2a5SDouglas Gregor } 2432b82c2a5SDouglas Gregor Mod->UnresolvedExports.clear(); 2442b82c2a5SDouglas Gregor return HadError; 2452b82c2a5SDouglas Gregor } 2462b82c2a5SDouglas Gregor 2470093b3c7SDouglas Gregor Module *ModuleMap::inferModuleFromLocation(FullSourceLoc Loc) { 2480093b3c7SDouglas Gregor if (Loc.isInvalid()) 2490093b3c7SDouglas Gregor return 0; 2500093b3c7SDouglas Gregor 2510093b3c7SDouglas Gregor // Use the expansion location to determine which module we're in. 2520093b3c7SDouglas Gregor FullSourceLoc ExpansionLoc = Loc.getExpansionLoc(); 2530093b3c7SDouglas Gregor if (!ExpansionLoc.isFileID()) 2540093b3c7SDouglas Gregor return 0; 2550093b3c7SDouglas Gregor 2560093b3c7SDouglas Gregor 2570093b3c7SDouglas Gregor const SourceManager &SrcMgr = Loc.getManager(); 2580093b3c7SDouglas Gregor FileID ExpansionFileID = ExpansionLoc.getFileID(); 2590093b3c7SDouglas Gregor const FileEntry *ExpansionFile = SrcMgr.getFileEntryForID(ExpansionFileID); 2600093b3c7SDouglas Gregor if (!ExpansionFile) 2610093b3c7SDouglas Gregor return 0; 2620093b3c7SDouglas Gregor 2630093b3c7SDouglas Gregor // Find the module that owns this header. 2640093b3c7SDouglas Gregor return findModuleForHeader(ExpansionFile); 2650093b3c7SDouglas Gregor } 2660093b3c7SDouglas Gregor 267718292f2SDouglas Gregor //----------------------------------------------------------------------------// 268718292f2SDouglas Gregor // Module map file parser 269718292f2SDouglas Gregor //----------------------------------------------------------------------------// 270718292f2SDouglas Gregor 271718292f2SDouglas Gregor namespace clang { 272718292f2SDouglas Gregor /// \brief A token in a module map file. 273718292f2SDouglas Gregor struct MMToken { 274718292f2SDouglas Gregor enum TokenKind { 275718292f2SDouglas Gregor EndOfFile, 276718292f2SDouglas Gregor HeaderKeyword, 277718292f2SDouglas Gregor Identifier, 278718292f2SDouglas Gregor ExplicitKeyword, 2792b82c2a5SDouglas Gregor ExportKeyword, 280755b2055SDouglas Gregor FrameworkKeyword, 281718292f2SDouglas Gregor ModuleKeyword, 2822b82c2a5SDouglas Gregor Period, 283718292f2SDouglas Gregor UmbrellaKeyword, 2842b82c2a5SDouglas Gregor Star, 285718292f2SDouglas Gregor StringLiteral, 286718292f2SDouglas Gregor LBrace, 287718292f2SDouglas Gregor RBrace 288718292f2SDouglas Gregor } Kind; 289718292f2SDouglas Gregor 290718292f2SDouglas Gregor unsigned Location; 291718292f2SDouglas Gregor unsigned StringLength; 292718292f2SDouglas Gregor const char *StringData; 293718292f2SDouglas Gregor 294718292f2SDouglas Gregor void clear() { 295718292f2SDouglas Gregor Kind = EndOfFile; 296718292f2SDouglas Gregor Location = 0; 297718292f2SDouglas Gregor StringLength = 0; 298718292f2SDouglas Gregor StringData = 0; 299718292f2SDouglas Gregor } 300718292f2SDouglas Gregor 301718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 302718292f2SDouglas Gregor 303718292f2SDouglas Gregor SourceLocation getLocation() const { 304718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 305718292f2SDouglas Gregor } 306718292f2SDouglas Gregor 307718292f2SDouglas Gregor StringRef getString() const { 308718292f2SDouglas Gregor return StringRef(StringData, StringLength); 309718292f2SDouglas Gregor } 310718292f2SDouglas Gregor }; 311718292f2SDouglas Gregor 312718292f2SDouglas Gregor class ModuleMapParser { 313718292f2SDouglas Gregor Lexer &L; 314718292f2SDouglas Gregor SourceManager &SourceMgr; 315718292f2SDouglas Gregor DiagnosticsEngine &Diags; 316718292f2SDouglas Gregor ModuleMap ⤅ 317718292f2SDouglas Gregor 3185257fc63SDouglas Gregor /// \brief The directory that this module map resides in. 3195257fc63SDouglas Gregor const DirectoryEntry *Directory; 3205257fc63SDouglas Gregor 321718292f2SDouglas Gregor /// \brief Whether an error occurred. 322718292f2SDouglas Gregor bool HadError; 323718292f2SDouglas Gregor 324718292f2SDouglas Gregor /// \brief Default target information, used only for string literal 325718292f2SDouglas Gregor /// parsing. 326718292f2SDouglas Gregor TargetInfo *Target; 327718292f2SDouglas Gregor 328718292f2SDouglas Gregor /// \brief Stores string data for the various string literals referenced 329718292f2SDouglas Gregor /// during parsing. 330718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 331718292f2SDouglas Gregor 332718292f2SDouglas Gregor /// \brief The current token. 333718292f2SDouglas Gregor MMToken Tok; 334718292f2SDouglas Gregor 335718292f2SDouglas Gregor /// \brief The active module. 336de3ef502SDouglas Gregor Module *ActiveModule; 337718292f2SDouglas Gregor 338718292f2SDouglas Gregor /// \brief Consume the current token and return its location. 339718292f2SDouglas Gregor SourceLocation consumeToken(); 340718292f2SDouglas Gregor 341718292f2SDouglas Gregor /// \brief Skip tokens until we reach the a token with the given kind 342718292f2SDouglas Gregor /// (or the end of the file). 343718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 344718292f2SDouglas Gregor 345718292f2SDouglas Gregor void parseModuleDecl(); 346718292f2SDouglas Gregor void parseUmbrellaDecl(); 347718292f2SDouglas Gregor void parseHeaderDecl(); 3482b82c2a5SDouglas Gregor void parseExportDecl(); 349718292f2SDouglas Gregor 350718292f2SDouglas Gregor public: 351718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 352718292f2SDouglas Gregor DiagnosticsEngine &Diags, 3535257fc63SDouglas Gregor ModuleMap &Map, 3545257fc63SDouglas Gregor const DirectoryEntry *Directory) 3555257fc63SDouglas Gregor : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map), 3565257fc63SDouglas Gregor Directory(Directory), HadError(false), ActiveModule(0) 357718292f2SDouglas Gregor { 358718292f2SDouglas Gregor TargetOptions TargetOpts; 359718292f2SDouglas Gregor TargetOpts.Triple = llvm::sys::getDefaultTargetTriple(); 360718292f2SDouglas Gregor Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); 361718292f2SDouglas Gregor 362718292f2SDouglas Gregor Tok.clear(); 363718292f2SDouglas Gregor consumeToken(); 364718292f2SDouglas Gregor } 365718292f2SDouglas Gregor 366718292f2SDouglas Gregor bool parseModuleMapFile(); 367718292f2SDouglas Gregor }; 368718292f2SDouglas Gregor } 369718292f2SDouglas Gregor 370718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 371718292f2SDouglas Gregor retry: 372718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 373718292f2SDouglas Gregor Tok.clear(); 374718292f2SDouglas Gregor 375718292f2SDouglas Gregor Token LToken; 376718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 377718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 378718292f2SDouglas Gregor switch (LToken.getKind()) { 379718292f2SDouglas Gregor case tok::raw_identifier: 380718292f2SDouglas Gregor Tok.StringData = LToken.getRawIdentifierData(); 381718292f2SDouglas Gregor Tok.StringLength = LToken.getLength(); 382718292f2SDouglas Gregor Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString()) 383718292f2SDouglas Gregor .Case("header", MMToken::HeaderKeyword) 384718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 3852b82c2a5SDouglas Gregor .Case("export", MMToken::ExportKeyword) 386755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 387718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 388718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 389718292f2SDouglas Gregor .Default(MMToken::Identifier); 390718292f2SDouglas Gregor break; 391718292f2SDouglas Gregor 392718292f2SDouglas Gregor case tok::eof: 393718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 394718292f2SDouglas Gregor break; 395718292f2SDouglas Gregor 396718292f2SDouglas Gregor case tok::l_brace: 397718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 398718292f2SDouglas Gregor break; 399718292f2SDouglas Gregor 4002b82c2a5SDouglas Gregor case tok::period: 4012b82c2a5SDouglas Gregor Tok.Kind = MMToken::Period; 4022b82c2a5SDouglas Gregor break; 4032b82c2a5SDouglas Gregor 404718292f2SDouglas Gregor case tok::r_brace: 405718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 406718292f2SDouglas Gregor break; 407718292f2SDouglas Gregor 4082b82c2a5SDouglas Gregor case tok::star: 4092b82c2a5SDouglas Gregor Tok.Kind = MMToken::Star; 4102b82c2a5SDouglas Gregor break; 4112b82c2a5SDouglas Gregor 412718292f2SDouglas Gregor case tok::string_literal: { 413718292f2SDouglas Gregor // Parse the string literal. 414718292f2SDouglas Gregor LangOptions LangOpts; 415718292f2SDouglas Gregor StringLiteralParser StringLiteral(<oken, 1, SourceMgr, LangOpts, *Target); 416718292f2SDouglas Gregor if (StringLiteral.hadError) 417718292f2SDouglas Gregor goto retry; 418718292f2SDouglas Gregor 419718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 420718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 421718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 422718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 423718292f2SDouglas Gregor Saved[Length] = 0; 424718292f2SDouglas Gregor 425718292f2SDouglas Gregor // Form the token. 426718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 427718292f2SDouglas Gregor Tok.StringData = Saved; 428718292f2SDouglas Gregor Tok.StringLength = Length; 429718292f2SDouglas Gregor break; 430718292f2SDouglas Gregor } 431718292f2SDouglas Gregor 432718292f2SDouglas Gregor case tok::comment: 433718292f2SDouglas Gregor goto retry; 434718292f2SDouglas Gregor 435718292f2SDouglas Gregor default: 436718292f2SDouglas Gregor Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token); 437718292f2SDouglas Gregor HadError = true; 438718292f2SDouglas Gregor goto retry; 439718292f2SDouglas Gregor } 440718292f2SDouglas Gregor 441718292f2SDouglas Gregor return Result; 442718292f2SDouglas Gregor } 443718292f2SDouglas Gregor 444718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 445718292f2SDouglas Gregor unsigned braceDepth = 0; 446718292f2SDouglas Gregor do { 447718292f2SDouglas Gregor switch (Tok.Kind) { 448718292f2SDouglas Gregor case MMToken::EndOfFile: 449718292f2SDouglas Gregor return; 450718292f2SDouglas Gregor 451718292f2SDouglas Gregor case MMToken::LBrace: 452718292f2SDouglas Gregor if (Tok.is(K) && braceDepth == 0) 453718292f2SDouglas Gregor return; 454718292f2SDouglas Gregor 455718292f2SDouglas Gregor ++braceDepth; 456718292f2SDouglas Gregor break; 457718292f2SDouglas Gregor 458718292f2SDouglas Gregor case MMToken::RBrace: 459718292f2SDouglas Gregor if (braceDepth > 0) 460718292f2SDouglas Gregor --braceDepth; 461718292f2SDouglas Gregor else if (Tok.is(K)) 462718292f2SDouglas Gregor return; 463718292f2SDouglas Gregor break; 464718292f2SDouglas Gregor 465718292f2SDouglas Gregor default: 466718292f2SDouglas Gregor if (braceDepth == 0 && Tok.is(K)) 467718292f2SDouglas Gregor return; 468718292f2SDouglas Gregor break; 469718292f2SDouglas Gregor } 470718292f2SDouglas Gregor 471718292f2SDouglas Gregor consumeToken(); 472718292f2SDouglas Gregor } while (true); 473718292f2SDouglas Gregor } 474718292f2SDouglas Gregor 475718292f2SDouglas Gregor /// \brief Parse a module declaration. 476718292f2SDouglas Gregor /// 477718292f2SDouglas Gregor /// module-declaration: 478755b2055SDouglas Gregor /// 'framework'[opt] 'module' identifier { module-member* } 479718292f2SDouglas Gregor /// 480718292f2SDouglas Gregor /// module-member: 481718292f2SDouglas Gregor /// umbrella-declaration 482718292f2SDouglas Gregor /// header-declaration 483718292f2SDouglas Gregor /// 'explicit'[opt] module-declaration 4842b82c2a5SDouglas Gregor /// export-declaration 485718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 486755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 487755b2055SDouglas Gregor Tok.is(MMToken::FrameworkKeyword)); 488718292f2SDouglas Gregor 489755b2055SDouglas Gregor // Parse 'framework' or 'explicit' keyword, if present. 490755b2055SDouglas Gregor bool Framework = false; 491718292f2SDouglas Gregor bool Explicit = false; 492755b2055SDouglas Gregor 493755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 494755b2055SDouglas Gregor consumeToken(); 495755b2055SDouglas Gregor Framework = true; 496755b2055SDouglas Gregor } 497755b2055SDouglas Gregor // Parse 'explicit' keyword, if present. 498755b2055SDouglas Gregor else if (Tok.is(MMToken::ExplicitKeyword)) { 499718292f2SDouglas Gregor consumeToken(); 500718292f2SDouglas Gregor Explicit = true; 501718292f2SDouglas Gregor } 502718292f2SDouglas Gregor 503718292f2SDouglas Gregor // Parse 'module' keyword. 504718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 505718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), 506718292f2SDouglas Gregor diag::err_mmap_expected_module_after_explicit); 507718292f2SDouglas Gregor consumeToken(); 508718292f2SDouglas Gregor HadError = true; 509718292f2SDouglas Gregor return; 510718292f2SDouglas Gregor } 511718292f2SDouglas Gregor consumeToken(); // 'module' keyword 512718292f2SDouglas Gregor 513718292f2SDouglas Gregor // Parse the module name. 514718292f2SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 515718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 516718292f2SDouglas Gregor HadError = true; 517718292f2SDouglas Gregor return; 518718292f2SDouglas Gregor } 519718292f2SDouglas Gregor StringRef ModuleName = Tok.getString(); 520718292f2SDouglas Gregor SourceLocation ModuleNameLoc = consumeToken(); 521718292f2SDouglas Gregor 522718292f2SDouglas Gregor // Parse the opening brace. 523718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 524718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 525718292f2SDouglas Gregor << ModuleName; 526718292f2SDouglas Gregor HadError = true; 527718292f2SDouglas Gregor return; 528718292f2SDouglas Gregor } 529718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 530718292f2SDouglas Gregor 531718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 532718292f2SDouglas Gregor llvm::StringMap<Module *> &ModuleSpace 533718292f2SDouglas Gregor = ActiveModule? ActiveModule->SubModules : Map.Modules; 534718292f2SDouglas Gregor llvm::StringMap<Module *>::iterator ExistingModule 535718292f2SDouglas Gregor = ModuleSpace.find(ModuleName); 536718292f2SDouglas Gregor if (ExistingModule != ModuleSpace.end()) { 537718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 538718292f2SDouglas Gregor << ModuleName; 539718292f2SDouglas Gregor Diags.Report(ExistingModule->getValue()->DefinitionLoc, 540718292f2SDouglas Gregor diag::note_mmap_prev_definition); 541718292f2SDouglas Gregor 542718292f2SDouglas Gregor // Skip the module definition. 543718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 544718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 545718292f2SDouglas Gregor consumeToken(); 546718292f2SDouglas Gregor 547718292f2SDouglas Gregor HadError = true; 548718292f2SDouglas Gregor return; 549718292f2SDouglas Gregor } 550718292f2SDouglas Gregor 551718292f2SDouglas Gregor // Start defining this module. 552755b2055SDouglas Gregor ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework, 553755b2055SDouglas Gregor Explicit); 554718292f2SDouglas Gregor ModuleSpace[ModuleName] = ActiveModule; 555718292f2SDouglas Gregor 556718292f2SDouglas Gregor bool Done = false; 557718292f2SDouglas Gregor do { 558718292f2SDouglas Gregor switch (Tok.Kind) { 559718292f2SDouglas Gregor case MMToken::EndOfFile: 560718292f2SDouglas Gregor case MMToken::RBrace: 561718292f2SDouglas Gregor Done = true; 562718292f2SDouglas Gregor break; 563718292f2SDouglas Gregor 564718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 565718292f2SDouglas Gregor case MMToken::ModuleKeyword: 566718292f2SDouglas Gregor parseModuleDecl(); 567718292f2SDouglas Gregor break; 568718292f2SDouglas Gregor 5692b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 5702b82c2a5SDouglas Gregor parseExportDecl(); 5712b82c2a5SDouglas Gregor break; 5722b82c2a5SDouglas Gregor 573718292f2SDouglas Gregor case MMToken::HeaderKeyword: 574718292f2SDouglas Gregor parseHeaderDecl(); 575718292f2SDouglas Gregor break; 576718292f2SDouglas Gregor 577718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 578718292f2SDouglas Gregor parseUmbrellaDecl(); 579718292f2SDouglas Gregor break; 580718292f2SDouglas Gregor 581718292f2SDouglas Gregor default: 582718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 583718292f2SDouglas Gregor consumeToken(); 584718292f2SDouglas Gregor break; 585718292f2SDouglas Gregor } 586718292f2SDouglas Gregor } while (!Done); 587718292f2SDouglas Gregor 588718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 589718292f2SDouglas Gregor consumeToken(); 590718292f2SDouglas Gregor else { 591718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 592718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 593718292f2SDouglas Gregor HadError = true; 594718292f2SDouglas Gregor } 595718292f2SDouglas Gregor 596718292f2SDouglas Gregor // We're done parsing this module. Pop back to our parent scope. 597718292f2SDouglas Gregor ActiveModule = ActiveModule->Parent; 598718292f2SDouglas Gregor } 599718292f2SDouglas Gregor 600718292f2SDouglas Gregor /// \brief Parse an umbrella header declaration. 601718292f2SDouglas Gregor /// 602718292f2SDouglas Gregor /// umbrella-declaration: 603718292f2SDouglas Gregor /// 'umbrella' string-literal 604718292f2SDouglas Gregor void ModuleMapParser::parseUmbrellaDecl() { 605718292f2SDouglas Gregor assert(Tok.is(MMToken::UmbrellaKeyword)); 606718292f2SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 607718292f2SDouglas Gregor 608718292f2SDouglas Gregor // Parse the header name. 609718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 610718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 611718292f2SDouglas Gregor << "umbrella"; 612718292f2SDouglas Gregor HadError = true; 613718292f2SDouglas Gregor return; 614718292f2SDouglas Gregor } 615718292f2SDouglas Gregor StringRef FileName = Tok.getString(); 616718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 617718292f2SDouglas Gregor 6185257fc63SDouglas Gregor // Check whether we already have an umbrella header. 6195257fc63SDouglas Gregor if (ActiveModule->UmbrellaHeader) { 6205257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict) 6215257fc63SDouglas Gregor << ActiveModule->getFullModuleName() 6225257fc63SDouglas Gregor << ActiveModule->UmbrellaHeader->getName(); 6235257fc63SDouglas Gregor HadError = true; 6245257fc63SDouglas Gregor return; 6255257fc63SDouglas Gregor } 6265257fc63SDouglas Gregor 6275257fc63SDouglas Gregor // Only top-level modules can have umbrella headers. 6285257fc63SDouglas Gregor if (ActiveModule->Parent) { 6295257fc63SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule) 6305257fc63SDouglas Gregor << ActiveModule->getFullModuleName(); 6315257fc63SDouglas Gregor HadError = true; 6325257fc63SDouglas Gregor return; 6335257fc63SDouglas Gregor } 6345257fc63SDouglas Gregor 6355257fc63SDouglas Gregor // Look for this file. 6365257fc63SDouglas Gregor llvm::SmallString<128> PathName; 637f545f67dSDouglas Gregor const FileEntry *File = 0; 638f545f67dSDouglas Gregor 639f545f67dSDouglas Gregor if (llvm::sys::path::is_absolute(FileName)) { 640f545f67dSDouglas Gregor PathName = FileName; 641f545f67dSDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 642f545f67dSDouglas Gregor } else { 643f545f67dSDouglas Gregor // Search for the header file within the search directory. 6445257fc63SDouglas Gregor PathName += Directory->getName(); 645755b2055SDouglas Gregor unsigned PathLength = PathName.size(); 646755b2055SDouglas Gregor if (ActiveModule->isPartOfFramework()) { 647755b2055SDouglas Gregor // Check whether this file is in the public headers. 648755b2055SDouglas Gregor llvm::sys::path::append(PathName, "Headers"); 6495257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 650755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 651755b2055SDouglas Gregor 652755b2055SDouglas Gregor if (!File) { 653755b2055SDouglas Gregor // Check whether this file is in the private headers. 654755b2055SDouglas Gregor PathName.resize(PathLength); 655755b2055SDouglas Gregor llvm::sys::path::append(PathName, "PrivateHeaders"); 656755b2055SDouglas Gregor llvm::sys::path::append(PathName, FileName); 657755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 658755b2055SDouglas Gregor } 659755b2055SDouglas Gregor 660755b2055SDouglas Gregor // FIXME: Deal with subframeworks. 661755b2055SDouglas Gregor } else { 662755b2055SDouglas Gregor // Lookup for normal headers. 663755b2055SDouglas Gregor llvm::sys::path::append(PathName, FileName); 664755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 665755b2055SDouglas Gregor } 666f545f67dSDouglas Gregor } 6675257fc63SDouglas Gregor 6685257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 6695257fc63SDouglas Gregor // Come up with a lazy way to do this. 670755b2055SDouglas Gregor if (File) { 6715257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 6725257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 6735257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 6745257fc63SDouglas Gregor HadError = true; 675b65dbfffSDouglas Gregor } else if ((OwningModule = Map.UmbrellaDirs[Directory])) { 676b65dbfffSDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 677b65dbfffSDouglas Gregor << OwningModule->getFullModuleName(); 678b65dbfffSDouglas Gregor HadError = true; 6795257fc63SDouglas Gregor } else { 6805257fc63SDouglas Gregor // Record this umbrella header. 6815257fc63SDouglas Gregor ActiveModule->UmbrellaHeader = File; 6825257fc63SDouglas Gregor Map.Headers[File] = ActiveModule; 683b65dbfffSDouglas Gregor Map.UmbrellaDirs[Directory] = ActiveModule; 6845257fc63SDouglas Gregor } 6855257fc63SDouglas Gregor } else { 6865257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 6875257fc63SDouglas Gregor << true << FileName; 6885257fc63SDouglas Gregor HadError = true; 6895257fc63SDouglas Gregor } 690718292f2SDouglas Gregor } 691718292f2SDouglas Gregor 692718292f2SDouglas Gregor /// \brief Parse a header declaration. 693718292f2SDouglas Gregor /// 694718292f2SDouglas Gregor /// header-declaration: 695718292f2SDouglas Gregor /// 'header' string-literal 696718292f2SDouglas Gregor void ModuleMapParser::parseHeaderDecl() { 697718292f2SDouglas Gregor assert(Tok.is(MMToken::HeaderKeyword)); 6981871ed3dSBenjamin Kramer consumeToken(); 699718292f2SDouglas Gregor 700718292f2SDouglas Gregor // Parse the header name. 701718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 702718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 703718292f2SDouglas Gregor << "header"; 704718292f2SDouglas Gregor HadError = true; 705718292f2SDouglas Gregor return; 706718292f2SDouglas Gregor } 707718292f2SDouglas Gregor StringRef FileName = Tok.getString(); 708718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 709718292f2SDouglas Gregor 7105257fc63SDouglas Gregor // Look for this file. 7115257fc63SDouglas Gregor llvm::SmallString<128> PathName; 712f545f67dSDouglas Gregor if (llvm::sys::path::is_relative(FileName)) { 713f545f67dSDouglas Gregor // FIXME: Change this search to also look for private headers! 7145257fc63SDouglas Gregor PathName += Directory->getName(); 715755b2055SDouglas Gregor 716755b2055SDouglas Gregor if (ActiveModule->isPartOfFramework()) 717755b2055SDouglas Gregor llvm::sys::path::append(PathName, "Headers"); 718f545f67dSDouglas Gregor } 719755b2055SDouglas Gregor 7205257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 7215257fc63SDouglas Gregor 7225257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 7235257fc63SDouglas Gregor // Come up with a lazy way to do this. 7245257fc63SDouglas Gregor if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) { 7255257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 7265257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 7275257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 7285257fc63SDouglas Gregor HadError = true; 7295257fc63SDouglas Gregor } else { 7305257fc63SDouglas Gregor // Record this file. 7315257fc63SDouglas Gregor ActiveModule->Headers.push_back(File); 7325257fc63SDouglas Gregor Map.Headers[File] = ActiveModule; 7335257fc63SDouglas Gregor } 7345257fc63SDouglas Gregor } else { 7355257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 7365257fc63SDouglas Gregor << false << FileName; 7375257fc63SDouglas Gregor HadError = true; 7385257fc63SDouglas Gregor } 739718292f2SDouglas Gregor } 740718292f2SDouglas Gregor 7412b82c2a5SDouglas Gregor /// \brief Parse a module export declaration. 7422b82c2a5SDouglas Gregor /// 7432b82c2a5SDouglas Gregor /// export-declaration: 7442b82c2a5SDouglas Gregor /// 'export' wildcard-module-id 7452b82c2a5SDouglas Gregor /// 7462b82c2a5SDouglas Gregor /// wildcard-module-id: 7472b82c2a5SDouglas Gregor /// identifier 7482b82c2a5SDouglas Gregor /// '*' 7492b82c2a5SDouglas Gregor /// identifier '.' wildcard-module-id 7502b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() { 7512b82c2a5SDouglas Gregor assert(Tok.is(MMToken::ExportKeyword)); 7522b82c2a5SDouglas Gregor SourceLocation ExportLoc = consumeToken(); 7532b82c2a5SDouglas Gregor 7542b82c2a5SDouglas Gregor // Parse the module-id with an optional wildcard at the end. 7552b82c2a5SDouglas Gregor ModuleId ParsedModuleId; 7562b82c2a5SDouglas Gregor bool Wildcard = false; 7572b82c2a5SDouglas Gregor do { 7582b82c2a5SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 7592b82c2a5SDouglas Gregor ParsedModuleId.push_back(std::make_pair(Tok.getString(), 7602b82c2a5SDouglas Gregor Tok.getLocation())); 7612b82c2a5SDouglas Gregor consumeToken(); 7622b82c2a5SDouglas Gregor 7632b82c2a5SDouglas Gregor if (Tok.is(MMToken::Period)) { 7642b82c2a5SDouglas Gregor consumeToken(); 7652b82c2a5SDouglas Gregor continue; 7662b82c2a5SDouglas Gregor } 7672b82c2a5SDouglas Gregor 7682b82c2a5SDouglas Gregor break; 7692b82c2a5SDouglas Gregor } 7702b82c2a5SDouglas Gregor 7712b82c2a5SDouglas Gregor if(Tok.is(MMToken::Star)) { 7722b82c2a5SDouglas Gregor Wildcard = true; 773*f5eedd05SDouglas Gregor consumeToken(); 7742b82c2a5SDouglas Gregor break; 7752b82c2a5SDouglas Gregor } 7762b82c2a5SDouglas Gregor 7772b82c2a5SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id); 7782b82c2a5SDouglas Gregor HadError = true; 7792b82c2a5SDouglas Gregor return; 7802b82c2a5SDouglas Gregor } while (true); 7812b82c2a5SDouglas Gregor 7822b82c2a5SDouglas Gregor Module::UnresolvedExportDecl Unresolved = { 7832b82c2a5SDouglas Gregor ExportLoc, ParsedModuleId, Wildcard 7842b82c2a5SDouglas Gregor }; 7852b82c2a5SDouglas Gregor ActiveModule->UnresolvedExports.push_back(Unresolved); 7862b82c2a5SDouglas Gregor } 7872b82c2a5SDouglas Gregor 788718292f2SDouglas Gregor /// \brief Parse a module map file. 789718292f2SDouglas Gregor /// 790718292f2SDouglas Gregor /// module-map-file: 791718292f2SDouglas Gregor /// module-declaration* 792718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 793718292f2SDouglas Gregor do { 794718292f2SDouglas Gregor switch (Tok.Kind) { 795718292f2SDouglas Gregor case MMToken::EndOfFile: 796718292f2SDouglas Gregor return HadError; 797718292f2SDouglas Gregor 798718292f2SDouglas Gregor case MMToken::ModuleKeyword: 799755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 800718292f2SDouglas Gregor parseModuleDecl(); 801718292f2SDouglas Gregor break; 802718292f2SDouglas Gregor 803718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 8042b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 805718292f2SDouglas Gregor case MMToken::HeaderKeyword: 806718292f2SDouglas Gregor case MMToken::Identifier: 807718292f2SDouglas Gregor case MMToken::LBrace: 8082b82c2a5SDouglas Gregor case MMToken::Period: 809718292f2SDouglas Gregor case MMToken::RBrace: 8102b82c2a5SDouglas Gregor case MMToken::Star: 811718292f2SDouglas Gregor case MMToken::StringLiteral: 812718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 813718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 814718292f2SDouglas Gregor HadError = true; 815718292f2SDouglas Gregor consumeToken(); 816718292f2SDouglas Gregor break; 817718292f2SDouglas Gregor } 818718292f2SDouglas Gregor } while (true); 819718292f2SDouglas Gregor 820718292f2SDouglas Gregor return HadError; 821718292f2SDouglas Gregor } 822718292f2SDouglas Gregor 823718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) { 824718292f2SDouglas Gregor FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User); 825718292f2SDouglas Gregor const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID); 826718292f2SDouglas Gregor if (!Buffer) 827718292f2SDouglas Gregor return true; 828718292f2SDouglas Gregor 829718292f2SDouglas Gregor // Parse this module map file. 830718292f2SDouglas Gregor Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts); 831718292f2SDouglas Gregor Diags->getClient()->BeginSourceFile(LangOpts); 8325257fc63SDouglas Gregor ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir()); 833718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 834718292f2SDouglas Gregor Diags->getClient()->EndSourceFile(); 835718292f2SDouglas Gregor 836718292f2SDouglas Gregor return Result; 837718292f2SDouglas Gregor } 838