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 ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) { 31718292f2SDouglas Gregor llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs); 32718292f2SDouglas Gregor Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>( 33718292f2SDouglas Gregor new DiagnosticsEngine(DiagIDs)); 34718292f2SDouglas Gregor Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true); 35718292f2SDouglas Gregor SourceMgr = new SourceManager(*Diags, FileMgr); 36718292f2SDouglas Gregor } 37718292f2SDouglas Gregor 38718292f2SDouglas Gregor ModuleMap::~ModuleMap() { 395acdf59eSDouglas Gregor for (llvm::StringMap<Module *>::iterator I = Modules.begin(), 405acdf59eSDouglas Gregor IEnd = Modules.end(); 415acdf59eSDouglas Gregor I != IEnd; ++I) { 425acdf59eSDouglas Gregor delete I->getValue(); 435acdf59eSDouglas Gregor } 445acdf59eSDouglas Gregor 45718292f2SDouglas Gregor delete SourceMgr; 46718292f2SDouglas Gregor } 47718292f2SDouglas Gregor 48*de3ef502SDouglas Gregor Module *ModuleMap::findModuleForHeader(const FileEntry *File) { 49ab0c8a84SDouglas Gregor llvm::DenseMap<const FileEntry *, Module *>::iterator Known 50ab0c8a84SDouglas Gregor = Headers.find(File); 51ab0c8a84SDouglas Gregor if (Known != Headers.end()) 52ab0c8a84SDouglas Gregor return Known->second; 53ab0c8a84SDouglas Gregor 54b65dbfffSDouglas Gregor const DirectoryEntry *Dir = File->getDir(); 55b65dbfffSDouglas Gregor llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir 56b65dbfffSDouglas Gregor = UmbrellaDirs.find(Dir); 57b65dbfffSDouglas Gregor if (KnownDir != UmbrellaDirs.end()) 58b65dbfffSDouglas Gregor return KnownDir->second; 59b65dbfffSDouglas Gregor 60b65dbfffSDouglas Gregor // Walk up the directory hierarchy looking for umbrella headers. 61b65dbfffSDouglas Gregor llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs; 62b65dbfffSDouglas Gregor StringRef DirName = Dir->getName(); 63b65dbfffSDouglas Gregor do { 64b65dbfffSDouglas Gregor // Retrieve our parent path. 65b65dbfffSDouglas Gregor DirName = llvm::sys::path::parent_path(DirName); 66b65dbfffSDouglas Gregor if (DirName.empty()) 67b65dbfffSDouglas Gregor break; 68b65dbfffSDouglas Gregor 69b65dbfffSDouglas Gregor // Resolve the parent path to a directory entry. 70b65dbfffSDouglas Gregor Dir = SourceMgr->getFileManager().getDirectory(DirName); 71b65dbfffSDouglas Gregor if (!Dir) 72b65dbfffSDouglas Gregor break; 73b65dbfffSDouglas Gregor 74b65dbfffSDouglas Gregor KnownDir = UmbrellaDirs.find(Dir); 75b65dbfffSDouglas Gregor if (KnownDir != UmbrellaDirs.end()) { 76b65dbfffSDouglas Gregor Module *Result = KnownDir->second; 77b65dbfffSDouglas Gregor 78b65dbfffSDouglas Gregor // Record each of the directories we stepped through as being part of 79b65dbfffSDouglas Gregor // the module we found, since the umbrella header covers them all. 80b65dbfffSDouglas Gregor for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I) 81b65dbfffSDouglas Gregor UmbrellaDirs[SkippedDirs[I]] = Result; 82b65dbfffSDouglas Gregor 83b65dbfffSDouglas Gregor return Result; 84b65dbfffSDouglas Gregor } 85b65dbfffSDouglas Gregor 86b65dbfffSDouglas Gregor SkippedDirs.push_back(Dir); 87b65dbfffSDouglas Gregor } while (true); 88b65dbfffSDouglas Gregor 89ab0c8a84SDouglas Gregor return 0; 90ab0c8a84SDouglas Gregor } 91ab0c8a84SDouglas Gregor 92*de3ef502SDouglas Gregor Module *ModuleMap::findModule(StringRef Name) { 9388bdfb0eSDouglas Gregor llvm::StringMap<Module *>::iterator Known = Modules.find(Name); 9488bdfb0eSDouglas Gregor if (Known != Modules.end()) 9588bdfb0eSDouglas Gregor return Known->getValue(); 9688bdfb0eSDouglas Gregor 9788bdfb0eSDouglas Gregor return 0; 9888bdfb0eSDouglas Gregor } 9988bdfb0eSDouglas Gregor 100*de3ef502SDouglas Gregor std::pair<Module *, bool> 10169021974SDouglas Gregor ModuleMap::findOrCreateModule(StringRef Name, Module *Parent, bool IsFramework, 10269021974SDouglas Gregor bool IsExplicit) { 10369021974SDouglas Gregor // Try to find an existing module with this name. 10469021974SDouglas Gregor if (Module *Found = Parent? Parent->SubModules[Name] : Modules[Name]) 10569021974SDouglas Gregor return std::make_pair(Found, false); 10669021974SDouglas Gregor 10769021974SDouglas Gregor // Create a new module with this name. 10869021974SDouglas Gregor Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework, 10969021974SDouglas Gregor IsExplicit); 11069021974SDouglas Gregor if (Parent) 11169021974SDouglas Gregor Parent->SubModules[Name] = Result; 11269021974SDouglas Gregor else 11369021974SDouglas Gregor Modules[Name] = Result; 11469021974SDouglas Gregor return std::make_pair(Result, true); 11569021974SDouglas Gregor } 11669021974SDouglas Gregor 117*de3ef502SDouglas Gregor Module * 11856c64013SDouglas Gregor ModuleMap::inferFrameworkModule(StringRef ModuleName, 11956c64013SDouglas Gregor const DirectoryEntry *FrameworkDir) { 12056c64013SDouglas Gregor // Check whether we've already found this module. 12156c64013SDouglas Gregor if (Module *Module = findModule(ModuleName)) 12256c64013SDouglas Gregor return Module; 12356c64013SDouglas Gregor 12456c64013SDouglas Gregor // Look for an umbrella header. 12556c64013SDouglas Gregor llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 12656c64013SDouglas Gregor llvm::sys::path::append(UmbrellaName, "Headers"); 12756c64013SDouglas Gregor llvm::sys::path::append(UmbrellaName, ModuleName + ".h"); 12856c64013SDouglas Gregor const FileEntry *UmbrellaHeader 12956c64013SDouglas Gregor = SourceMgr->getFileManager().getFile(UmbrellaName); 13056c64013SDouglas Gregor 13156c64013SDouglas Gregor // FIXME: If there's no umbrella header, we could probably scan the 13256c64013SDouglas Gregor // framework to load *everything*. But, it's not clear that this is a good 13356c64013SDouglas Gregor // idea. 13456c64013SDouglas Gregor if (!UmbrellaHeader) 13556c64013SDouglas Gregor return 0; 13656c64013SDouglas Gregor 137755b2055SDouglas Gregor Module *Result = new Module(ModuleName, SourceLocation(), 138755b2055SDouglas Gregor /*IsFramework=*/true); 13956c64013SDouglas Gregor Result->UmbrellaHeader = UmbrellaHeader; 14056c64013SDouglas Gregor Headers[UmbrellaHeader] = Result; 14156c64013SDouglas Gregor UmbrellaDirs[FrameworkDir] = Result; 14256c64013SDouglas Gregor Modules[ModuleName] = Result; 14356c64013SDouglas Gregor return Result; 14456c64013SDouglas Gregor } 14556c64013SDouglas Gregor 146514b636aSDouglas Gregor const FileEntry * 147*de3ef502SDouglas Gregor ModuleMap::getContainingModuleMapFile(Module *Module) { 148514b636aSDouglas Gregor if (Module->DefinitionLoc.isInvalid() || !SourceMgr) 149514b636aSDouglas Gregor return 0; 150514b636aSDouglas Gregor 151514b636aSDouglas Gregor return SourceMgr->getFileEntryForID( 152514b636aSDouglas Gregor SourceMgr->getFileID(Module->DefinitionLoc)); 153514b636aSDouglas Gregor } 154514b636aSDouglas Gregor 155718292f2SDouglas Gregor void ModuleMap::dump() { 156718292f2SDouglas Gregor llvm::errs() << "Modules:"; 157718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 158718292f2SDouglas Gregor MEnd = Modules.end(); 159718292f2SDouglas Gregor M != MEnd; ++M) 160d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 161718292f2SDouglas Gregor 162718292f2SDouglas Gregor llvm::errs() << "Headers:"; 163718292f2SDouglas Gregor for (llvm::DenseMap<const FileEntry *, Module *>::iterator 164718292f2SDouglas Gregor H = Headers.begin(), 165718292f2SDouglas Gregor HEnd = Headers.end(); 166718292f2SDouglas Gregor H != HEnd; ++H) { 167718292f2SDouglas Gregor llvm::errs() << " \"" << H->first->getName() << "\" -> " 168718292f2SDouglas Gregor << H->second->getFullModuleName() << "\n"; 169718292f2SDouglas Gregor } 170718292f2SDouglas Gregor } 171718292f2SDouglas Gregor 172718292f2SDouglas Gregor //----------------------------------------------------------------------------// 173718292f2SDouglas Gregor // Module map file parser 174718292f2SDouglas Gregor //----------------------------------------------------------------------------// 175718292f2SDouglas Gregor 176718292f2SDouglas Gregor namespace clang { 177718292f2SDouglas Gregor /// \brief A token in a module map file. 178718292f2SDouglas Gregor struct MMToken { 179718292f2SDouglas Gregor enum TokenKind { 180718292f2SDouglas Gregor EndOfFile, 181718292f2SDouglas Gregor HeaderKeyword, 182718292f2SDouglas Gregor Identifier, 183718292f2SDouglas Gregor ExplicitKeyword, 184755b2055SDouglas Gregor FrameworkKeyword, 185718292f2SDouglas Gregor ModuleKeyword, 186718292f2SDouglas Gregor UmbrellaKeyword, 187718292f2SDouglas Gregor StringLiteral, 188718292f2SDouglas Gregor LBrace, 189718292f2SDouglas Gregor RBrace 190718292f2SDouglas Gregor } Kind; 191718292f2SDouglas Gregor 192718292f2SDouglas Gregor unsigned Location; 193718292f2SDouglas Gregor unsigned StringLength; 194718292f2SDouglas Gregor const char *StringData; 195718292f2SDouglas Gregor 196718292f2SDouglas Gregor void clear() { 197718292f2SDouglas Gregor Kind = EndOfFile; 198718292f2SDouglas Gregor Location = 0; 199718292f2SDouglas Gregor StringLength = 0; 200718292f2SDouglas Gregor StringData = 0; 201718292f2SDouglas Gregor } 202718292f2SDouglas Gregor 203718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 204718292f2SDouglas Gregor 205718292f2SDouglas Gregor SourceLocation getLocation() const { 206718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 207718292f2SDouglas Gregor } 208718292f2SDouglas Gregor 209718292f2SDouglas Gregor StringRef getString() const { 210718292f2SDouglas Gregor return StringRef(StringData, StringLength); 211718292f2SDouglas Gregor } 212718292f2SDouglas Gregor }; 213718292f2SDouglas Gregor 214718292f2SDouglas Gregor class ModuleMapParser { 215718292f2SDouglas Gregor Lexer &L; 216718292f2SDouglas Gregor SourceManager &SourceMgr; 217718292f2SDouglas Gregor DiagnosticsEngine &Diags; 218718292f2SDouglas Gregor ModuleMap ⤅ 219718292f2SDouglas Gregor 2205257fc63SDouglas Gregor /// \brief The directory that this module map resides in. 2215257fc63SDouglas Gregor const DirectoryEntry *Directory; 2225257fc63SDouglas Gregor 223718292f2SDouglas Gregor /// \brief Whether an error occurred. 224718292f2SDouglas Gregor bool HadError; 225718292f2SDouglas Gregor 226718292f2SDouglas Gregor /// \brief Default target information, used only for string literal 227718292f2SDouglas Gregor /// parsing. 228718292f2SDouglas Gregor TargetInfo *Target; 229718292f2SDouglas Gregor 230718292f2SDouglas Gregor /// \brief Stores string data for the various string literals referenced 231718292f2SDouglas Gregor /// during parsing. 232718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 233718292f2SDouglas Gregor 234718292f2SDouglas Gregor /// \brief The current token. 235718292f2SDouglas Gregor MMToken Tok; 236718292f2SDouglas Gregor 237718292f2SDouglas Gregor /// \brief The active module. 238*de3ef502SDouglas Gregor Module *ActiveModule; 239718292f2SDouglas Gregor 240718292f2SDouglas Gregor /// \brief Consume the current token and return its location. 241718292f2SDouglas Gregor SourceLocation consumeToken(); 242718292f2SDouglas Gregor 243718292f2SDouglas Gregor /// \brief Skip tokens until we reach the a token with the given kind 244718292f2SDouglas Gregor /// (or the end of the file). 245718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 246718292f2SDouglas Gregor 247718292f2SDouglas Gregor void parseModuleDecl(); 248718292f2SDouglas Gregor void parseUmbrellaDecl(); 249718292f2SDouglas Gregor void parseHeaderDecl(); 250718292f2SDouglas Gregor 251718292f2SDouglas Gregor public: 252*de3ef502SDouglas Gregor typedef Module Module; 253718292f2SDouglas Gregor 254718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 255718292f2SDouglas Gregor DiagnosticsEngine &Diags, 2565257fc63SDouglas Gregor ModuleMap &Map, 2575257fc63SDouglas Gregor const DirectoryEntry *Directory) 2585257fc63SDouglas Gregor : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map), 2595257fc63SDouglas Gregor Directory(Directory), HadError(false), ActiveModule(0) 260718292f2SDouglas Gregor { 261718292f2SDouglas Gregor TargetOptions TargetOpts; 262718292f2SDouglas Gregor TargetOpts.Triple = llvm::sys::getDefaultTargetTriple(); 263718292f2SDouglas Gregor Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); 264718292f2SDouglas Gregor 265718292f2SDouglas Gregor Tok.clear(); 266718292f2SDouglas Gregor consumeToken(); 267718292f2SDouglas Gregor } 268718292f2SDouglas Gregor 269718292f2SDouglas Gregor bool parseModuleMapFile(); 270718292f2SDouglas Gregor }; 271718292f2SDouglas Gregor } 272718292f2SDouglas Gregor 273718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 274718292f2SDouglas Gregor retry: 275718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 276718292f2SDouglas Gregor Tok.clear(); 277718292f2SDouglas Gregor 278718292f2SDouglas Gregor Token LToken; 279718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 280718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 281718292f2SDouglas Gregor switch (LToken.getKind()) { 282718292f2SDouglas Gregor case tok::raw_identifier: 283718292f2SDouglas Gregor Tok.StringData = LToken.getRawIdentifierData(); 284718292f2SDouglas Gregor Tok.StringLength = LToken.getLength(); 285718292f2SDouglas Gregor Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString()) 286718292f2SDouglas Gregor .Case("header", MMToken::HeaderKeyword) 287718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 288755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 289718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 290718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 291718292f2SDouglas Gregor .Default(MMToken::Identifier); 292718292f2SDouglas Gregor break; 293718292f2SDouglas Gregor 294718292f2SDouglas Gregor case tok::eof: 295718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 296718292f2SDouglas Gregor break; 297718292f2SDouglas Gregor 298718292f2SDouglas Gregor case tok::l_brace: 299718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 300718292f2SDouglas Gregor break; 301718292f2SDouglas Gregor 302718292f2SDouglas Gregor case tok::r_brace: 303718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 304718292f2SDouglas Gregor break; 305718292f2SDouglas Gregor 306718292f2SDouglas Gregor case tok::string_literal: { 307718292f2SDouglas Gregor // Parse the string literal. 308718292f2SDouglas Gregor LangOptions LangOpts; 309718292f2SDouglas Gregor StringLiteralParser StringLiteral(<oken, 1, SourceMgr, LangOpts, *Target); 310718292f2SDouglas Gregor if (StringLiteral.hadError) 311718292f2SDouglas Gregor goto retry; 312718292f2SDouglas Gregor 313718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 314718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 315718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 316718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 317718292f2SDouglas Gregor Saved[Length] = 0; 318718292f2SDouglas Gregor 319718292f2SDouglas Gregor // Form the token. 320718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 321718292f2SDouglas Gregor Tok.StringData = Saved; 322718292f2SDouglas Gregor Tok.StringLength = Length; 323718292f2SDouglas Gregor break; 324718292f2SDouglas Gregor } 325718292f2SDouglas Gregor 326718292f2SDouglas Gregor case tok::comment: 327718292f2SDouglas Gregor goto retry; 328718292f2SDouglas Gregor 329718292f2SDouglas Gregor default: 330718292f2SDouglas Gregor Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token); 331718292f2SDouglas Gregor HadError = true; 332718292f2SDouglas Gregor goto retry; 333718292f2SDouglas Gregor } 334718292f2SDouglas Gregor 335718292f2SDouglas Gregor return Result; 336718292f2SDouglas Gregor } 337718292f2SDouglas Gregor 338718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 339718292f2SDouglas Gregor unsigned braceDepth = 0; 340718292f2SDouglas Gregor do { 341718292f2SDouglas Gregor switch (Tok.Kind) { 342718292f2SDouglas Gregor case MMToken::EndOfFile: 343718292f2SDouglas Gregor return; 344718292f2SDouglas Gregor 345718292f2SDouglas Gregor case MMToken::LBrace: 346718292f2SDouglas Gregor if (Tok.is(K) && braceDepth == 0) 347718292f2SDouglas Gregor return; 348718292f2SDouglas Gregor 349718292f2SDouglas Gregor ++braceDepth; 350718292f2SDouglas Gregor break; 351718292f2SDouglas Gregor 352718292f2SDouglas Gregor case MMToken::RBrace: 353718292f2SDouglas Gregor if (braceDepth > 0) 354718292f2SDouglas Gregor --braceDepth; 355718292f2SDouglas Gregor else if (Tok.is(K)) 356718292f2SDouglas Gregor return; 357718292f2SDouglas Gregor break; 358718292f2SDouglas Gregor 359718292f2SDouglas Gregor default: 360718292f2SDouglas Gregor if (braceDepth == 0 && Tok.is(K)) 361718292f2SDouglas Gregor return; 362718292f2SDouglas Gregor break; 363718292f2SDouglas Gregor } 364718292f2SDouglas Gregor 365718292f2SDouglas Gregor consumeToken(); 366718292f2SDouglas Gregor } while (true); 367718292f2SDouglas Gregor } 368718292f2SDouglas Gregor 369718292f2SDouglas Gregor /// \brief Parse a module declaration. 370718292f2SDouglas Gregor /// 371718292f2SDouglas Gregor /// module-declaration: 372755b2055SDouglas Gregor /// 'framework'[opt] 'module' identifier { module-member* } 373718292f2SDouglas Gregor /// 374718292f2SDouglas Gregor /// module-member: 375718292f2SDouglas Gregor /// umbrella-declaration 376718292f2SDouglas Gregor /// header-declaration 377718292f2SDouglas Gregor /// 'explicit'[opt] module-declaration 378718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 379755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 380755b2055SDouglas Gregor Tok.is(MMToken::FrameworkKeyword)); 381718292f2SDouglas Gregor 382755b2055SDouglas Gregor // Parse 'framework' or 'explicit' keyword, if present. 383755b2055SDouglas Gregor bool Framework = false; 384718292f2SDouglas Gregor bool Explicit = false; 385755b2055SDouglas Gregor 386755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 387755b2055SDouglas Gregor consumeToken(); 388755b2055SDouglas Gregor Framework = true; 389755b2055SDouglas Gregor } 390755b2055SDouglas Gregor // Parse 'explicit' keyword, if present. 391755b2055SDouglas Gregor else if (Tok.is(MMToken::ExplicitKeyword)) { 392718292f2SDouglas Gregor consumeToken(); 393718292f2SDouglas Gregor Explicit = true; 394718292f2SDouglas Gregor } 395718292f2SDouglas Gregor 396718292f2SDouglas Gregor // Parse 'module' keyword. 397718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 398718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), 399718292f2SDouglas Gregor diag::err_mmap_expected_module_after_explicit); 400718292f2SDouglas Gregor consumeToken(); 401718292f2SDouglas Gregor HadError = true; 402718292f2SDouglas Gregor return; 403718292f2SDouglas Gregor } 404718292f2SDouglas Gregor consumeToken(); // 'module' keyword 405718292f2SDouglas Gregor 406718292f2SDouglas Gregor // Parse the module name. 407718292f2SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 408718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 409718292f2SDouglas Gregor HadError = true; 410718292f2SDouglas Gregor return; 411718292f2SDouglas Gregor } 412718292f2SDouglas Gregor StringRef ModuleName = Tok.getString(); 413718292f2SDouglas Gregor SourceLocation ModuleNameLoc = consumeToken(); 414718292f2SDouglas Gregor 415718292f2SDouglas Gregor // Parse the opening brace. 416718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 417718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 418718292f2SDouglas Gregor << ModuleName; 419718292f2SDouglas Gregor HadError = true; 420718292f2SDouglas Gregor return; 421718292f2SDouglas Gregor } 422718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 423718292f2SDouglas Gregor 424718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 425718292f2SDouglas Gregor llvm::StringMap<Module *> &ModuleSpace 426718292f2SDouglas Gregor = ActiveModule? ActiveModule->SubModules : Map.Modules; 427718292f2SDouglas Gregor llvm::StringMap<Module *>::iterator ExistingModule 428718292f2SDouglas Gregor = ModuleSpace.find(ModuleName); 429718292f2SDouglas Gregor if (ExistingModule != ModuleSpace.end()) { 430718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 431718292f2SDouglas Gregor << ModuleName; 432718292f2SDouglas Gregor Diags.Report(ExistingModule->getValue()->DefinitionLoc, 433718292f2SDouglas Gregor diag::note_mmap_prev_definition); 434718292f2SDouglas Gregor 435718292f2SDouglas Gregor // Skip the module definition. 436718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 437718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 438718292f2SDouglas Gregor consumeToken(); 439718292f2SDouglas Gregor 440718292f2SDouglas Gregor HadError = true; 441718292f2SDouglas Gregor return; 442718292f2SDouglas Gregor } 443718292f2SDouglas Gregor 444718292f2SDouglas Gregor // Start defining this module. 445755b2055SDouglas Gregor ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework, 446755b2055SDouglas Gregor Explicit); 447718292f2SDouglas Gregor ModuleSpace[ModuleName] = ActiveModule; 448718292f2SDouglas Gregor 449718292f2SDouglas Gregor bool Done = false; 450718292f2SDouglas Gregor do { 451718292f2SDouglas Gregor switch (Tok.Kind) { 452718292f2SDouglas Gregor case MMToken::EndOfFile: 453718292f2SDouglas Gregor case MMToken::RBrace: 454718292f2SDouglas Gregor Done = true; 455718292f2SDouglas Gregor break; 456718292f2SDouglas Gregor 457718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 458718292f2SDouglas Gregor case MMToken::ModuleKeyword: 459718292f2SDouglas Gregor parseModuleDecl(); 460718292f2SDouglas Gregor break; 461718292f2SDouglas Gregor 462718292f2SDouglas Gregor case MMToken::HeaderKeyword: 463718292f2SDouglas Gregor parseHeaderDecl(); 464718292f2SDouglas Gregor break; 465718292f2SDouglas Gregor 466718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 467718292f2SDouglas Gregor parseUmbrellaDecl(); 468718292f2SDouglas Gregor break; 469718292f2SDouglas Gregor 470718292f2SDouglas Gregor default: 471718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 472718292f2SDouglas Gregor consumeToken(); 473718292f2SDouglas Gregor break; 474718292f2SDouglas Gregor } 475718292f2SDouglas Gregor } while (!Done); 476718292f2SDouglas Gregor 477718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 478718292f2SDouglas Gregor consumeToken(); 479718292f2SDouglas Gregor else { 480718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 481718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 482718292f2SDouglas Gregor HadError = true; 483718292f2SDouglas Gregor } 484718292f2SDouglas Gregor 485718292f2SDouglas Gregor // We're done parsing this module. Pop back to our parent scope. 486718292f2SDouglas Gregor ActiveModule = ActiveModule->Parent; 487718292f2SDouglas Gregor } 488718292f2SDouglas Gregor 489718292f2SDouglas Gregor /// \brief Parse an umbrella header declaration. 490718292f2SDouglas Gregor /// 491718292f2SDouglas Gregor /// umbrella-declaration: 492718292f2SDouglas Gregor /// 'umbrella' string-literal 493718292f2SDouglas Gregor void ModuleMapParser::parseUmbrellaDecl() { 494718292f2SDouglas Gregor assert(Tok.is(MMToken::UmbrellaKeyword)); 495718292f2SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 496718292f2SDouglas Gregor 497718292f2SDouglas Gregor // Parse the header name. 498718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 499718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 500718292f2SDouglas Gregor << "umbrella"; 501718292f2SDouglas Gregor HadError = true; 502718292f2SDouglas Gregor return; 503718292f2SDouglas Gregor } 504718292f2SDouglas Gregor StringRef FileName = Tok.getString(); 505718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 506718292f2SDouglas Gregor 5075257fc63SDouglas Gregor // Check whether we already have an umbrella header. 5085257fc63SDouglas Gregor if (ActiveModule->UmbrellaHeader) { 5095257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict) 5105257fc63SDouglas Gregor << ActiveModule->getFullModuleName() 5115257fc63SDouglas Gregor << ActiveModule->UmbrellaHeader->getName(); 5125257fc63SDouglas Gregor HadError = true; 5135257fc63SDouglas Gregor return; 5145257fc63SDouglas Gregor } 5155257fc63SDouglas Gregor 5165257fc63SDouglas Gregor // Only top-level modules can have umbrella headers. 5175257fc63SDouglas Gregor if (ActiveModule->Parent) { 5185257fc63SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule) 5195257fc63SDouglas Gregor << ActiveModule->getFullModuleName(); 5205257fc63SDouglas Gregor HadError = true; 5215257fc63SDouglas Gregor return; 5225257fc63SDouglas Gregor } 5235257fc63SDouglas Gregor 5245257fc63SDouglas Gregor // Look for this file. 5255257fc63SDouglas Gregor llvm::SmallString<128> PathName; 526f545f67dSDouglas Gregor const FileEntry *File = 0; 527f545f67dSDouglas Gregor 528f545f67dSDouglas Gregor if (llvm::sys::path::is_absolute(FileName)) { 529f545f67dSDouglas Gregor PathName = FileName; 530f545f67dSDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 531f545f67dSDouglas Gregor } else { 532f545f67dSDouglas Gregor // Search for the header file within the search directory. 5335257fc63SDouglas Gregor PathName += Directory->getName(); 534755b2055SDouglas Gregor unsigned PathLength = PathName.size(); 535755b2055SDouglas Gregor if (ActiveModule->isPartOfFramework()) { 536755b2055SDouglas Gregor // Check whether this file is in the public headers. 537755b2055SDouglas Gregor llvm::sys::path::append(PathName, "Headers"); 5385257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 539755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 540755b2055SDouglas Gregor 541755b2055SDouglas Gregor if (!File) { 542755b2055SDouglas Gregor // Check whether this file is in the private headers. 543755b2055SDouglas Gregor PathName.resize(PathLength); 544755b2055SDouglas Gregor llvm::sys::path::append(PathName, "PrivateHeaders"); 545755b2055SDouglas Gregor llvm::sys::path::append(PathName, FileName); 546755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 547755b2055SDouglas Gregor } 548755b2055SDouglas Gregor 549755b2055SDouglas Gregor // FIXME: Deal with subframeworks. 550755b2055SDouglas Gregor } else { 551755b2055SDouglas Gregor // Lookup for normal headers. 552755b2055SDouglas Gregor llvm::sys::path::append(PathName, FileName); 553755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 554755b2055SDouglas Gregor } 555f545f67dSDouglas Gregor } 5565257fc63SDouglas Gregor 5575257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 5585257fc63SDouglas Gregor // Come up with a lazy way to do this. 559755b2055SDouglas Gregor if (File) { 5605257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 5615257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 5625257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 5635257fc63SDouglas Gregor HadError = true; 564b65dbfffSDouglas Gregor } else if ((OwningModule = Map.UmbrellaDirs[Directory])) { 565b65dbfffSDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 566b65dbfffSDouglas Gregor << OwningModule->getFullModuleName(); 567b65dbfffSDouglas Gregor HadError = true; 5685257fc63SDouglas Gregor } else { 5695257fc63SDouglas Gregor // Record this umbrella header. 5705257fc63SDouglas Gregor ActiveModule->UmbrellaHeader = File; 5715257fc63SDouglas Gregor Map.Headers[File] = ActiveModule; 572b65dbfffSDouglas Gregor Map.UmbrellaDirs[Directory] = ActiveModule; 5735257fc63SDouglas Gregor } 5745257fc63SDouglas Gregor } else { 5755257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 5765257fc63SDouglas Gregor << true << FileName; 5775257fc63SDouglas Gregor HadError = true; 5785257fc63SDouglas Gregor } 579718292f2SDouglas Gregor } 580718292f2SDouglas Gregor 581718292f2SDouglas Gregor /// \brief Parse a header declaration. 582718292f2SDouglas Gregor /// 583718292f2SDouglas Gregor /// header-declaration: 584718292f2SDouglas Gregor /// 'header' string-literal 585718292f2SDouglas Gregor void ModuleMapParser::parseHeaderDecl() { 586718292f2SDouglas Gregor assert(Tok.is(MMToken::HeaderKeyword)); 5871871ed3dSBenjamin Kramer consumeToken(); 588718292f2SDouglas Gregor 589718292f2SDouglas Gregor // Parse the header name. 590718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 591718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 592718292f2SDouglas Gregor << "header"; 593718292f2SDouglas Gregor HadError = true; 594718292f2SDouglas Gregor return; 595718292f2SDouglas Gregor } 596718292f2SDouglas Gregor StringRef FileName = Tok.getString(); 597718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 598718292f2SDouglas Gregor 5995257fc63SDouglas Gregor // Look for this file. 6005257fc63SDouglas Gregor llvm::SmallString<128> PathName; 601f545f67dSDouglas Gregor if (llvm::sys::path::is_relative(FileName)) { 602f545f67dSDouglas Gregor // FIXME: Change this search to also look for private headers! 6035257fc63SDouglas Gregor PathName += Directory->getName(); 604755b2055SDouglas Gregor 605755b2055SDouglas Gregor if (ActiveModule->isPartOfFramework()) 606755b2055SDouglas Gregor llvm::sys::path::append(PathName, "Headers"); 607f545f67dSDouglas Gregor } 608755b2055SDouglas Gregor 6095257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 6105257fc63SDouglas Gregor 6115257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 6125257fc63SDouglas Gregor // Come up with a lazy way to do this. 6135257fc63SDouglas Gregor if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) { 6145257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 6155257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 6165257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 6175257fc63SDouglas Gregor HadError = true; 6185257fc63SDouglas Gregor } else { 6195257fc63SDouglas Gregor // Record this file. 6205257fc63SDouglas Gregor ActiveModule->Headers.push_back(File); 6215257fc63SDouglas Gregor Map.Headers[File] = ActiveModule; 6225257fc63SDouglas Gregor } 6235257fc63SDouglas Gregor } else { 6245257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 6255257fc63SDouglas Gregor << false << FileName; 6265257fc63SDouglas Gregor HadError = true; 6275257fc63SDouglas Gregor } 628718292f2SDouglas Gregor } 629718292f2SDouglas Gregor 630718292f2SDouglas Gregor /// \brief Parse a module map file. 631718292f2SDouglas Gregor /// 632718292f2SDouglas Gregor /// module-map-file: 633718292f2SDouglas Gregor /// module-declaration* 634718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 635718292f2SDouglas Gregor do { 636718292f2SDouglas Gregor switch (Tok.Kind) { 637718292f2SDouglas Gregor case MMToken::EndOfFile: 638718292f2SDouglas Gregor return HadError; 639718292f2SDouglas Gregor 640718292f2SDouglas Gregor case MMToken::ModuleKeyword: 641755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 642718292f2SDouglas Gregor parseModuleDecl(); 643718292f2SDouglas Gregor break; 644718292f2SDouglas Gregor 645718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 646718292f2SDouglas Gregor case MMToken::HeaderKeyword: 647718292f2SDouglas Gregor case MMToken::Identifier: 648718292f2SDouglas Gregor case MMToken::LBrace: 649718292f2SDouglas Gregor case MMToken::RBrace: 650718292f2SDouglas Gregor case MMToken::StringLiteral: 651718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 652718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 653718292f2SDouglas Gregor HadError = true; 654718292f2SDouglas Gregor consumeToken(); 655718292f2SDouglas Gregor break; 656718292f2SDouglas Gregor } 657718292f2SDouglas Gregor } while (true); 658718292f2SDouglas Gregor 659718292f2SDouglas Gregor return HadError; 660718292f2SDouglas Gregor } 661718292f2SDouglas Gregor 662718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) { 663718292f2SDouglas Gregor FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User); 664718292f2SDouglas Gregor const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID); 665718292f2SDouglas Gregor if (!Buffer) 666718292f2SDouglas Gregor return true; 667718292f2SDouglas Gregor 668718292f2SDouglas Gregor // Parse this module map file. 669718292f2SDouglas Gregor Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts); 670718292f2SDouglas Gregor Diags->getClient()->BeginSourceFile(LangOpts); 6715257fc63SDouglas Gregor ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir()); 672718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 673718292f2SDouglas Gregor Diags->getClient()->EndSourceFile(); 674718292f2SDouglas Gregor 675718292f2SDouglas Gregor return Result; 676718292f2SDouglas Gregor } 677