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 30718292f2SDouglas Gregor //----------------------------------------------------------------------------// 31718292f2SDouglas Gregor // Module 32718292f2SDouglas Gregor //----------------------------------------------------------------------------// 33718292f2SDouglas Gregor 34*5acdf59eSDouglas Gregor ModuleMap::Module::~Module() { 35*5acdf59eSDouglas Gregor for (llvm::StringMap<Module *>::iterator I = SubModules.begin(), 36*5acdf59eSDouglas Gregor IEnd = SubModules.end(); 37*5acdf59eSDouglas Gregor I != IEnd; ++I) { 38*5acdf59eSDouglas Gregor delete I->getValue(); 39*5acdf59eSDouglas Gregor } 40*5acdf59eSDouglas Gregor 41*5acdf59eSDouglas Gregor } 42*5acdf59eSDouglas Gregor 43718292f2SDouglas Gregor std::string ModuleMap::Module::getFullModuleName() const { 44718292f2SDouglas Gregor llvm::SmallVector<StringRef, 2> Names; 45718292f2SDouglas Gregor 46718292f2SDouglas Gregor // Build up the set of module names (from innermost to outermost). 47718292f2SDouglas Gregor for (const Module *M = this; M; M = M->Parent) 48718292f2SDouglas Gregor Names.push_back(M->Name); 49718292f2SDouglas Gregor 50718292f2SDouglas Gregor std::string Result; 51718292f2SDouglas Gregor for (llvm::SmallVector<StringRef, 2>::reverse_iterator I = Names.rbegin(), 52718292f2SDouglas Gregor IEnd = Names.rend(); 53718292f2SDouglas Gregor I != IEnd; ++I) { 54718292f2SDouglas Gregor if (!Result.empty()) 55718292f2SDouglas Gregor Result += '.'; 56718292f2SDouglas Gregor 57718292f2SDouglas Gregor Result += *I; 58718292f2SDouglas Gregor } 59718292f2SDouglas Gregor 60718292f2SDouglas Gregor return Result; 61718292f2SDouglas Gregor } 62718292f2SDouglas Gregor 63ab0c8a84SDouglas Gregor StringRef ModuleMap::Module::getTopLevelModuleName() const { 64ab0c8a84SDouglas Gregor const Module *Top = this; 65ab0c8a84SDouglas Gregor while (Top->Parent) 66ab0c8a84SDouglas Gregor Top = Top->Parent; 67ab0c8a84SDouglas Gregor 68ab0c8a84SDouglas Gregor return Top->Name; 69ab0c8a84SDouglas Gregor } 70ab0c8a84SDouglas Gregor 71718292f2SDouglas Gregor //----------------------------------------------------------------------------// 72718292f2SDouglas Gregor // Module map 73718292f2SDouglas Gregor //----------------------------------------------------------------------------// 74718292f2SDouglas Gregor 75718292f2SDouglas Gregor ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) { 76718292f2SDouglas Gregor llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs); 77718292f2SDouglas Gregor Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>( 78718292f2SDouglas Gregor new DiagnosticsEngine(DiagIDs)); 79718292f2SDouglas Gregor Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true); 80718292f2SDouglas Gregor SourceMgr = new SourceManager(*Diags, FileMgr); 81718292f2SDouglas Gregor } 82718292f2SDouglas Gregor 83718292f2SDouglas Gregor ModuleMap::~ModuleMap() { 84*5acdf59eSDouglas Gregor for (llvm::StringMap<Module *>::iterator I = Modules.begin(), 85*5acdf59eSDouglas Gregor IEnd = Modules.end(); 86*5acdf59eSDouglas Gregor I != IEnd; ++I) { 87*5acdf59eSDouglas Gregor delete I->getValue(); 88*5acdf59eSDouglas Gregor } 89*5acdf59eSDouglas Gregor 90718292f2SDouglas Gregor delete SourceMgr; 91718292f2SDouglas Gregor } 92718292f2SDouglas Gregor 93ab0c8a84SDouglas Gregor ModuleMap::Module *ModuleMap::findModuleForHeader(const FileEntry *File) { 94ab0c8a84SDouglas Gregor llvm::DenseMap<const FileEntry *, Module *>::iterator Known 95ab0c8a84SDouglas Gregor = Headers.find(File); 96ab0c8a84SDouglas Gregor if (Known != Headers.end()) 97ab0c8a84SDouglas Gregor return Known->second; 98ab0c8a84SDouglas Gregor 99b65dbfffSDouglas Gregor const DirectoryEntry *Dir = File->getDir(); 100b65dbfffSDouglas Gregor llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir 101b65dbfffSDouglas Gregor = UmbrellaDirs.find(Dir); 102b65dbfffSDouglas Gregor if (KnownDir != UmbrellaDirs.end()) 103b65dbfffSDouglas Gregor return KnownDir->second; 104b65dbfffSDouglas Gregor 105b65dbfffSDouglas Gregor // Walk up the directory hierarchy looking for umbrella headers. 106b65dbfffSDouglas Gregor llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs; 107b65dbfffSDouglas Gregor StringRef DirName = Dir->getName(); 108b65dbfffSDouglas Gregor do { 109b65dbfffSDouglas Gregor // Retrieve our parent path. 110b65dbfffSDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 111b65dbfffSDouglas Gregor if (DirName.empty()) 112b65dbfffSDouglas Gregor break; 113b65dbfffSDouglas Gregor 114b65dbfffSDouglas Gregor // Resolve the parent path to a directory entry. 115b65dbfffSDouglas Gregor Dir = SourceMgr->getFileManager().getDirectory(DirName); 116b65dbfffSDouglas Gregor if (!Dir) 117b65dbfffSDouglas Gregor break; 118b65dbfffSDouglas Gregor 119b65dbfffSDouglas Gregor KnownDir = UmbrellaDirs.find(Dir); 120b65dbfffSDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 121b65dbfffSDouglas Gregor Module *Result = KnownDir->second; 122b65dbfffSDouglas Gregor 123b65dbfffSDouglas Gregor // Record each of the directories we stepped through as being part of 124b65dbfffSDouglas Gregor // the module we found, since the umbrella header covers them all. 125b65dbfffSDouglas Gregor for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I) 126b65dbfffSDouglas Gregor UmbrellaDirs[SkippedDirs[I]] = Result; 127b65dbfffSDouglas Gregor 128b65dbfffSDouglas Gregor return Result; 129b65dbfffSDouglas Gregor } 130b65dbfffSDouglas Gregor 131b65dbfffSDouglas Gregor SkippedDirs.push_back(Dir); 132b65dbfffSDouglas Gregor } while (true); 133b65dbfffSDouglas Gregor 134ab0c8a84SDouglas Gregor return 0; 135ab0c8a84SDouglas Gregor } 136ab0c8a84SDouglas Gregor 13788bdfb0eSDouglas Gregor ModuleMap::Module *ModuleMap::findModule(StringRef Name) { 13888bdfb0eSDouglas Gregor llvm::StringMap<Module *>::iterator Known = Modules.find(Name); 13988bdfb0eSDouglas Gregor if (Known != Modules.end()) 14088bdfb0eSDouglas Gregor return Known->getValue(); 14188bdfb0eSDouglas Gregor 14288bdfb0eSDouglas Gregor return 0; 14388bdfb0eSDouglas Gregor } 14488bdfb0eSDouglas Gregor 14556c64013SDouglas Gregor ModuleMap::Module * 14656c64013SDouglas Gregor ModuleMap::inferFrameworkModule(StringRef ModuleName, 14756c64013SDouglas Gregor const DirectoryEntry *FrameworkDir) { 14856c64013SDouglas Gregor // Check whether we've already found this module. 14956c64013SDouglas Gregor if (Module *Module = findModule(ModuleName)) 15056c64013SDouglas Gregor return Module; 15156c64013SDouglas Gregor 15256c64013SDouglas Gregor // Look for an umbrella header. 15356c64013SDouglas Gregor llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 15456c64013SDouglas Gregor llvm::sys::path::append(UmbrellaName, "Headers"); 15556c64013SDouglas Gregor llvm::sys::path::append(UmbrellaName, ModuleName + ".h"); 15656c64013SDouglas Gregor const FileEntry *UmbrellaHeader 15756c64013SDouglas Gregor = SourceMgr->getFileManager().getFile(UmbrellaName); 15856c64013SDouglas Gregor 15956c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the 16056c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good 16156c64013SDouglas Gregor // idea. 16256c64013SDouglas Gregor if (!UmbrellaHeader) 16356c64013SDouglas Gregor return 0; 16456c64013SDouglas Gregor 16556c64013SDouglas Gregor Module *Result = new Module(ModuleName, SourceLocation()); 16656c64013SDouglas Gregor Result->UmbrellaHeader = UmbrellaHeader; 16756c64013SDouglas Gregor Headers[UmbrellaHeader] = Result; 16856c64013SDouglas Gregor UmbrellaDirs[FrameworkDir] = Result; 16956c64013SDouglas Gregor Modules[ModuleName] = Result; 17056c64013SDouglas Gregor return Result; 17156c64013SDouglas Gregor } 17256c64013SDouglas Gregor 173718292f2SDouglas Gregor static void indent(llvm::raw_ostream &OS, unsigned Spaces) { 174718292f2SDouglas Gregor OS << std::string(' ', Spaces); 175718292f2SDouglas Gregor } 176718292f2SDouglas Gregor 177718292f2SDouglas Gregor static void dumpModule(llvm::raw_ostream &OS, ModuleMap::Module *M, 178718292f2SDouglas Gregor unsigned Indent) { 179718292f2SDouglas Gregor indent(OS, Indent); 180718292f2SDouglas Gregor if (M->IsExplicit) 181718292f2SDouglas Gregor OS << "explicit "; 182718292f2SDouglas Gregor OS << M->Name << " {\n"; 183718292f2SDouglas Gregor 184718292f2SDouglas Gregor if (M->UmbrellaHeader) { 185718292f2SDouglas Gregor indent(OS, Indent + 2); 186718292f2SDouglas Gregor OS << "umbrella \"" << M->UmbrellaHeader->getName() << "\"\n"; 187718292f2SDouglas Gregor } 188718292f2SDouglas Gregor 189718292f2SDouglas Gregor for (unsigned I = 0, N = M->Headers.size(); I != N; ++I) { 190718292f2SDouglas Gregor indent(OS, Indent + 2); 191718292f2SDouglas Gregor OS << "header \"" << M->Headers[I]->getName() << "\"\n"; 192718292f2SDouglas Gregor } 193718292f2SDouglas Gregor 194718292f2SDouglas Gregor for (llvm::StringMap<ModuleMap::Module *>::iterator 195718292f2SDouglas Gregor MI = M->SubModules.begin(), 196718292f2SDouglas Gregor MIEnd = M->SubModules.end(); 197718292f2SDouglas Gregor MI != MIEnd; ++MI) 198718292f2SDouglas Gregor dumpModule(llvm::errs(), MI->getValue(), Indent + 2); 199718292f2SDouglas Gregor 200718292f2SDouglas Gregor indent(OS, Indent); 201718292f2SDouglas Gregor OS << "}\n"; 202718292f2SDouglas Gregor } 203718292f2SDouglas Gregor 204718292f2SDouglas Gregor void ModuleMap::dump() { 205718292f2SDouglas Gregor llvm::errs() << "Modules:"; 206718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 207718292f2SDouglas Gregor MEnd = Modules.end(); 208718292f2SDouglas Gregor M != MEnd; ++M) 209718292f2SDouglas Gregor dumpModule(llvm::errs(), M->getValue(), 2); 210718292f2SDouglas Gregor 211718292f2SDouglas Gregor llvm::errs() << "Headers:"; 212718292f2SDouglas Gregor for (llvm::DenseMap<const FileEntry *, Module *>::iterator 213718292f2SDouglas Gregor H = Headers.begin(), 214718292f2SDouglas Gregor HEnd = Headers.end(); 215718292f2SDouglas Gregor H != HEnd; ++H) { 216718292f2SDouglas Gregor llvm::errs() << " \"" << H->first->getName() << "\" -> " 217718292f2SDouglas Gregor << H->second->getFullModuleName() << "\n"; 218718292f2SDouglas Gregor } 219718292f2SDouglas Gregor } 220718292f2SDouglas Gregor 221718292f2SDouglas Gregor //----------------------------------------------------------------------------// 222718292f2SDouglas Gregor // Module map file parser 223718292f2SDouglas Gregor //----------------------------------------------------------------------------// 224718292f2SDouglas Gregor 225718292f2SDouglas Gregor namespace clang { 226718292f2SDouglas Gregor /// \brief A token in a module map file. 227718292f2SDouglas Gregor struct MMToken { 228718292f2SDouglas Gregor enum TokenKind { 229718292f2SDouglas Gregor EndOfFile, 230718292f2SDouglas Gregor HeaderKeyword, 231718292f2SDouglas Gregor Identifier, 232718292f2SDouglas Gregor ExplicitKeyword, 233718292f2SDouglas Gregor ModuleKeyword, 234718292f2SDouglas Gregor UmbrellaKeyword, 235718292f2SDouglas Gregor StringLiteral, 236718292f2SDouglas Gregor LBrace, 237718292f2SDouglas Gregor RBrace 238718292f2SDouglas Gregor } Kind; 239718292f2SDouglas Gregor 240718292f2SDouglas Gregor unsigned Location; 241718292f2SDouglas Gregor unsigned StringLength; 242718292f2SDouglas Gregor const char *StringData; 243718292f2SDouglas Gregor 244718292f2SDouglas Gregor void clear() { 245718292f2SDouglas Gregor Kind = EndOfFile; 246718292f2SDouglas Gregor Location = 0; 247718292f2SDouglas Gregor StringLength = 0; 248718292f2SDouglas Gregor StringData = 0; 249718292f2SDouglas Gregor } 250718292f2SDouglas Gregor 251718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 252718292f2SDouglas Gregor 253718292f2SDouglas Gregor SourceLocation getLocation() const { 254718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 255718292f2SDouglas Gregor } 256718292f2SDouglas Gregor 257718292f2SDouglas Gregor StringRef getString() const { 258718292f2SDouglas Gregor return StringRef(StringData, StringLength); 259718292f2SDouglas Gregor } 260718292f2SDouglas Gregor }; 261718292f2SDouglas Gregor 262718292f2SDouglas Gregor class ModuleMapParser { 263718292f2SDouglas Gregor Lexer &L; 264718292f2SDouglas Gregor SourceManager &SourceMgr; 265718292f2SDouglas Gregor DiagnosticsEngine &Diags; 266718292f2SDouglas Gregor ModuleMap ⤅ 267718292f2SDouglas Gregor 2685257fc63SDouglas Gregor /// \brief The directory that this module map resides in. 2695257fc63SDouglas Gregor const DirectoryEntry *Directory; 2705257fc63SDouglas Gregor 271718292f2SDouglas Gregor /// \brief Whether an error occurred. 272718292f2SDouglas Gregor bool HadError; 273718292f2SDouglas Gregor 274718292f2SDouglas Gregor /// \brief Default target information, used only for string literal 275718292f2SDouglas Gregor /// parsing. 276718292f2SDouglas Gregor TargetInfo *Target; 277718292f2SDouglas Gregor 278718292f2SDouglas Gregor /// \brief Stores string data for the various string literals referenced 279718292f2SDouglas Gregor /// during parsing. 280718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 281718292f2SDouglas Gregor 282718292f2SDouglas Gregor /// \brief The current token. 283718292f2SDouglas Gregor MMToken Tok; 284718292f2SDouglas Gregor 285718292f2SDouglas Gregor /// \brief The active module. 286718292f2SDouglas Gregor ModuleMap::Module *ActiveModule; 287718292f2SDouglas Gregor 288718292f2SDouglas Gregor /// \brief Consume the current token and return its location. 289718292f2SDouglas Gregor SourceLocation consumeToken(); 290718292f2SDouglas Gregor 291718292f2SDouglas Gregor /// \brief Skip tokens until we reach the a token with the given kind 292718292f2SDouglas Gregor /// (or the end of the file). 293718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 294718292f2SDouglas Gregor 295718292f2SDouglas Gregor void parseModuleDecl(); 296718292f2SDouglas Gregor void parseUmbrellaDecl(); 297718292f2SDouglas Gregor void parseHeaderDecl(); 298718292f2SDouglas Gregor 299718292f2SDouglas Gregor public: 300718292f2SDouglas Gregor typedef ModuleMap::Module Module; 301718292f2SDouglas Gregor 302718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 303718292f2SDouglas Gregor DiagnosticsEngine &Diags, 3045257fc63SDouglas Gregor ModuleMap &Map, 3055257fc63SDouglas Gregor const DirectoryEntry *Directory) 3065257fc63SDouglas Gregor : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map), 3075257fc63SDouglas Gregor Directory(Directory), HadError(false), ActiveModule(0) 308718292f2SDouglas Gregor { 309718292f2SDouglas Gregor TargetOptions TargetOpts; 310718292f2SDouglas Gregor TargetOpts.Triple = llvm::sys::getDefaultTargetTriple(); 311718292f2SDouglas Gregor Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); 312718292f2SDouglas Gregor 313718292f2SDouglas Gregor Tok.clear(); 314718292f2SDouglas Gregor consumeToken(); 315718292f2SDouglas Gregor } 316718292f2SDouglas Gregor 317718292f2SDouglas Gregor bool parseModuleMapFile(); 318718292f2SDouglas Gregor }; 319718292f2SDouglas Gregor } 320718292f2SDouglas Gregor 321718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 322718292f2SDouglas Gregor retry: 323718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 324718292f2SDouglas Gregor Tok.clear(); 325718292f2SDouglas Gregor 326718292f2SDouglas Gregor Token LToken; 327718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 328718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 329718292f2SDouglas Gregor switch (LToken.getKind()) { 330718292f2SDouglas Gregor case tok::raw_identifier: 331718292f2SDouglas Gregor Tok.StringData = LToken.getRawIdentifierData(); 332718292f2SDouglas Gregor Tok.StringLength = LToken.getLength(); 333718292f2SDouglas Gregor Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString()) 334718292f2SDouglas Gregor .Case("header", MMToken::HeaderKeyword) 335718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 336718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 337718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 338718292f2SDouglas Gregor .Default(MMToken::Identifier); 339718292f2SDouglas Gregor break; 340718292f2SDouglas Gregor 341718292f2SDouglas Gregor case tok::eof: 342718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 343718292f2SDouglas Gregor break; 344718292f2SDouglas Gregor 345718292f2SDouglas Gregor case tok::l_brace: 346718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 347718292f2SDouglas Gregor break; 348718292f2SDouglas Gregor 349718292f2SDouglas Gregor case tok::r_brace: 350718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 351718292f2SDouglas Gregor break; 352718292f2SDouglas Gregor 353718292f2SDouglas Gregor case tok::string_literal: { 354718292f2SDouglas Gregor // Parse the string literal. 355718292f2SDouglas Gregor LangOptions LangOpts; 356718292f2SDouglas Gregor StringLiteralParser StringLiteral(<oken, 1, SourceMgr, LangOpts, *Target); 357718292f2SDouglas Gregor if (StringLiteral.hadError) 358718292f2SDouglas Gregor goto retry; 359718292f2SDouglas Gregor 360718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 361718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 362718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 363718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 364718292f2SDouglas Gregor Saved[Length] = 0; 365718292f2SDouglas Gregor 366718292f2SDouglas Gregor // Form the token. 367718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 368718292f2SDouglas Gregor Tok.StringData = Saved; 369718292f2SDouglas Gregor Tok.StringLength = Length; 370718292f2SDouglas Gregor break; 371718292f2SDouglas Gregor } 372718292f2SDouglas Gregor 373718292f2SDouglas Gregor case tok::comment: 374718292f2SDouglas Gregor goto retry; 375718292f2SDouglas Gregor 376718292f2SDouglas Gregor default: 377718292f2SDouglas Gregor Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token); 378718292f2SDouglas Gregor HadError = true; 379718292f2SDouglas Gregor goto retry; 380718292f2SDouglas Gregor } 381718292f2SDouglas Gregor 382718292f2SDouglas Gregor return Result; 383718292f2SDouglas Gregor } 384718292f2SDouglas Gregor 385718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 386718292f2SDouglas Gregor unsigned braceDepth = 0; 387718292f2SDouglas Gregor do { 388718292f2SDouglas Gregor switch (Tok.Kind) { 389718292f2SDouglas Gregor case MMToken::EndOfFile: 390718292f2SDouglas Gregor return; 391718292f2SDouglas Gregor 392718292f2SDouglas Gregor case MMToken::LBrace: 393718292f2SDouglas Gregor if (Tok.is(K) && braceDepth == 0) 394718292f2SDouglas Gregor return; 395718292f2SDouglas Gregor 396718292f2SDouglas Gregor ++braceDepth; 397718292f2SDouglas Gregor break; 398718292f2SDouglas Gregor 399718292f2SDouglas Gregor case MMToken::RBrace: 400718292f2SDouglas Gregor if (braceDepth > 0) 401718292f2SDouglas Gregor --braceDepth; 402718292f2SDouglas Gregor else if (Tok.is(K)) 403718292f2SDouglas Gregor return; 404718292f2SDouglas Gregor break; 405718292f2SDouglas Gregor 406718292f2SDouglas Gregor default: 407718292f2SDouglas Gregor if (braceDepth == 0 && Tok.is(K)) 408718292f2SDouglas Gregor return; 409718292f2SDouglas Gregor break; 410718292f2SDouglas Gregor } 411718292f2SDouglas Gregor 412718292f2SDouglas Gregor consumeToken(); 413718292f2SDouglas Gregor } while (true); 414718292f2SDouglas Gregor } 415718292f2SDouglas Gregor 416718292f2SDouglas Gregor /// \brief Parse a module declaration. 417718292f2SDouglas Gregor /// 418718292f2SDouglas Gregor /// module-declaration: 419718292f2SDouglas Gregor /// 'module' identifier { module-member* } 420718292f2SDouglas Gregor /// 421718292f2SDouglas Gregor /// module-member: 422718292f2SDouglas Gregor /// umbrella-declaration 423718292f2SDouglas Gregor /// header-declaration 424718292f2SDouglas Gregor /// 'explicit'[opt] module-declaration 425718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 426718292f2SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword)); 427718292f2SDouglas Gregor 428718292f2SDouglas Gregor // Parse 'explicit' keyword, if present. 429718292f2SDouglas Gregor bool Explicit = false; 430718292f2SDouglas Gregor if (Tok.is(MMToken::ExplicitKeyword)) { 431718292f2SDouglas Gregor consumeToken(); 432718292f2SDouglas Gregor Explicit = true; 433718292f2SDouglas Gregor } 434718292f2SDouglas Gregor 435718292f2SDouglas Gregor // Parse 'module' keyword. 436718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 437718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), 438718292f2SDouglas Gregor diag::err_mmap_expected_module_after_explicit); 439718292f2SDouglas Gregor consumeToken(); 440718292f2SDouglas Gregor HadError = true; 441718292f2SDouglas Gregor return; 442718292f2SDouglas Gregor } 443718292f2SDouglas Gregor consumeToken(); // 'module' keyword 444718292f2SDouglas Gregor 445718292f2SDouglas Gregor // Parse the module name. 446718292f2SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 447718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 448718292f2SDouglas Gregor HadError = true; 449718292f2SDouglas Gregor return; 450718292f2SDouglas Gregor } 451718292f2SDouglas Gregor StringRef ModuleName = Tok.getString(); 452718292f2SDouglas Gregor SourceLocation ModuleNameLoc = consumeToken(); 453718292f2SDouglas Gregor 454718292f2SDouglas Gregor // Parse the opening brace. 455718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 456718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 457718292f2SDouglas Gregor << ModuleName; 458718292f2SDouglas Gregor HadError = true; 459718292f2SDouglas Gregor return; 460718292f2SDouglas Gregor } 461718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 462718292f2SDouglas Gregor 463718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 464718292f2SDouglas Gregor llvm::StringMap<Module *> &ModuleSpace 465718292f2SDouglas Gregor = ActiveModule? ActiveModule->SubModules : Map.Modules; 466718292f2SDouglas Gregor llvm::StringMap<Module *>::iterator ExistingModule 467718292f2SDouglas Gregor = ModuleSpace.find(ModuleName); 468718292f2SDouglas Gregor if (ExistingModule != ModuleSpace.end()) { 469718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 470718292f2SDouglas Gregor << ModuleName; 471718292f2SDouglas Gregor Diags.Report(ExistingModule->getValue()->DefinitionLoc, 472718292f2SDouglas Gregor diag::note_mmap_prev_definition); 473718292f2SDouglas Gregor 474718292f2SDouglas Gregor // Skip the module definition. 475718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 476718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 477718292f2SDouglas Gregor consumeToken(); 478718292f2SDouglas Gregor 479718292f2SDouglas Gregor HadError = true; 480718292f2SDouglas Gregor return; 481718292f2SDouglas Gregor } 482718292f2SDouglas Gregor 483718292f2SDouglas Gregor // Start defining this module. 484718292f2SDouglas Gregor ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Explicit); 485718292f2SDouglas Gregor ModuleSpace[ModuleName] = ActiveModule; 486718292f2SDouglas Gregor 487718292f2SDouglas Gregor bool Done = false; 488718292f2SDouglas Gregor do { 489718292f2SDouglas Gregor switch (Tok.Kind) { 490718292f2SDouglas Gregor case MMToken::EndOfFile: 491718292f2SDouglas Gregor case MMToken::RBrace: 492718292f2SDouglas Gregor Done = true; 493718292f2SDouglas Gregor break; 494718292f2SDouglas Gregor 495718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 496718292f2SDouglas Gregor case MMToken::ModuleKeyword: 497718292f2SDouglas Gregor parseModuleDecl(); 498718292f2SDouglas Gregor break; 499718292f2SDouglas Gregor 500718292f2SDouglas Gregor case MMToken::HeaderKeyword: 501718292f2SDouglas Gregor parseHeaderDecl(); 502718292f2SDouglas Gregor break; 503718292f2SDouglas Gregor 504718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 505718292f2SDouglas Gregor parseUmbrellaDecl(); 506718292f2SDouglas Gregor break; 507718292f2SDouglas Gregor 508718292f2SDouglas Gregor default: 509718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 510718292f2SDouglas Gregor consumeToken(); 511718292f2SDouglas Gregor break; 512718292f2SDouglas Gregor } 513718292f2SDouglas Gregor } while (!Done); 514718292f2SDouglas Gregor 515718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 516718292f2SDouglas Gregor consumeToken(); 517718292f2SDouglas Gregor else { 518718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 519718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 520718292f2SDouglas Gregor HadError = true; 521718292f2SDouglas Gregor } 522718292f2SDouglas Gregor 523718292f2SDouglas Gregor // We're done parsing this module. Pop back to our parent scope. 524718292f2SDouglas Gregor ActiveModule = ActiveModule->Parent; 525718292f2SDouglas Gregor } 526718292f2SDouglas Gregor 527718292f2SDouglas Gregor /// \brief Parse an umbrella header declaration. 528718292f2SDouglas Gregor /// 529718292f2SDouglas Gregor /// umbrella-declaration: 530718292f2SDouglas Gregor /// 'umbrella' string-literal 531718292f2SDouglas Gregor void ModuleMapParser::parseUmbrellaDecl() { 532718292f2SDouglas Gregor assert(Tok.is(MMToken::UmbrellaKeyword)); 533718292f2SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 534718292f2SDouglas Gregor 535718292f2SDouglas Gregor // Parse the header name. 536718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 537718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 538718292f2SDouglas Gregor << "umbrella"; 539718292f2SDouglas Gregor HadError = true; 540718292f2SDouglas Gregor return; 541718292f2SDouglas Gregor } 542718292f2SDouglas Gregor StringRef FileName = Tok.getString(); 543718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 544718292f2SDouglas Gregor 5455257fc63SDouglas Gregor // Check whether we already have an umbrella header. 5465257fc63SDouglas Gregor if (ActiveModule->UmbrellaHeader) { 5475257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict) 5485257fc63SDouglas Gregor << ActiveModule->getFullModuleName() 5495257fc63SDouglas Gregor << ActiveModule->UmbrellaHeader->getName(); 5505257fc63SDouglas Gregor HadError = true; 5515257fc63SDouglas Gregor return; 5525257fc63SDouglas Gregor } 5535257fc63SDouglas Gregor 5545257fc63SDouglas Gregor // Only top-level modules can have umbrella headers. 5555257fc63SDouglas Gregor if (ActiveModule->Parent) { 5565257fc63SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule) 5575257fc63SDouglas Gregor << ActiveModule->getFullModuleName(); 5585257fc63SDouglas Gregor HadError = true; 5595257fc63SDouglas Gregor return; 5605257fc63SDouglas Gregor } 5615257fc63SDouglas Gregor 5625257fc63SDouglas Gregor // Look for this file. 5635257fc63SDouglas Gregor llvm::SmallString<128> PathName; 5645257fc63SDouglas Gregor PathName += Directory->getName(); 5655257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 5665257fc63SDouglas Gregor 5675257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 5685257fc63SDouglas Gregor // Come up with a lazy way to do this. 5695257fc63SDouglas Gregor if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) { 5705257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 5715257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 5725257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 5735257fc63SDouglas Gregor HadError = true; 574b65dbfffSDouglas Gregor } else if ((OwningModule = Map.UmbrellaDirs[Directory])) { 575b65dbfffSDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 576b65dbfffSDouglas Gregor << OwningModule->getFullModuleName(); 577b65dbfffSDouglas Gregor HadError = true; 5785257fc63SDouglas Gregor } else { 5795257fc63SDouglas Gregor // Record this umbrella header. 5805257fc63SDouglas Gregor ActiveModule->UmbrellaHeader = File; 5815257fc63SDouglas Gregor Map.Headers[File] = ActiveModule; 582b65dbfffSDouglas Gregor Map.UmbrellaDirs[Directory] = ActiveModule; 5835257fc63SDouglas Gregor } 5845257fc63SDouglas Gregor } else { 5855257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 5865257fc63SDouglas Gregor << true << FileName; 5875257fc63SDouglas Gregor HadError = true; 5885257fc63SDouglas Gregor } 589718292f2SDouglas Gregor } 590718292f2SDouglas Gregor 591718292f2SDouglas Gregor /// \brief Parse a header declaration. 592718292f2SDouglas Gregor /// 593718292f2SDouglas Gregor /// header-declaration: 594718292f2SDouglas Gregor /// 'header' string-literal 595718292f2SDouglas Gregor void ModuleMapParser::parseHeaderDecl() { 596718292f2SDouglas Gregor assert(Tok.is(MMToken::HeaderKeyword)); 5971871ed3dSBenjamin Kramer consumeToken(); 598718292f2SDouglas Gregor 599718292f2SDouglas Gregor // Parse the header name. 600718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 601718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 602718292f2SDouglas Gregor << "header"; 603718292f2SDouglas Gregor HadError = true; 604718292f2SDouglas Gregor return; 605718292f2SDouglas Gregor } 606718292f2SDouglas Gregor StringRef FileName = Tok.getString(); 607718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 608718292f2SDouglas Gregor 6095257fc63SDouglas Gregor // Look for this file. 6105257fc63SDouglas Gregor llvm::SmallString<128> PathName; 6115257fc63SDouglas Gregor PathName += Directory->getName(); 6125257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 6135257fc63SDouglas Gregor 6145257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 6155257fc63SDouglas Gregor // Come up with a lazy way to do this. 6165257fc63SDouglas Gregor if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) { 6175257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 6185257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 6195257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 6205257fc63SDouglas Gregor HadError = true; 6215257fc63SDouglas Gregor } else { 6225257fc63SDouglas Gregor // Record this file. 6235257fc63SDouglas Gregor ActiveModule->Headers.push_back(File); 6245257fc63SDouglas Gregor Map.Headers[File] = ActiveModule; 6255257fc63SDouglas Gregor } 6265257fc63SDouglas Gregor } else { 6275257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 6285257fc63SDouglas Gregor << false << FileName; 6295257fc63SDouglas Gregor HadError = true; 6305257fc63SDouglas Gregor } 631718292f2SDouglas Gregor } 632718292f2SDouglas Gregor 633718292f2SDouglas Gregor /// \brief Parse a module map file. 634718292f2SDouglas Gregor /// 635718292f2SDouglas Gregor /// module-map-file: 636718292f2SDouglas Gregor /// module-declaration* 637718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 638718292f2SDouglas Gregor do { 639718292f2SDouglas Gregor switch (Tok.Kind) { 640718292f2SDouglas Gregor case MMToken::EndOfFile: 641718292f2SDouglas Gregor return HadError; 642718292f2SDouglas Gregor 643718292f2SDouglas Gregor case MMToken::ModuleKeyword: 644718292f2SDouglas Gregor parseModuleDecl(); 645718292f2SDouglas Gregor break; 646718292f2SDouglas Gregor 647718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 648718292f2SDouglas Gregor case MMToken::HeaderKeyword: 649718292f2SDouglas Gregor case MMToken::Identifier: 650718292f2SDouglas Gregor case MMToken::LBrace: 651718292f2SDouglas Gregor case MMToken::RBrace: 652718292f2SDouglas Gregor case MMToken::StringLiteral: 653718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 654718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 655718292f2SDouglas Gregor HadError = true; 656718292f2SDouglas Gregor consumeToken(); 657718292f2SDouglas Gregor break; 658718292f2SDouglas Gregor } 659718292f2SDouglas Gregor } while (true); 660718292f2SDouglas Gregor 661718292f2SDouglas Gregor return HadError; 662718292f2SDouglas Gregor } 663718292f2SDouglas Gregor 664718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) { 665718292f2SDouglas Gregor FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User); 666718292f2SDouglas Gregor const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID); 667718292f2SDouglas Gregor if (!Buffer) 668718292f2SDouglas Gregor return true; 669718292f2SDouglas Gregor 670718292f2SDouglas Gregor // Parse this module map file. 671718292f2SDouglas Gregor Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts); 672718292f2SDouglas Gregor Diags->getClient()->BeginSourceFile(LangOpts); 6735257fc63SDouglas Gregor ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir()); 674718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 675718292f2SDouglas Gregor Diags->getClient()->EndSourceFile(); 676718292f2SDouglas Gregor 677718292f2SDouglas Gregor return Result; 678718292f2SDouglas Gregor } 679