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 345acdf59eSDouglas Gregor ModuleMap::Module::~Module() { 355acdf59eSDouglas Gregor for (llvm::StringMap<Module *>::iterator I = SubModules.begin(), 365acdf59eSDouglas Gregor IEnd = SubModules.end(); 375acdf59eSDouglas Gregor I != IEnd; ++I) { 385acdf59eSDouglas Gregor delete I->getValue(); 395acdf59eSDouglas Gregor } 405acdf59eSDouglas Gregor 415acdf59eSDouglas Gregor } 425acdf59eSDouglas 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 71*d28d1b8dSDouglas Gregor static void indent(llvm::raw_ostream &OS, unsigned Spaces) { 72*d28d1b8dSDouglas Gregor OS << std::string(' ', Spaces); 73*d28d1b8dSDouglas Gregor } 74*d28d1b8dSDouglas Gregor 75*d28d1b8dSDouglas Gregor void ModuleMap::Module::print(llvm::raw_ostream &OS, unsigned Indent) const { 76*d28d1b8dSDouglas Gregor indent(OS, Indent); 77*d28d1b8dSDouglas Gregor if (IsFramework) 78*d28d1b8dSDouglas Gregor OS << "framework "; 79*d28d1b8dSDouglas Gregor if (IsExplicit) 80*d28d1b8dSDouglas Gregor OS << "explicit "; 81*d28d1b8dSDouglas Gregor OS << Name << " {\n"; 82*d28d1b8dSDouglas Gregor 83*d28d1b8dSDouglas Gregor if (UmbrellaHeader) { 84*d28d1b8dSDouglas Gregor indent(OS, Indent + 2); 85*d28d1b8dSDouglas Gregor OS << "umbrella \"" << UmbrellaHeader->getName() << "\"\n"; 86*d28d1b8dSDouglas Gregor } 87*d28d1b8dSDouglas Gregor 88*d28d1b8dSDouglas Gregor for (unsigned I = 0, N = Headers.size(); I != N; ++I) { 89*d28d1b8dSDouglas Gregor indent(OS, Indent + 2); 90*d28d1b8dSDouglas Gregor OS << "header \"" << Headers[I]->getName() << "\"\n"; 91*d28d1b8dSDouglas Gregor } 92*d28d1b8dSDouglas Gregor 93*d28d1b8dSDouglas Gregor for (llvm::StringMap<Module *>::const_iterator MI = SubModules.begin(), 94*d28d1b8dSDouglas Gregor MIEnd = SubModules.end(); 95*d28d1b8dSDouglas Gregor MI != MIEnd; ++MI) 96*d28d1b8dSDouglas Gregor MI->getValue()->print(OS, Indent + 2); 97*d28d1b8dSDouglas Gregor 98*d28d1b8dSDouglas Gregor indent(OS, Indent); 99*d28d1b8dSDouglas Gregor OS << "}\n"; 100*d28d1b8dSDouglas Gregor } 101*d28d1b8dSDouglas Gregor 102*d28d1b8dSDouglas Gregor void ModuleMap::Module::dump() const { 103*d28d1b8dSDouglas Gregor print(llvm::errs()); 104*d28d1b8dSDouglas Gregor } 105*d28d1b8dSDouglas Gregor 106718292f2SDouglas Gregor //----------------------------------------------------------------------------// 107718292f2SDouglas Gregor // Module map 108718292f2SDouglas Gregor //----------------------------------------------------------------------------// 109718292f2SDouglas Gregor 110718292f2SDouglas Gregor ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) { 111718292f2SDouglas Gregor llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs); 112718292f2SDouglas Gregor Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>( 113718292f2SDouglas Gregor new DiagnosticsEngine(DiagIDs)); 114718292f2SDouglas Gregor Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true); 115718292f2SDouglas Gregor SourceMgr = new SourceManager(*Diags, FileMgr); 116718292f2SDouglas Gregor } 117718292f2SDouglas Gregor 118718292f2SDouglas Gregor ModuleMap::~ModuleMap() { 1195acdf59eSDouglas Gregor for (llvm::StringMap<Module *>::iterator I = Modules.begin(), 1205acdf59eSDouglas Gregor IEnd = Modules.end(); 1215acdf59eSDouglas Gregor I != IEnd; ++I) { 1225acdf59eSDouglas Gregor delete I->getValue(); 1235acdf59eSDouglas Gregor } 1245acdf59eSDouglas Gregor 125718292f2SDouglas Gregor delete SourceMgr; 126718292f2SDouglas Gregor } 127718292f2SDouglas Gregor 128ab0c8a84SDouglas Gregor ModuleMap::Module *ModuleMap::findModuleForHeader(const FileEntry *File) { 129ab0c8a84SDouglas Gregor llvm::DenseMap<const FileEntry *, Module *>::iterator Known 130ab0c8a84SDouglas Gregor = Headers.find(File); 131ab0c8a84SDouglas Gregor if (Known != Headers.end()) 132ab0c8a84SDouglas Gregor return Known->second; 133ab0c8a84SDouglas Gregor 134b65dbfffSDouglas Gregor const DirectoryEntry *Dir = File->getDir(); 135b65dbfffSDouglas Gregor llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir 136b65dbfffSDouglas Gregor = UmbrellaDirs.find(Dir); 137b65dbfffSDouglas Gregor if (KnownDir != UmbrellaDirs.end()) 138b65dbfffSDouglas Gregor return KnownDir->second; 139b65dbfffSDouglas Gregor 140b65dbfffSDouglas Gregor // Walk up the directory hierarchy looking for umbrella headers. 141b65dbfffSDouglas Gregor llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs; 142b65dbfffSDouglas Gregor StringRef DirName = Dir->getName(); 143b65dbfffSDouglas Gregor do { 144b65dbfffSDouglas Gregor // Retrieve our parent path. 145b65dbfffSDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 146b65dbfffSDouglas Gregor if (DirName.empty()) 147b65dbfffSDouglas Gregor break; 148b65dbfffSDouglas Gregor 149b65dbfffSDouglas Gregor // Resolve the parent path to a directory entry. 150b65dbfffSDouglas Gregor Dir = SourceMgr->getFileManager().getDirectory(DirName); 151b65dbfffSDouglas Gregor if (!Dir) 152b65dbfffSDouglas Gregor break; 153b65dbfffSDouglas Gregor 154b65dbfffSDouglas Gregor KnownDir = UmbrellaDirs.find(Dir); 155b65dbfffSDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 156b65dbfffSDouglas Gregor Module *Result = KnownDir->second; 157b65dbfffSDouglas Gregor 158b65dbfffSDouglas Gregor // Record each of the directories we stepped through as being part of 159b65dbfffSDouglas Gregor // the module we found, since the umbrella header covers them all. 160b65dbfffSDouglas Gregor for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I) 161b65dbfffSDouglas Gregor UmbrellaDirs[SkippedDirs[I]] = Result; 162b65dbfffSDouglas Gregor 163b65dbfffSDouglas Gregor return Result; 164b65dbfffSDouglas Gregor } 165b65dbfffSDouglas Gregor 166b65dbfffSDouglas Gregor SkippedDirs.push_back(Dir); 167b65dbfffSDouglas Gregor } while (true); 168b65dbfffSDouglas Gregor 169ab0c8a84SDouglas Gregor return 0; 170ab0c8a84SDouglas Gregor } 171ab0c8a84SDouglas Gregor 17288bdfb0eSDouglas Gregor ModuleMap::Module *ModuleMap::findModule(StringRef Name) { 17388bdfb0eSDouglas Gregor llvm::StringMap<Module *>::iterator Known = Modules.find(Name); 17488bdfb0eSDouglas Gregor if (Known != Modules.end()) 17588bdfb0eSDouglas Gregor return Known->getValue(); 17688bdfb0eSDouglas Gregor 17788bdfb0eSDouglas Gregor return 0; 17888bdfb0eSDouglas Gregor } 17988bdfb0eSDouglas Gregor 18056c64013SDouglas Gregor ModuleMap::Module * 18156c64013SDouglas Gregor ModuleMap::inferFrameworkModule(StringRef ModuleName, 18256c64013SDouglas Gregor const DirectoryEntry *FrameworkDir) { 18356c64013SDouglas Gregor // Check whether we've already found this module. 18456c64013SDouglas Gregor if (Module *Module = findModule(ModuleName)) 18556c64013SDouglas Gregor return Module; 18656c64013SDouglas Gregor 18756c64013SDouglas Gregor // Look for an umbrella header. 18856c64013SDouglas Gregor llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 18956c64013SDouglas Gregor llvm::sys::path::append(UmbrellaName, "Headers"); 19056c64013SDouglas Gregor llvm::sys::path::append(UmbrellaName, ModuleName + ".h"); 19156c64013SDouglas Gregor const FileEntry *UmbrellaHeader 19256c64013SDouglas Gregor = SourceMgr->getFileManager().getFile(UmbrellaName); 19356c64013SDouglas Gregor 19456c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the 19556c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good 19656c64013SDouglas Gregor // idea. 19756c64013SDouglas Gregor if (!UmbrellaHeader) 19856c64013SDouglas Gregor return 0; 19956c64013SDouglas Gregor 200755b2055SDouglas Gregor Module *Result = new Module(ModuleName, SourceLocation(), 201755b2055SDouglas Gregor /*IsFramework=*/true); 20256c64013SDouglas Gregor Result->UmbrellaHeader = UmbrellaHeader; 20356c64013SDouglas Gregor Headers[UmbrellaHeader] = Result; 20456c64013SDouglas Gregor UmbrellaDirs[FrameworkDir] = Result; 20556c64013SDouglas Gregor Modules[ModuleName] = Result; 20656c64013SDouglas Gregor return Result; 20756c64013SDouglas Gregor } 20856c64013SDouglas Gregor 209718292f2SDouglas Gregor void ModuleMap::dump() { 210718292f2SDouglas Gregor llvm::errs() << "Modules:"; 211718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 212718292f2SDouglas Gregor MEnd = Modules.end(); 213718292f2SDouglas Gregor M != MEnd; ++M) 214*d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 215718292f2SDouglas Gregor 216718292f2SDouglas Gregor llvm::errs() << "Headers:"; 217718292f2SDouglas Gregor for (llvm::DenseMap<const FileEntry *, Module *>::iterator 218718292f2SDouglas Gregor H = Headers.begin(), 219718292f2SDouglas Gregor HEnd = Headers.end(); 220718292f2SDouglas Gregor H != HEnd; ++H) { 221718292f2SDouglas Gregor llvm::errs() << " \"" << H->first->getName() << "\" -> " 222718292f2SDouglas Gregor << H->second->getFullModuleName() << "\n"; 223718292f2SDouglas Gregor } 224718292f2SDouglas Gregor } 225718292f2SDouglas Gregor 226718292f2SDouglas Gregor //----------------------------------------------------------------------------// 227718292f2SDouglas Gregor // Module map file parser 228718292f2SDouglas Gregor //----------------------------------------------------------------------------// 229718292f2SDouglas Gregor 230718292f2SDouglas Gregor namespace clang { 231718292f2SDouglas Gregor /// \brief A token in a module map file. 232718292f2SDouglas Gregor struct MMToken { 233718292f2SDouglas Gregor enum TokenKind { 234718292f2SDouglas Gregor EndOfFile, 235718292f2SDouglas Gregor HeaderKeyword, 236718292f2SDouglas Gregor Identifier, 237718292f2SDouglas Gregor ExplicitKeyword, 238755b2055SDouglas Gregor FrameworkKeyword, 239718292f2SDouglas Gregor ModuleKeyword, 240718292f2SDouglas Gregor UmbrellaKeyword, 241718292f2SDouglas Gregor StringLiteral, 242718292f2SDouglas Gregor LBrace, 243718292f2SDouglas Gregor RBrace 244718292f2SDouglas Gregor } Kind; 245718292f2SDouglas Gregor 246718292f2SDouglas Gregor unsigned Location; 247718292f2SDouglas Gregor unsigned StringLength; 248718292f2SDouglas Gregor const char *StringData; 249718292f2SDouglas Gregor 250718292f2SDouglas Gregor void clear() { 251718292f2SDouglas Gregor Kind = EndOfFile; 252718292f2SDouglas Gregor Location = 0; 253718292f2SDouglas Gregor StringLength = 0; 254718292f2SDouglas Gregor StringData = 0; 255718292f2SDouglas Gregor } 256718292f2SDouglas Gregor 257718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 258718292f2SDouglas Gregor 259718292f2SDouglas Gregor SourceLocation getLocation() const { 260718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 261718292f2SDouglas Gregor } 262718292f2SDouglas Gregor 263718292f2SDouglas Gregor StringRef getString() const { 264718292f2SDouglas Gregor return StringRef(StringData, StringLength); 265718292f2SDouglas Gregor } 266718292f2SDouglas Gregor }; 267718292f2SDouglas Gregor 268718292f2SDouglas Gregor class ModuleMapParser { 269718292f2SDouglas Gregor Lexer &L; 270718292f2SDouglas Gregor SourceManager &SourceMgr; 271718292f2SDouglas Gregor DiagnosticsEngine &Diags; 272718292f2SDouglas Gregor ModuleMap ⤅ 273718292f2SDouglas Gregor 2745257fc63SDouglas Gregor /// \brief The directory that this module map resides in. 2755257fc63SDouglas Gregor const DirectoryEntry *Directory; 2765257fc63SDouglas Gregor 277718292f2SDouglas Gregor /// \brief Whether an error occurred. 278718292f2SDouglas Gregor bool HadError; 279718292f2SDouglas Gregor 280718292f2SDouglas Gregor /// \brief Default target information, used only for string literal 281718292f2SDouglas Gregor /// parsing. 282718292f2SDouglas Gregor TargetInfo *Target; 283718292f2SDouglas Gregor 284718292f2SDouglas Gregor /// \brief Stores string data for the various string literals referenced 285718292f2SDouglas Gregor /// during parsing. 286718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 287718292f2SDouglas Gregor 288718292f2SDouglas Gregor /// \brief The current token. 289718292f2SDouglas Gregor MMToken Tok; 290718292f2SDouglas Gregor 291718292f2SDouglas Gregor /// \brief The active module. 292718292f2SDouglas Gregor ModuleMap::Module *ActiveModule; 293718292f2SDouglas Gregor 294718292f2SDouglas Gregor /// \brief Consume the current token and return its location. 295718292f2SDouglas Gregor SourceLocation consumeToken(); 296718292f2SDouglas Gregor 297718292f2SDouglas Gregor /// \brief Skip tokens until we reach the a token with the given kind 298718292f2SDouglas Gregor /// (or the end of the file). 299718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 300718292f2SDouglas Gregor 301718292f2SDouglas Gregor void parseModuleDecl(); 302718292f2SDouglas Gregor void parseUmbrellaDecl(); 303718292f2SDouglas Gregor void parseHeaderDecl(); 304718292f2SDouglas Gregor 305718292f2SDouglas Gregor public: 306718292f2SDouglas Gregor typedef ModuleMap::Module Module; 307718292f2SDouglas Gregor 308718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 309718292f2SDouglas Gregor DiagnosticsEngine &Diags, 3105257fc63SDouglas Gregor ModuleMap &Map, 3115257fc63SDouglas Gregor const DirectoryEntry *Directory) 3125257fc63SDouglas Gregor : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map), 3135257fc63SDouglas Gregor Directory(Directory), HadError(false), ActiveModule(0) 314718292f2SDouglas Gregor { 315718292f2SDouglas Gregor TargetOptions TargetOpts; 316718292f2SDouglas Gregor TargetOpts.Triple = llvm::sys::getDefaultTargetTriple(); 317718292f2SDouglas Gregor Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); 318718292f2SDouglas Gregor 319718292f2SDouglas Gregor Tok.clear(); 320718292f2SDouglas Gregor consumeToken(); 321718292f2SDouglas Gregor } 322718292f2SDouglas Gregor 323718292f2SDouglas Gregor bool parseModuleMapFile(); 324718292f2SDouglas Gregor }; 325718292f2SDouglas Gregor } 326718292f2SDouglas Gregor 327718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 328718292f2SDouglas Gregor retry: 329718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 330718292f2SDouglas Gregor Tok.clear(); 331718292f2SDouglas Gregor 332718292f2SDouglas Gregor Token LToken; 333718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 334718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 335718292f2SDouglas Gregor switch (LToken.getKind()) { 336718292f2SDouglas Gregor case tok::raw_identifier: 337718292f2SDouglas Gregor Tok.StringData = LToken.getRawIdentifierData(); 338718292f2SDouglas Gregor Tok.StringLength = LToken.getLength(); 339718292f2SDouglas Gregor Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString()) 340718292f2SDouglas Gregor .Case("header", MMToken::HeaderKeyword) 341718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 342755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 343718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 344718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 345718292f2SDouglas Gregor .Default(MMToken::Identifier); 346718292f2SDouglas Gregor break; 347718292f2SDouglas Gregor 348718292f2SDouglas Gregor case tok::eof: 349718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 350718292f2SDouglas Gregor break; 351718292f2SDouglas Gregor 352718292f2SDouglas Gregor case tok::l_brace: 353718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 354718292f2SDouglas Gregor break; 355718292f2SDouglas Gregor 356718292f2SDouglas Gregor case tok::r_brace: 357718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 358718292f2SDouglas Gregor break; 359718292f2SDouglas Gregor 360718292f2SDouglas Gregor case tok::string_literal: { 361718292f2SDouglas Gregor // Parse the string literal. 362718292f2SDouglas Gregor LangOptions LangOpts; 363718292f2SDouglas Gregor StringLiteralParser StringLiteral(<oken, 1, SourceMgr, LangOpts, *Target); 364718292f2SDouglas Gregor if (StringLiteral.hadError) 365718292f2SDouglas Gregor goto retry; 366718292f2SDouglas Gregor 367718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 368718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 369718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 370718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 371718292f2SDouglas Gregor Saved[Length] = 0; 372718292f2SDouglas Gregor 373718292f2SDouglas Gregor // Form the token. 374718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 375718292f2SDouglas Gregor Tok.StringData = Saved; 376718292f2SDouglas Gregor Tok.StringLength = Length; 377718292f2SDouglas Gregor break; 378718292f2SDouglas Gregor } 379718292f2SDouglas Gregor 380718292f2SDouglas Gregor case tok::comment: 381718292f2SDouglas Gregor goto retry; 382718292f2SDouglas Gregor 383718292f2SDouglas Gregor default: 384718292f2SDouglas Gregor Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token); 385718292f2SDouglas Gregor HadError = true; 386718292f2SDouglas Gregor goto retry; 387718292f2SDouglas Gregor } 388718292f2SDouglas Gregor 389718292f2SDouglas Gregor return Result; 390718292f2SDouglas Gregor } 391718292f2SDouglas Gregor 392718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 393718292f2SDouglas Gregor unsigned braceDepth = 0; 394718292f2SDouglas Gregor do { 395718292f2SDouglas Gregor switch (Tok.Kind) { 396718292f2SDouglas Gregor case MMToken::EndOfFile: 397718292f2SDouglas Gregor return; 398718292f2SDouglas Gregor 399718292f2SDouglas Gregor case MMToken::LBrace: 400718292f2SDouglas Gregor if (Tok.is(K) && braceDepth == 0) 401718292f2SDouglas Gregor return; 402718292f2SDouglas Gregor 403718292f2SDouglas Gregor ++braceDepth; 404718292f2SDouglas Gregor break; 405718292f2SDouglas Gregor 406718292f2SDouglas Gregor case MMToken::RBrace: 407718292f2SDouglas Gregor if (braceDepth > 0) 408718292f2SDouglas Gregor --braceDepth; 409718292f2SDouglas Gregor else if (Tok.is(K)) 410718292f2SDouglas Gregor return; 411718292f2SDouglas Gregor break; 412718292f2SDouglas Gregor 413718292f2SDouglas Gregor default: 414718292f2SDouglas Gregor if (braceDepth == 0 && Tok.is(K)) 415718292f2SDouglas Gregor return; 416718292f2SDouglas Gregor break; 417718292f2SDouglas Gregor } 418718292f2SDouglas Gregor 419718292f2SDouglas Gregor consumeToken(); 420718292f2SDouglas Gregor } while (true); 421718292f2SDouglas Gregor } 422718292f2SDouglas Gregor 423718292f2SDouglas Gregor /// \brief Parse a module declaration. 424718292f2SDouglas Gregor /// 425718292f2SDouglas Gregor /// module-declaration: 426755b2055SDouglas Gregor /// 'framework'[opt] 'module' identifier { module-member* } 427718292f2SDouglas Gregor /// 428718292f2SDouglas Gregor /// module-member: 429718292f2SDouglas Gregor /// umbrella-declaration 430718292f2SDouglas Gregor /// header-declaration 431718292f2SDouglas Gregor /// 'explicit'[opt] module-declaration 432718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 433755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 434755b2055SDouglas Gregor Tok.is(MMToken::FrameworkKeyword)); 435718292f2SDouglas Gregor 436755b2055SDouglas Gregor // Parse 'framework' or 'explicit' keyword, if present. 437755b2055SDouglas Gregor bool Framework = false; 438718292f2SDouglas Gregor bool Explicit = false; 439755b2055SDouglas Gregor 440755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 441755b2055SDouglas Gregor consumeToken(); 442755b2055SDouglas Gregor Framework = true; 443755b2055SDouglas Gregor } 444755b2055SDouglas Gregor // Parse 'explicit' keyword, if present. 445755b2055SDouglas Gregor else if (Tok.is(MMToken::ExplicitKeyword)) { 446718292f2SDouglas Gregor consumeToken(); 447718292f2SDouglas Gregor Explicit = true; 448718292f2SDouglas Gregor } 449718292f2SDouglas Gregor 450718292f2SDouglas Gregor // Parse 'module' keyword. 451718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 452718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), 453718292f2SDouglas Gregor diag::err_mmap_expected_module_after_explicit); 454718292f2SDouglas Gregor consumeToken(); 455718292f2SDouglas Gregor HadError = true; 456718292f2SDouglas Gregor return; 457718292f2SDouglas Gregor } 458718292f2SDouglas Gregor consumeToken(); // 'module' keyword 459718292f2SDouglas Gregor 460718292f2SDouglas Gregor // Parse the module name. 461718292f2SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 462718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 463718292f2SDouglas Gregor HadError = true; 464718292f2SDouglas Gregor return; 465718292f2SDouglas Gregor } 466718292f2SDouglas Gregor StringRef ModuleName = Tok.getString(); 467718292f2SDouglas Gregor SourceLocation ModuleNameLoc = consumeToken(); 468718292f2SDouglas Gregor 469718292f2SDouglas Gregor // Parse the opening brace. 470718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 471718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 472718292f2SDouglas Gregor << ModuleName; 473718292f2SDouglas Gregor HadError = true; 474718292f2SDouglas Gregor return; 475718292f2SDouglas Gregor } 476718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 477718292f2SDouglas Gregor 478718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 479718292f2SDouglas Gregor llvm::StringMap<Module *> &ModuleSpace 480718292f2SDouglas Gregor = ActiveModule? ActiveModule->SubModules : Map.Modules; 481718292f2SDouglas Gregor llvm::StringMap<Module *>::iterator ExistingModule 482718292f2SDouglas Gregor = ModuleSpace.find(ModuleName); 483718292f2SDouglas Gregor if (ExistingModule != ModuleSpace.end()) { 484718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 485718292f2SDouglas Gregor << ModuleName; 486718292f2SDouglas Gregor Diags.Report(ExistingModule->getValue()->DefinitionLoc, 487718292f2SDouglas Gregor diag::note_mmap_prev_definition); 488718292f2SDouglas Gregor 489718292f2SDouglas Gregor // Skip the module definition. 490718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 491718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 492718292f2SDouglas Gregor consumeToken(); 493718292f2SDouglas Gregor 494718292f2SDouglas Gregor HadError = true; 495718292f2SDouglas Gregor return; 496718292f2SDouglas Gregor } 497718292f2SDouglas Gregor 498718292f2SDouglas Gregor // Start defining this module. 499755b2055SDouglas Gregor ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework, 500755b2055SDouglas Gregor Explicit); 501718292f2SDouglas Gregor ModuleSpace[ModuleName] = ActiveModule; 502718292f2SDouglas Gregor 503718292f2SDouglas Gregor bool Done = false; 504718292f2SDouglas Gregor do { 505718292f2SDouglas Gregor switch (Tok.Kind) { 506718292f2SDouglas Gregor case MMToken::EndOfFile: 507718292f2SDouglas Gregor case MMToken::RBrace: 508718292f2SDouglas Gregor Done = true; 509718292f2SDouglas Gregor break; 510718292f2SDouglas Gregor 511718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 512718292f2SDouglas Gregor case MMToken::ModuleKeyword: 513718292f2SDouglas Gregor parseModuleDecl(); 514718292f2SDouglas Gregor break; 515718292f2SDouglas Gregor 516718292f2SDouglas Gregor case MMToken::HeaderKeyword: 517718292f2SDouglas Gregor parseHeaderDecl(); 518718292f2SDouglas Gregor break; 519718292f2SDouglas Gregor 520718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 521718292f2SDouglas Gregor parseUmbrellaDecl(); 522718292f2SDouglas Gregor break; 523718292f2SDouglas Gregor 524718292f2SDouglas Gregor default: 525718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 526718292f2SDouglas Gregor consumeToken(); 527718292f2SDouglas Gregor break; 528718292f2SDouglas Gregor } 529718292f2SDouglas Gregor } while (!Done); 530718292f2SDouglas Gregor 531718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 532718292f2SDouglas Gregor consumeToken(); 533718292f2SDouglas Gregor else { 534718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 535718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 536718292f2SDouglas Gregor HadError = true; 537718292f2SDouglas Gregor } 538718292f2SDouglas Gregor 539718292f2SDouglas Gregor // We're done parsing this module. Pop back to our parent scope. 540718292f2SDouglas Gregor ActiveModule = ActiveModule->Parent; 541718292f2SDouglas Gregor } 542718292f2SDouglas Gregor 543718292f2SDouglas Gregor /// \brief Parse an umbrella header declaration. 544718292f2SDouglas Gregor /// 545718292f2SDouglas Gregor /// umbrella-declaration: 546718292f2SDouglas Gregor /// 'umbrella' string-literal 547718292f2SDouglas Gregor void ModuleMapParser::parseUmbrellaDecl() { 548718292f2SDouglas Gregor assert(Tok.is(MMToken::UmbrellaKeyword)); 549718292f2SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 550718292f2SDouglas Gregor 551718292f2SDouglas Gregor // Parse the header name. 552718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 553718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 554718292f2SDouglas Gregor << "umbrella"; 555718292f2SDouglas Gregor HadError = true; 556718292f2SDouglas Gregor return; 557718292f2SDouglas Gregor } 558718292f2SDouglas Gregor StringRef FileName = Tok.getString(); 559718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 560718292f2SDouglas Gregor 5615257fc63SDouglas Gregor // Check whether we already have an umbrella header. 5625257fc63SDouglas Gregor if (ActiveModule->UmbrellaHeader) { 5635257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict) 5645257fc63SDouglas Gregor << ActiveModule->getFullModuleName() 5655257fc63SDouglas Gregor << ActiveModule->UmbrellaHeader->getName(); 5665257fc63SDouglas Gregor HadError = true; 5675257fc63SDouglas Gregor return; 5685257fc63SDouglas Gregor } 5695257fc63SDouglas Gregor 5705257fc63SDouglas Gregor // Only top-level modules can have umbrella headers. 5715257fc63SDouglas Gregor if (ActiveModule->Parent) { 5725257fc63SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule) 5735257fc63SDouglas Gregor << ActiveModule->getFullModuleName(); 5745257fc63SDouglas Gregor HadError = true; 5755257fc63SDouglas Gregor return; 5765257fc63SDouglas Gregor } 5775257fc63SDouglas Gregor 5785257fc63SDouglas Gregor // Look for this file. 5795257fc63SDouglas Gregor llvm::SmallString<128> PathName; 5805257fc63SDouglas Gregor PathName += Directory->getName(); 581755b2055SDouglas Gregor unsigned PathLength = PathName.size(); 582755b2055SDouglas Gregor const FileEntry *File = 0; 583755b2055SDouglas Gregor if (ActiveModule->isPartOfFramework()) { 584755b2055SDouglas Gregor // Check whether this file is in the public headers. 585755b2055SDouglas Gregor llvm::sys::path::append(PathName, "Headers"); 5865257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 587755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 588755b2055SDouglas Gregor 589755b2055SDouglas Gregor if (!File) { 590755b2055SDouglas Gregor // Check whether this file is in the private headers. 591755b2055SDouglas Gregor PathName.resize(PathLength); 592755b2055SDouglas Gregor llvm::sys::path::append(PathName, "PrivateHeaders"); 593755b2055SDouglas Gregor llvm::sys::path::append(PathName, FileName); 594755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 595755b2055SDouglas Gregor } 596755b2055SDouglas Gregor 597755b2055SDouglas Gregor // FIXME: Deal with subframeworks. 598755b2055SDouglas Gregor } else { 599755b2055SDouglas Gregor // Lookup for normal headers. 600755b2055SDouglas Gregor llvm::sys::path::append(PathName, FileName); 601755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 602755b2055SDouglas Gregor } 6035257fc63SDouglas Gregor 6045257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 6055257fc63SDouglas Gregor // Come up with a lazy way to do this. 606755b2055SDouglas Gregor if (File) { 6075257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 6085257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 6095257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 6105257fc63SDouglas Gregor HadError = true; 611b65dbfffSDouglas Gregor } else if ((OwningModule = Map.UmbrellaDirs[Directory])) { 612b65dbfffSDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 613b65dbfffSDouglas Gregor << OwningModule->getFullModuleName(); 614b65dbfffSDouglas Gregor HadError = true; 6155257fc63SDouglas Gregor } else { 6165257fc63SDouglas Gregor // Record this umbrella header. 6175257fc63SDouglas Gregor ActiveModule->UmbrellaHeader = File; 6185257fc63SDouglas Gregor Map.Headers[File] = ActiveModule; 619b65dbfffSDouglas Gregor Map.UmbrellaDirs[Directory] = ActiveModule; 6205257fc63SDouglas Gregor } 6215257fc63SDouglas Gregor } else { 6225257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 6235257fc63SDouglas Gregor << true << FileName; 6245257fc63SDouglas Gregor HadError = true; 6255257fc63SDouglas Gregor } 626718292f2SDouglas Gregor } 627718292f2SDouglas Gregor 628718292f2SDouglas Gregor /// \brief Parse a header declaration. 629718292f2SDouglas Gregor /// 630718292f2SDouglas Gregor /// header-declaration: 631718292f2SDouglas Gregor /// 'header' string-literal 632718292f2SDouglas Gregor void ModuleMapParser::parseHeaderDecl() { 633718292f2SDouglas Gregor assert(Tok.is(MMToken::HeaderKeyword)); 6341871ed3dSBenjamin Kramer consumeToken(); 635718292f2SDouglas Gregor 636718292f2SDouglas Gregor // Parse the header name. 637718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 638718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 639718292f2SDouglas Gregor << "header"; 640718292f2SDouglas Gregor HadError = true; 641718292f2SDouglas Gregor return; 642718292f2SDouglas Gregor } 643718292f2SDouglas Gregor StringRef FileName = Tok.getString(); 644718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 645718292f2SDouglas Gregor 6465257fc63SDouglas Gregor // Look for this file. 6475257fc63SDouglas Gregor llvm::SmallString<128> PathName; 6485257fc63SDouglas Gregor PathName += Directory->getName(); 649755b2055SDouglas Gregor 650755b2055SDouglas Gregor if (ActiveModule->isPartOfFramework()) 651755b2055SDouglas Gregor llvm::sys::path::append(PathName, "Headers"); 652755b2055SDouglas Gregor 6535257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 6545257fc63SDouglas Gregor 6555257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 6565257fc63SDouglas Gregor // Come up with a lazy way to do this. 6575257fc63SDouglas Gregor if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) { 6585257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 6595257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 6605257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 6615257fc63SDouglas Gregor HadError = true; 6625257fc63SDouglas Gregor } else { 6635257fc63SDouglas Gregor // Record this file. 6645257fc63SDouglas Gregor ActiveModule->Headers.push_back(File); 6655257fc63SDouglas Gregor Map.Headers[File] = ActiveModule; 6665257fc63SDouglas Gregor } 6675257fc63SDouglas Gregor } else { 6685257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 6695257fc63SDouglas Gregor << false << FileName; 6705257fc63SDouglas Gregor HadError = true; 6715257fc63SDouglas Gregor } 672718292f2SDouglas Gregor } 673718292f2SDouglas Gregor 674718292f2SDouglas Gregor /// \brief Parse a module map file. 675718292f2SDouglas Gregor /// 676718292f2SDouglas Gregor /// module-map-file: 677718292f2SDouglas Gregor /// module-declaration* 678718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 679718292f2SDouglas Gregor do { 680718292f2SDouglas Gregor switch (Tok.Kind) { 681718292f2SDouglas Gregor case MMToken::EndOfFile: 682718292f2SDouglas Gregor return HadError; 683718292f2SDouglas Gregor 684718292f2SDouglas Gregor case MMToken::ModuleKeyword: 685755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 686718292f2SDouglas Gregor parseModuleDecl(); 687718292f2SDouglas Gregor break; 688718292f2SDouglas Gregor 689718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 690718292f2SDouglas Gregor case MMToken::HeaderKeyword: 691718292f2SDouglas Gregor case MMToken::Identifier: 692718292f2SDouglas Gregor case MMToken::LBrace: 693718292f2SDouglas Gregor case MMToken::RBrace: 694718292f2SDouglas Gregor case MMToken::StringLiteral: 695718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 696718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 697718292f2SDouglas Gregor HadError = true; 698718292f2SDouglas Gregor consumeToken(); 699718292f2SDouglas Gregor break; 700718292f2SDouglas Gregor } 701718292f2SDouglas Gregor } while (true); 702718292f2SDouglas Gregor 703718292f2SDouglas Gregor return HadError; 704718292f2SDouglas Gregor } 705718292f2SDouglas Gregor 706718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) { 707718292f2SDouglas Gregor FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User); 708718292f2SDouglas Gregor const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID); 709718292f2SDouglas Gregor if (!Buffer) 710718292f2SDouglas Gregor return true; 711718292f2SDouglas Gregor 712718292f2SDouglas Gregor // Parse this module map file. 713718292f2SDouglas Gregor Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts); 714718292f2SDouglas Gregor Diags->getClient()->BeginSourceFile(LangOpts); 7155257fc63SDouglas Gregor ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir()); 716718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 717718292f2SDouglas Gregor Diags->getClient()->EndSourceFile(); 718718292f2SDouglas Gregor 719718292f2SDouglas Gregor return Result; 720718292f2SDouglas Gregor } 721