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 30*2b82c2a5SDouglas Gregor Module::ExportDecl 31*2b82c2a5SDouglas Gregor ModuleMap::resolveExport(Module *Mod, 32*2b82c2a5SDouglas Gregor const Module::UnresolvedExportDecl &Unresolved, 33*2b82c2a5SDouglas Gregor bool Complain) { 34*2b82c2a5SDouglas Gregor // Find the starting module. 35*2b82c2a5SDouglas Gregor Module *Context = lookupModuleUnqualified(Unresolved.Id[0].first, Mod); 36*2b82c2a5SDouglas Gregor if (!Context) { 37*2b82c2a5SDouglas Gregor if (Complain) 38*2b82c2a5SDouglas Gregor Diags->Report(Unresolved.Id[0].second, 39*2b82c2a5SDouglas Gregor diag::err_mmap_missing_module_unqualified) 40*2b82c2a5SDouglas Gregor << Unresolved.Id[0].first << Mod->getFullModuleName(); 41*2b82c2a5SDouglas Gregor 42*2b82c2a5SDouglas Gregor return Module::ExportDecl(); 43*2b82c2a5SDouglas Gregor } 44*2b82c2a5SDouglas Gregor 45*2b82c2a5SDouglas Gregor // Dig into the module path. 46*2b82c2a5SDouglas Gregor for (unsigned I = 1, N = Unresolved.Id.size(); I != N; ++I) { 47*2b82c2a5SDouglas Gregor Module *Sub = lookupModuleQualified(Unresolved.Id[I].first, 48*2b82c2a5SDouglas Gregor Context); 49*2b82c2a5SDouglas Gregor if (!Sub) { 50*2b82c2a5SDouglas Gregor if (Complain) 51*2b82c2a5SDouglas Gregor Diags->Report(Unresolved.Id[I].second, 52*2b82c2a5SDouglas Gregor diag::err_mmap_missing_module_qualified) 53*2b82c2a5SDouglas Gregor << Unresolved.Id[I].first << Context->getFullModuleName() 54*2b82c2a5SDouglas Gregor << SourceRange(Unresolved.Id[0].second, Unresolved.Id[I-1].second); 55*2b82c2a5SDouglas Gregor 56*2b82c2a5SDouglas Gregor return Module::ExportDecl(); 57*2b82c2a5SDouglas Gregor } 58*2b82c2a5SDouglas Gregor 59*2b82c2a5SDouglas Gregor Context = Sub; 60*2b82c2a5SDouglas Gregor } 61*2b82c2a5SDouglas Gregor 62*2b82c2a5SDouglas Gregor return Module::ExportDecl(Context, Unresolved.Wildcard); 63*2b82c2a5SDouglas Gregor } 64*2b82c2a5SDouglas Gregor 65718292f2SDouglas Gregor ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) { 66718292f2SDouglas Gregor llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs); 67718292f2SDouglas Gregor Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>( 68718292f2SDouglas Gregor new DiagnosticsEngine(DiagIDs)); 69718292f2SDouglas Gregor Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true); 70718292f2SDouglas Gregor SourceMgr = new SourceManager(*Diags, FileMgr); 71718292f2SDouglas Gregor } 72718292f2SDouglas Gregor 73718292f2SDouglas Gregor ModuleMap::~ModuleMap() { 745acdf59eSDouglas Gregor for (llvm::StringMap<Module *>::iterator I = Modules.begin(), 755acdf59eSDouglas Gregor IEnd = Modules.end(); 765acdf59eSDouglas Gregor I != IEnd; ++I) { 775acdf59eSDouglas Gregor delete I->getValue(); 785acdf59eSDouglas Gregor } 795acdf59eSDouglas Gregor 80718292f2SDouglas Gregor delete SourceMgr; 81718292f2SDouglas Gregor } 82718292f2SDouglas Gregor 83de3ef502SDouglas Gregor Module *ModuleMap::findModuleForHeader(const FileEntry *File) { 84ab0c8a84SDouglas Gregor llvm::DenseMap<const FileEntry *, Module *>::iterator Known 85ab0c8a84SDouglas Gregor = Headers.find(File); 86ab0c8a84SDouglas Gregor if (Known != Headers.end()) 87ab0c8a84SDouglas Gregor return Known->second; 88ab0c8a84SDouglas Gregor 89b65dbfffSDouglas Gregor const DirectoryEntry *Dir = File->getDir(); 90b65dbfffSDouglas Gregor llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir 91b65dbfffSDouglas Gregor = UmbrellaDirs.find(Dir); 92b65dbfffSDouglas Gregor if (KnownDir != UmbrellaDirs.end()) 93b65dbfffSDouglas Gregor return KnownDir->second; 94b65dbfffSDouglas Gregor 95b65dbfffSDouglas Gregor // Walk up the directory hierarchy looking for umbrella headers. 96b65dbfffSDouglas Gregor llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs; 97b65dbfffSDouglas Gregor StringRef DirName = Dir->getName(); 98b65dbfffSDouglas Gregor do { 99b65dbfffSDouglas Gregor // Retrieve our parent path. 100b65dbfffSDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 101b65dbfffSDouglas Gregor if (DirName.empty()) 102b65dbfffSDouglas Gregor break; 103b65dbfffSDouglas Gregor 104b65dbfffSDouglas Gregor // Resolve the parent path to a directory entry. 105b65dbfffSDouglas Gregor Dir = SourceMgr->getFileManager().getDirectory(DirName); 106b65dbfffSDouglas Gregor if (!Dir) 107b65dbfffSDouglas Gregor break; 108b65dbfffSDouglas Gregor 109b65dbfffSDouglas Gregor KnownDir = UmbrellaDirs.find(Dir); 110b65dbfffSDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 111b65dbfffSDouglas Gregor Module *Result = KnownDir->second; 112b65dbfffSDouglas Gregor 113b65dbfffSDouglas Gregor // Record each of the directories we stepped through as being part of 114b65dbfffSDouglas Gregor // the module we found, since the umbrella header covers them all. 115b65dbfffSDouglas Gregor for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I) 116b65dbfffSDouglas Gregor UmbrellaDirs[SkippedDirs[I]] = Result; 117b65dbfffSDouglas Gregor 118b65dbfffSDouglas Gregor return Result; 119b65dbfffSDouglas Gregor } 120b65dbfffSDouglas Gregor 121b65dbfffSDouglas Gregor SkippedDirs.push_back(Dir); 122b65dbfffSDouglas Gregor } while (true); 123b65dbfffSDouglas Gregor 124ab0c8a84SDouglas Gregor return 0; 125ab0c8a84SDouglas Gregor } 126ab0c8a84SDouglas Gregor 127de3ef502SDouglas Gregor Module *ModuleMap::findModule(StringRef Name) { 12888bdfb0eSDouglas Gregor llvm::StringMap<Module *>::iterator Known = Modules.find(Name); 12988bdfb0eSDouglas Gregor if (Known != Modules.end()) 13088bdfb0eSDouglas Gregor return Known->getValue(); 13188bdfb0eSDouglas Gregor 13288bdfb0eSDouglas Gregor return 0; 13388bdfb0eSDouglas Gregor } 13488bdfb0eSDouglas Gregor 135*2b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleUnqualified(StringRef Name, Module *Context) { 136*2b82c2a5SDouglas Gregor for(; Context; Context = Context->Parent) { 137*2b82c2a5SDouglas Gregor if (Module *Sub = lookupModuleQualified(Name, Context)) 138*2b82c2a5SDouglas Gregor return Sub; 139*2b82c2a5SDouglas Gregor } 140*2b82c2a5SDouglas Gregor 141*2b82c2a5SDouglas Gregor return findModule(Name); 142*2b82c2a5SDouglas Gregor } 143*2b82c2a5SDouglas Gregor 144*2b82c2a5SDouglas Gregor Module *ModuleMap::lookupModuleQualified(StringRef Name, Module *Context) { 145*2b82c2a5SDouglas Gregor if (!Context) 146*2b82c2a5SDouglas Gregor return findModule(Name); 147*2b82c2a5SDouglas Gregor 148*2b82c2a5SDouglas Gregor llvm::StringMap<Module *>::iterator Sub = Context->SubModules.find(Name); 149*2b82c2a5SDouglas Gregor if (Sub != Context->SubModules.end()) 150*2b82c2a5SDouglas Gregor return Sub->getValue(); 151*2b82c2a5SDouglas Gregor 152*2b82c2a5SDouglas Gregor return 0; 153*2b82c2a5SDouglas Gregor } 154*2b82c2a5SDouglas Gregor 155de3ef502SDouglas Gregor std::pair<Module *, bool> 15669021974SDouglas Gregor ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework, 15769021974SDouglas Gregor bool IsExplicit) { 15869021974SDouglas Gregor // Try to find an existing module with this name. 15969021974SDouglas Gregor if (Module *Found = Parent? Parent->SubModules[Name] : Modules[Name]) 16069021974SDouglas Gregor return std::make_pair(Found, false); 16169021974SDouglas Gregor 16269021974SDouglas Gregor // Create a new module with this name. 16369021974SDouglas Gregor Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, 16469021974SDouglas Gregor IsExplicit); 16569021974SDouglas Gregor if (Parent) 16669021974SDouglas Gregor Parent->SubModules[Name] = Result; 16769021974SDouglas Gregor else 16869021974SDouglas Gregor Modules[Name] = Result; 16969021974SDouglas Gregor return std::make_pair(Result, true); 17069021974SDouglas Gregor } 17169021974SDouglas Gregor 172de3ef502SDouglas Gregor Module * 17356c64013SDouglas Gregor ModuleMap::inferFrameworkModule(StringRef ModuleName, 17456c64013SDouglas Gregor const DirectoryEntry *FrameworkDir) { 17556c64013SDouglas Gregor // Check whether we've already found this module. 17656c64013SDouglas Gregor if (Module *Module = findModule(ModuleName)) 17756c64013SDouglas Gregor return Module; 17856c64013SDouglas Gregor 17956c64013SDouglas Gregor // Look for an umbrella header. 18056c64013SDouglas Gregor llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 18156c64013SDouglas Gregor llvm::sys::path::append(UmbrellaName, "Headers"); 18256c64013SDouglas Gregor llvm::sys::path::append(UmbrellaName, ModuleName + ".h"); 18356c64013SDouglas Gregor const FileEntry *UmbrellaHeader 18456c64013SDouglas Gregor = SourceMgr->getFileManager().getFile(UmbrellaName); 18556c64013SDouglas Gregor 18656c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the 18756c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good 18856c64013SDouglas Gregor // idea. 18956c64013SDouglas Gregor if (!UmbrellaHeader) 19056c64013SDouglas Gregor return 0; 19156c64013SDouglas Gregor 192755b2055SDouglas Gregor Module *Result = new Module(ModuleName, SourceLocation(), 193755b2055SDouglas Gregor /*IsFramework=*/true); 19456c64013SDouglas Gregor Result->UmbrellaHeader = UmbrellaHeader; 19556c64013SDouglas Gregor Headers[UmbrellaHeader] = Result; 19656c64013SDouglas Gregor UmbrellaDirs[FrameworkDir] = Result; 19756c64013SDouglas Gregor Modules[ModuleName] = Result; 19856c64013SDouglas Gregor return Result; 19956c64013SDouglas Gregor } 20056c64013SDouglas Gregor 201514b636aSDouglas Gregor const FileEntry * 202de3ef502SDouglas Gregor ModuleMap::getContainingModuleMapFile(Module *Module) { 203514b636aSDouglas Gregor if (Module->DefinitionLoc.isInvalid() || !SourceMgr) 204514b636aSDouglas Gregor return 0; 205514b636aSDouglas Gregor 206514b636aSDouglas Gregor return SourceMgr->getFileEntryForID( 207514b636aSDouglas Gregor SourceMgr->getFileID(Module->DefinitionLoc)); 208514b636aSDouglas Gregor } 209514b636aSDouglas Gregor 210718292f2SDouglas Gregor void ModuleMap::dump() { 211718292f2SDouglas Gregor llvm::errs() << "Modules:"; 212718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 213718292f2SDouglas Gregor MEnd = Modules.end(); 214718292f2SDouglas Gregor M != MEnd; ++M) 215d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 216718292f2SDouglas Gregor 217718292f2SDouglas Gregor llvm::errs() << "Headers:"; 218718292f2SDouglas Gregor for (llvm::DenseMap<const FileEntry *, Module *>::iterator 219718292f2SDouglas Gregor H = Headers.begin(), 220718292f2SDouglas Gregor HEnd = Headers.end(); 221718292f2SDouglas Gregor H != HEnd; ++H) { 222718292f2SDouglas Gregor llvm::errs() << " \"" << H->first->getName() << "\" -> " 223718292f2SDouglas Gregor << H->second->getFullModuleName() << "\n"; 224718292f2SDouglas Gregor } 225718292f2SDouglas Gregor } 226718292f2SDouglas Gregor 227*2b82c2a5SDouglas Gregor bool ModuleMap::resolveExports(Module *Mod, bool Complain) { 228*2b82c2a5SDouglas Gregor bool HadError = false; 229*2b82c2a5SDouglas Gregor for (unsigned I = 0, N = Mod->UnresolvedExports.size(); I != N; ++I) { 230*2b82c2a5SDouglas Gregor Module::ExportDecl Export = resolveExport(Mod, Mod->UnresolvedExports[I], 231*2b82c2a5SDouglas Gregor Complain); 232*2b82c2a5SDouglas Gregor if (Export.getPointer()) 233*2b82c2a5SDouglas Gregor Mod->Exports.push_back(Export); 234*2b82c2a5SDouglas Gregor else 235*2b82c2a5SDouglas Gregor HadError = true; 236*2b82c2a5SDouglas Gregor } 237*2b82c2a5SDouglas Gregor Mod->UnresolvedExports.clear(); 238*2b82c2a5SDouglas Gregor return HadError; 239*2b82c2a5SDouglas Gregor } 240*2b82c2a5SDouglas Gregor 241718292f2SDouglas Gregor //----------------------------------------------------------------------------// 242718292f2SDouglas Gregor // Module map file parser 243718292f2SDouglas Gregor //----------------------------------------------------------------------------// 244718292f2SDouglas Gregor 245718292f2SDouglas Gregor namespace clang { 246718292f2SDouglas Gregor /// \brief A token in a module map file. 247718292f2SDouglas Gregor struct MMToken { 248718292f2SDouglas Gregor enum TokenKind { 249718292f2SDouglas Gregor EndOfFile, 250718292f2SDouglas Gregor HeaderKeyword, 251718292f2SDouglas Gregor Identifier, 252718292f2SDouglas Gregor ExplicitKeyword, 253*2b82c2a5SDouglas Gregor ExportKeyword, 254755b2055SDouglas Gregor FrameworkKeyword, 255718292f2SDouglas Gregor ModuleKeyword, 256*2b82c2a5SDouglas Gregor Period, 257718292f2SDouglas Gregor UmbrellaKeyword, 258*2b82c2a5SDouglas Gregor Star, 259718292f2SDouglas Gregor StringLiteral, 260718292f2SDouglas Gregor LBrace, 261718292f2SDouglas Gregor RBrace 262718292f2SDouglas Gregor } Kind; 263718292f2SDouglas Gregor 264718292f2SDouglas Gregor unsigned Location; 265718292f2SDouglas Gregor unsigned StringLength; 266718292f2SDouglas Gregor const char *StringData; 267718292f2SDouglas Gregor 268718292f2SDouglas Gregor void clear() { 269718292f2SDouglas Gregor Kind = EndOfFile; 270718292f2SDouglas Gregor Location = 0; 271718292f2SDouglas Gregor StringLength = 0; 272718292f2SDouglas Gregor StringData = 0; 273718292f2SDouglas Gregor } 274718292f2SDouglas Gregor 275718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 276718292f2SDouglas Gregor 277718292f2SDouglas Gregor SourceLocation getLocation() const { 278718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 279718292f2SDouglas Gregor } 280718292f2SDouglas Gregor 281718292f2SDouglas Gregor StringRef getString() const { 282718292f2SDouglas Gregor return StringRef(StringData, StringLength); 283718292f2SDouglas Gregor } 284718292f2SDouglas Gregor }; 285718292f2SDouglas Gregor 286718292f2SDouglas Gregor class ModuleMapParser { 287718292f2SDouglas Gregor Lexer &L; 288718292f2SDouglas Gregor SourceManager &SourceMgr; 289718292f2SDouglas Gregor DiagnosticsEngine &Diags; 290718292f2SDouglas Gregor ModuleMap ⤅ 291718292f2SDouglas Gregor 2925257fc63SDouglas Gregor /// \brief The directory that this module map resides in. 2935257fc63SDouglas Gregor const DirectoryEntry *Directory; 2945257fc63SDouglas Gregor 295718292f2SDouglas Gregor /// \brief Whether an error occurred. 296718292f2SDouglas Gregor bool HadError; 297718292f2SDouglas Gregor 298718292f2SDouglas Gregor /// \brief Default target information, used only for string literal 299718292f2SDouglas Gregor /// parsing. 300718292f2SDouglas Gregor TargetInfo *Target; 301718292f2SDouglas Gregor 302718292f2SDouglas Gregor /// \brief Stores string data for the various string literals referenced 303718292f2SDouglas Gregor /// during parsing. 304718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 305718292f2SDouglas Gregor 306718292f2SDouglas Gregor /// \brief The current token. 307718292f2SDouglas Gregor MMToken Tok; 308718292f2SDouglas Gregor 309718292f2SDouglas Gregor /// \brief The active module. 310de3ef502SDouglas Gregor Module *ActiveModule; 311718292f2SDouglas Gregor 312718292f2SDouglas Gregor /// \brief Consume the current token and return its location. 313718292f2SDouglas Gregor SourceLocation consumeToken(); 314718292f2SDouglas Gregor 315718292f2SDouglas Gregor /// \brief Skip tokens until we reach the a token with the given kind 316718292f2SDouglas Gregor /// (or the end of the file). 317718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 318718292f2SDouglas Gregor 319718292f2SDouglas Gregor void parseModuleDecl(); 320718292f2SDouglas Gregor void parseUmbrellaDecl(); 321718292f2SDouglas Gregor void parseHeaderDecl(); 322*2b82c2a5SDouglas Gregor void parseExportDecl(); 323718292f2SDouglas Gregor 324718292f2SDouglas Gregor public: 325718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 326718292f2SDouglas Gregor DiagnosticsEngine &Diags, 3275257fc63SDouglas Gregor ModuleMap &Map, 3285257fc63SDouglas Gregor const DirectoryEntry *Directory) 3295257fc63SDouglas Gregor : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map), 3305257fc63SDouglas Gregor Directory(Directory), HadError(false), ActiveModule(0) 331718292f2SDouglas Gregor { 332718292f2SDouglas Gregor TargetOptions TargetOpts; 333718292f2SDouglas Gregor TargetOpts.Triple = llvm::sys::getDefaultTargetTriple(); 334718292f2SDouglas Gregor Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); 335718292f2SDouglas Gregor 336718292f2SDouglas Gregor Tok.clear(); 337718292f2SDouglas Gregor consumeToken(); 338718292f2SDouglas Gregor } 339718292f2SDouglas Gregor 340718292f2SDouglas Gregor bool parseModuleMapFile(); 341718292f2SDouglas Gregor }; 342718292f2SDouglas Gregor } 343718292f2SDouglas Gregor 344718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 345718292f2SDouglas Gregor retry: 346718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 347718292f2SDouglas Gregor Tok.clear(); 348718292f2SDouglas Gregor 349718292f2SDouglas Gregor Token LToken; 350718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 351718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 352718292f2SDouglas Gregor switch (LToken.getKind()) { 353718292f2SDouglas Gregor case tok::raw_identifier: 354718292f2SDouglas Gregor Tok.StringData = LToken.getRawIdentifierData(); 355718292f2SDouglas Gregor Tok.StringLength = LToken.getLength(); 356718292f2SDouglas Gregor Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString()) 357718292f2SDouglas Gregor .Case("header", MMToken::HeaderKeyword) 358718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 359*2b82c2a5SDouglas Gregor .Case("export", MMToken::ExportKeyword) 360755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 361718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 362718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 363718292f2SDouglas Gregor .Default(MMToken::Identifier); 364718292f2SDouglas Gregor break; 365718292f2SDouglas Gregor 366718292f2SDouglas Gregor case tok::eof: 367718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 368718292f2SDouglas Gregor break; 369718292f2SDouglas Gregor 370718292f2SDouglas Gregor case tok::l_brace: 371718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 372718292f2SDouglas Gregor break; 373718292f2SDouglas Gregor 374*2b82c2a5SDouglas Gregor case tok::period: 375*2b82c2a5SDouglas Gregor Tok.Kind = MMToken::Period; 376*2b82c2a5SDouglas Gregor break; 377*2b82c2a5SDouglas Gregor 378718292f2SDouglas Gregor case tok::r_brace: 379718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 380718292f2SDouglas Gregor break; 381718292f2SDouglas Gregor 382*2b82c2a5SDouglas Gregor case tok::star: 383*2b82c2a5SDouglas Gregor Tok.Kind = MMToken::Star; 384*2b82c2a5SDouglas Gregor break; 385*2b82c2a5SDouglas Gregor 386718292f2SDouglas Gregor case tok::string_literal: { 387718292f2SDouglas Gregor // Parse the string literal. 388718292f2SDouglas Gregor LangOptions LangOpts; 389718292f2SDouglas Gregor StringLiteralParser StringLiteral(<oken, 1, SourceMgr, LangOpts, *Target); 390718292f2SDouglas Gregor if (StringLiteral.hadError) 391718292f2SDouglas Gregor goto retry; 392718292f2SDouglas Gregor 393718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 394718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 395718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 396718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 397718292f2SDouglas Gregor Saved[Length] = 0; 398718292f2SDouglas Gregor 399718292f2SDouglas Gregor // Form the token. 400718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 401718292f2SDouglas Gregor Tok.StringData = Saved; 402718292f2SDouglas Gregor Tok.StringLength = Length; 403718292f2SDouglas Gregor break; 404718292f2SDouglas Gregor } 405718292f2SDouglas Gregor 406718292f2SDouglas Gregor case tok::comment: 407718292f2SDouglas Gregor goto retry; 408718292f2SDouglas Gregor 409718292f2SDouglas Gregor default: 410718292f2SDouglas Gregor Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token); 411718292f2SDouglas Gregor HadError = true; 412718292f2SDouglas Gregor goto retry; 413718292f2SDouglas Gregor } 414718292f2SDouglas Gregor 415718292f2SDouglas Gregor return Result; 416718292f2SDouglas Gregor } 417718292f2SDouglas Gregor 418718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 419718292f2SDouglas Gregor unsigned braceDepth = 0; 420718292f2SDouglas Gregor do { 421718292f2SDouglas Gregor switch (Tok.Kind) { 422718292f2SDouglas Gregor case MMToken::EndOfFile: 423718292f2SDouglas Gregor return; 424718292f2SDouglas Gregor 425718292f2SDouglas Gregor case MMToken::LBrace: 426718292f2SDouglas Gregor if (Tok.is(K) && braceDepth == 0) 427718292f2SDouglas Gregor return; 428718292f2SDouglas Gregor 429718292f2SDouglas Gregor ++braceDepth; 430718292f2SDouglas Gregor break; 431718292f2SDouglas Gregor 432718292f2SDouglas Gregor case MMToken::RBrace: 433718292f2SDouglas Gregor if (braceDepth > 0) 434718292f2SDouglas Gregor --braceDepth; 435718292f2SDouglas Gregor else if (Tok.is(K)) 436718292f2SDouglas Gregor return; 437718292f2SDouglas Gregor break; 438718292f2SDouglas Gregor 439718292f2SDouglas Gregor default: 440718292f2SDouglas Gregor if (braceDepth == 0 && Tok.is(K)) 441718292f2SDouglas Gregor return; 442718292f2SDouglas Gregor break; 443718292f2SDouglas Gregor } 444718292f2SDouglas Gregor 445718292f2SDouglas Gregor consumeToken(); 446718292f2SDouglas Gregor } while (true); 447718292f2SDouglas Gregor } 448718292f2SDouglas Gregor 449718292f2SDouglas Gregor /// \brief Parse a module declaration. 450718292f2SDouglas Gregor /// 451718292f2SDouglas Gregor /// module-declaration: 452755b2055SDouglas Gregor /// 'framework'[opt] 'module' identifier { module-member* } 453718292f2SDouglas Gregor /// 454718292f2SDouglas Gregor /// module-member: 455718292f2SDouglas Gregor /// umbrella-declaration 456718292f2SDouglas Gregor /// header-declaration 457718292f2SDouglas Gregor /// 'explicit'[opt] module-declaration 458*2b82c2a5SDouglas Gregor /// export-declaration 459718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 460755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 461755b2055SDouglas Gregor Tok.is(MMToken::FrameworkKeyword)); 462718292f2SDouglas Gregor 463755b2055SDouglas Gregor // Parse 'framework' or 'explicit' keyword, if present. 464755b2055SDouglas Gregor bool Framework = false; 465718292f2SDouglas Gregor bool Explicit = false; 466755b2055SDouglas Gregor 467755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 468755b2055SDouglas Gregor consumeToken(); 469755b2055SDouglas Gregor Framework = true; 470755b2055SDouglas Gregor } 471755b2055SDouglas Gregor // Parse 'explicit' keyword, if present. 472755b2055SDouglas Gregor else if (Tok.is(MMToken::ExplicitKeyword)) { 473718292f2SDouglas Gregor consumeToken(); 474718292f2SDouglas Gregor Explicit = true; 475718292f2SDouglas Gregor } 476718292f2SDouglas Gregor 477718292f2SDouglas Gregor // Parse 'module' keyword. 478718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 479718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), 480718292f2SDouglas Gregor diag::err_mmap_expected_module_after_explicit); 481718292f2SDouglas Gregor consumeToken(); 482718292f2SDouglas Gregor HadError = true; 483718292f2SDouglas Gregor return; 484718292f2SDouglas Gregor } 485718292f2SDouglas Gregor consumeToken(); // 'module' keyword 486718292f2SDouglas Gregor 487718292f2SDouglas Gregor // Parse the module name. 488718292f2SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 489718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 490718292f2SDouglas Gregor HadError = true; 491718292f2SDouglas Gregor return; 492718292f2SDouglas Gregor } 493718292f2SDouglas Gregor StringRef ModuleName = Tok.getString(); 494718292f2SDouglas Gregor SourceLocation ModuleNameLoc = consumeToken(); 495718292f2SDouglas Gregor 496718292f2SDouglas Gregor // Parse the opening brace. 497718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 498718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 499718292f2SDouglas Gregor << ModuleName; 500718292f2SDouglas Gregor HadError = true; 501718292f2SDouglas Gregor return; 502718292f2SDouglas Gregor } 503718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 504718292f2SDouglas Gregor 505718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 506718292f2SDouglas Gregor llvm::StringMap<Module *> &ModuleSpace 507718292f2SDouglas Gregor = ActiveModule? ActiveModule->SubModules : Map.Modules; 508718292f2SDouglas Gregor llvm::StringMap<Module *>::iterator ExistingModule 509718292f2SDouglas Gregor = ModuleSpace.find(ModuleName); 510718292f2SDouglas Gregor if (ExistingModule != ModuleSpace.end()) { 511718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 512718292f2SDouglas Gregor << ModuleName; 513718292f2SDouglas Gregor Diags.Report(ExistingModule->getValue()->DefinitionLoc, 514718292f2SDouglas Gregor diag::note_mmap_prev_definition); 515718292f2SDouglas Gregor 516718292f2SDouglas Gregor // Skip the module definition. 517718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 518718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 519718292f2SDouglas Gregor consumeToken(); 520718292f2SDouglas Gregor 521718292f2SDouglas Gregor HadError = true; 522718292f2SDouglas Gregor return; 523718292f2SDouglas Gregor } 524718292f2SDouglas Gregor 525718292f2SDouglas Gregor // Start defining this module. 526755b2055SDouglas Gregor ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework, 527755b2055SDouglas Gregor Explicit); 528718292f2SDouglas Gregor ModuleSpace[ModuleName] = ActiveModule; 529718292f2SDouglas Gregor 530718292f2SDouglas Gregor bool Done = false; 531718292f2SDouglas Gregor do { 532718292f2SDouglas Gregor switch (Tok.Kind) { 533718292f2SDouglas Gregor case MMToken::EndOfFile: 534718292f2SDouglas Gregor case MMToken::RBrace: 535718292f2SDouglas Gregor Done = true; 536718292f2SDouglas Gregor break; 537718292f2SDouglas Gregor 538718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 539718292f2SDouglas Gregor case MMToken::ModuleKeyword: 540718292f2SDouglas Gregor parseModuleDecl(); 541718292f2SDouglas Gregor break; 542718292f2SDouglas Gregor 543*2b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 544*2b82c2a5SDouglas Gregor parseExportDecl(); 545*2b82c2a5SDouglas Gregor break; 546*2b82c2a5SDouglas Gregor 547718292f2SDouglas Gregor case MMToken::HeaderKeyword: 548718292f2SDouglas Gregor parseHeaderDecl(); 549718292f2SDouglas Gregor break; 550718292f2SDouglas Gregor 551718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 552718292f2SDouglas Gregor parseUmbrellaDecl(); 553718292f2SDouglas Gregor break; 554718292f2SDouglas Gregor 555718292f2SDouglas Gregor default: 556718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 557718292f2SDouglas Gregor consumeToken(); 558718292f2SDouglas Gregor break; 559718292f2SDouglas Gregor } 560718292f2SDouglas Gregor } while (!Done); 561718292f2SDouglas Gregor 562718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 563718292f2SDouglas Gregor consumeToken(); 564718292f2SDouglas Gregor else { 565718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 566718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 567718292f2SDouglas Gregor HadError = true; 568718292f2SDouglas Gregor } 569718292f2SDouglas Gregor 570718292f2SDouglas Gregor // We're done parsing this module. Pop back to our parent scope. 571718292f2SDouglas Gregor ActiveModule = ActiveModule->Parent; 572718292f2SDouglas Gregor } 573718292f2SDouglas Gregor 574718292f2SDouglas Gregor /// \brief Parse an umbrella header declaration. 575718292f2SDouglas Gregor /// 576718292f2SDouglas Gregor /// umbrella-declaration: 577718292f2SDouglas Gregor /// 'umbrella' string-literal 578718292f2SDouglas Gregor void ModuleMapParser::parseUmbrellaDecl() { 579718292f2SDouglas Gregor assert(Tok.is(MMToken::UmbrellaKeyword)); 580718292f2SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 581718292f2SDouglas Gregor 582718292f2SDouglas Gregor // Parse the header name. 583718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 584718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 585718292f2SDouglas Gregor << "umbrella"; 586718292f2SDouglas Gregor HadError = true; 587718292f2SDouglas Gregor return; 588718292f2SDouglas Gregor } 589718292f2SDouglas Gregor StringRef FileName = Tok.getString(); 590718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 591718292f2SDouglas Gregor 5925257fc63SDouglas Gregor // Check whether we already have an umbrella header. 5935257fc63SDouglas Gregor if (ActiveModule->UmbrellaHeader) { 5945257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict) 5955257fc63SDouglas Gregor << ActiveModule->getFullModuleName() 5965257fc63SDouglas Gregor << ActiveModule->UmbrellaHeader->getName(); 5975257fc63SDouglas Gregor HadError = true; 5985257fc63SDouglas Gregor return; 5995257fc63SDouglas Gregor } 6005257fc63SDouglas Gregor 6015257fc63SDouglas Gregor // Only top-level modules can have umbrella headers. 6025257fc63SDouglas Gregor if (ActiveModule->Parent) { 6035257fc63SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule) 6045257fc63SDouglas Gregor << ActiveModule->getFullModuleName(); 6055257fc63SDouglas Gregor HadError = true; 6065257fc63SDouglas Gregor return; 6075257fc63SDouglas Gregor } 6085257fc63SDouglas Gregor 6095257fc63SDouglas Gregor // Look for this file. 6105257fc63SDouglas Gregor llvm::SmallString<128> PathName; 611f545f67dSDouglas Gregor const FileEntry *File = 0; 612f545f67dSDouglas Gregor 613f545f67dSDouglas Gregor if (llvm::sys::path::is_absolute(FileName)) { 614f545f67dSDouglas Gregor PathName = FileName; 615f545f67dSDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 616f545f67dSDouglas Gregor } else { 617f545f67dSDouglas Gregor // Search for the header file within the search directory. 6185257fc63SDouglas Gregor PathName += Directory->getName(); 619755b2055SDouglas Gregor unsigned PathLength = PathName.size(); 620755b2055SDouglas Gregor if (ActiveModule->isPartOfFramework()) { 621755b2055SDouglas Gregor // Check whether this file is in the public headers. 622755b2055SDouglas Gregor llvm::sys::path::append(PathName, "Headers"); 6235257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 624755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 625755b2055SDouglas Gregor 626755b2055SDouglas Gregor if (!File) { 627755b2055SDouglas Gregor // Check whether this file is in the private headers. 628755b2055SDouglas Gregor PathName.resize(PathLength); 629755b2055SDouglas Gregor llvm::sys::path::append(PathName, "PrivateHeaders"); 630755b2055SDouglas Gregor llvm::sys::path::append(PathName, FileName); 631755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 632755b2055SDouglas Gregor } 633755b2055SDouglas Gregor 634755b2055SDouglas Gregor // FIXME: Deal with subframeworks. 635755b2055SDouglas Gregor } else { 636755b2055SDouglas Gregor // Lookup for normal headers. 637755b2055SDouglas Gregor llvm::sys::path::append(PathName, FileName); 638755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 639755b2055SDouglas Gregor } 640f545f67dSDouglas Gregor } 6415257fc63SDouglas Gregor 6425257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 6435257fc63SDouglas Gregor // Come up with a lazy way to do this. 644755b2055SDouglas Gregor if (File) { 6455257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 6465257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 6475257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 6485257fc63SDouglas Gregor HadError = true; 649b65dbfffSDouglas Gregor } else if ((OwningModule = Map.UmbrellaDirs[Directory])) { 650b65dbfffSDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 651b65dbfffSDouglas Gregor << OwningModule->getFullModuleName(); 652b65dbfffSDouglas Gregor HadError = true; 6535257fc63SDouglas Gregor } else { 6545257fc63SDouglas Gregor // Record this umbrella header. 6555257fc63SDouglas Gregor ActiveModule->UmbrellaHeader = File; 6565257fc63SDouglas Gregor Map.Headers[File] = ActiveModule; 657b65dbfffSDouglas Gregor Map.UmbrellaDirs[Directory] = ActiveModule; 6585257fc63SDouglas Gregor } 6595257fc63SDouglas Gregor } else { 6605257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 6615257fc63SDouglas Gregor << true << FileName; 6625257fc63SDouglas Gregor HadError = true; 6635257fc63SDouglas Gregor } 664718292f2SDouglas Gregor } 665718292f2SDouglas Gregor 666718292f2SDouglas Gregor /// \brief Parse a header declaration. 667718292f2SDouglas Gregor /// 668718292f2SDouglas Gregor /// header-declaration: 669718292f2SDouglas Gregor /// 'header' string-literal 670718292f2SDouglas Gregor void ModuleMapParser::parseHeaderDecl() { 671718292f2SDouglas Gregor assert(Tok.is(MMToken::HeaderKeyword)); 6721871ed3dSBenjamin Kramer consumeToken(); 673718292f2SDouglas Gregor 674718292f2SDouglas Gregor // Parse the header name. 675718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 676718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 677718292f2SDouglas Gregor << "header"; 678718292f2SDouglas Gregor HadError = true; 679718292f2SDouglas Gregor return; 680718292f2SDouglas Gregor } 681718292f2SDouglas Gregor StringRef FileName = Tok.getString(); 682718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 683718292f2SDouglas Gregor 6845257fc63SDouglas Gregor // Look for this file. 6855257fc63SDouglas Gregor llvm::SmallString<128> PathName; 686f545f67dSDouglas Gregor if (llvm::sys::path::is_relative(FileName)) { 687f545f67dSDouglas Gregor // FIXME: Change this search to also look for private headers! 6885257fc63SDouglas Gregor PathName += Directory->getName(); 689755b2055SDouglas Gregor 690755b2055SDouglas Gregor if (ActiveModule->isPartOfFramework()) 691755b2055SDouglas Gregor llvm::sys::path::append(PathName, "Headers"); 692f545f67dSDouglas Gregor } 693755b2055SDouglas Gregor 6945257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 6955257fc63SDouglas Gregor 6965257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 6975257fc63SDouglas Gregor // Come up with a lazy way to do this. 6985257fc63SDouglas Gregor if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) { 6995257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 7005257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 7015257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 7025257fc63SDouglas Gregor HadError = true; 7035257fc63SDouglas Gregor } else { 7045257fc63SDouglas Gregor // Record this file. 7055257fc63SDouglas Gregor ActiveModule->Headers.push_back(File); 7065257fc63SDouglas Gregor Map.Headers[File] = ActiveModule; 7075257fc63SDouglas Gregor } 7085257fc63SDouglas Gregor } else { 7095257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 7105257fc63SDouglas Gregor << false << FileName; 7115257fc63SDouglas Gregor HadError = true; 7125257fc63SDouglas Gregor } 713718292f2SDouglas Gregor } 714718292f2SDouglas Gregor 715*2b82c2a5SDouglas Gregor /// \brief Parse a module export declaration. 716*2b82c2a5SDouglas Gregor /// 717*2b82c2a5SDouglas Gregor /// export-declaration: 718*2b82c2a5SDouglas Gregor /// 'export' wildcard-module-id 719*2b82c2a5SDouglas Gregor /// 720*2b82c2a5SDouglas Gregor /// wildcard-module-id: 721*2b82c2a5SDouglas Gregor /// identifier 722*2b82c2a5SDouglas Gregor /// '*' 723*2b82c2a5SDouglas Gregor /// identifier '.' wildcard-module-id 724*2b82c2a5SDouglas Gregor void ModuleMapParser::parseExportDecl() { 725*2b82c2a5SDouglas Gregor assert(Tok.is(MMToken::ExportKeyword)); 726*2b82c2a5SDouglas Gregor SourceLocation ExportLoc = consumeToken(); 727*2b82c2a5SDouglas Gregor 728*2b82c2a5SDouglas Gregor // Parse the module-id with an optional wildcard at the end. 729*2b82c2a5SDouglas Gregor ModuleId ParsedModuleId; 730*2b82c2a5SDouglas Gregor bool Wildcard = false; 731*2b82c2a5SDouglas Gregor do { 732*2b82c2a5SDouglas Gregor if (Tok.is(MMToken::Identifier)) { 733*2b82c2a5SDouglas Gregor ParsedModuleId.push_back(std::make_pair(Tok.getString(), 734*2b82c2a5SDouglas Gregor Tok.getLocation())); 735*2b82c2a5SDouglas Gregor consumeToken(); 736*2b82c2a5SDouglas Gregor 737*2b82c2a5SDouglas Gregor if (Tok.is(MMToken::Period)) { 738*2b82c2a5SDouglas Gregor consumeToken(); 739*2b82c2a5SDouglas Gregor continue; 740*2b82c2a5SDouglas Gregor } 741*2b82c2a5SDouglas Gregor 742*2b82c2a5SDouglas Gregor break; 743*2b82c2a5SDouglas Gregor } 744*2b82c2a5SDouglas Gregor 745*2b82c2a5SDouglas Gregor if(Tok.is(MMToken::Star)) { 746*2b82c2a5SDouglas Gregor Wildcard = true; 747*2b82c2a5SDouglas Gregor break; 748*2b82c2a5SDouglas Gregor } 749*2b82c2a5SDouglas Gregor 750*2b82c2a5SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_export_module_id); 751*2b82c2a5SDouglas Gregor HadError = true; 752*2b82c2a5SDouglas Gregor return; 753*2b82c2a5SDouglas Gregor } while (true); 754*2b82c2a5SDouglas Gregor 755*2b82c2a5SDouglas Gregor Module::UnresolvedExportDecl Unresolved = { 756*2b82c2a5SDouglas Gregor ExportLoc, ParsedModuleId, Wildcard 757*2b82c2a5SDouglas Gregor }; 758*2b82c2a5SDouglas Gregor ActiveModule->UnresolvedExports.push_back(Unresolved); 759*2b82c2a5SDouglas Gregor } 760*2b82c2a5SDouglas Gregor 761718292f2SDouglas Gregor /// \brief Parse a module map file. 762718292f2SDouglas Gregor /// 763718292f2SDouglas Gregor /// module-map-file: 764718292f2SDouglas Gregor /// module-declaration* 765718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 766718292f2SDouglas Gregor do { 767718292f2SDouglas Gregor switch (Tok.Kind) { 768718292f2SDouglas Gregor case MMToken::EndOfFile: 769718292f2SDouglas Gregor return HadError; 770718292f2SDouglas Gregor 771718292f2SDouglas Gregor case MMToken::ModuleKeyword: 772755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 773718292f2SDouglas Gregor parseModuleDecl(); 774718292f2SDouglas Gregor break; 775718292f2SDouglas Gregor 776718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 777*2b82c2a5SDouglas Gregor case MMToken::ExportKeyword: 778718292f2SDouglas Gregor case MMToken::HeaderKeyword: 779718292f2SDouglas Gregor case MMToken::Identifier: 780718292f2SDouglas Gregor case MMToken::LBrace: 781*2b82c2a5SDouglas Gregor case MMToken::Period: 782718292f2SDouglas Gregor case MMToken::RBrace: 783*2b82c2a5SDouglas Gregor case MMToken::Star: 784718292f2SDouglas Gregor case MMToken::StringLiteral: 785718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 786718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 787718292f2SDouglas Gregor HadError = true; 788718292f2SDouglas Gregor consumeToken(); 789718292f2SDouglas Gregor break; 790718292f2SDouglas Gregor } 791718292f2SDouglas Gregor } while (true); 792718292f2SDouglas Gregor 793718292f2SDouglas Gregor return HadError; 794718292f2SDouglas Gregor } 795718292f2SDouglas Gregor 796718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) { 797718292f2SDouglas Gregor FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User); 798718292f2SDouglas Gregor const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID); 799718292f2SDouglas Gregor if (!Buffer) 800718292f2SDouglas Gregor return true; 801718292f2SDouglas Gregor 802718292f2SDouglas Gregor // Parse this module map file. 803718292f2SDouglas Gregor Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts); 804718292f2SDouglas Gregor Diags->getClient()->BeginSourceFile(LangOpts); 8055257fc63SDouglas Gregor ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir()); 806718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 807718292f2SDouglas Gregor Diags->getClient()->EndSourceFile(); 808718292f2SDouglas Gregor 809718292f2SDouglas Gregor return Result; 810718292f2SDouglas Gregor } 811