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 71d28d1b8dSDouglas Gregor static void indent(llvm::raw_ostream &OS, unsigned Spaces) { 72d28d1b8dSDouglas Gregor OS << std::string(' ', Spaces); 73d28d1b8dSDouglas Gregor } 74d28d1b8dSDouglas Gregor 75d28d1b8dSDouglas Gregor void ModuleMap::Module::print(llvm::raw_ostream &OS, unsigned Indent) const { 76d28d1b8dSDouglas Gregor indent(OS, Indent); 77d28d1b8dSDouglas Gregor if (IsFramework) 78d28d1b8dSDouglas Gregor OS << "framework "; 79d28d1b8dSDouglas Gregor if (IsExplicit) 80d28d1b8dSDouglas Gregor OS << "explicit "; 81d28d1b8dSDouglas Gregor OS << Name << " {\n"; 82d28d1b8dSDouglas Gregor 83d28d1b8dSDouglas Gregor if (UmbrellaHeader) { 84d28d1b8dSDouglas Gregor indent(OS, Indent + 2); 85d28d1b8dSDouglas Gregor OS << "umbrella \"" << UmbrellaHeader->getName() << "\"\n"; 86d28d1b8dSDouglas Gregor } 87d28d1b8dSDouglas Gregor 88d28d1b8dSDouglas Gregor for (unsigned I = 0, N = Headers.size(); I != N; ++I) { 89d28d1b8dSDouglas Gregor indent(OS, Indent + 2); 90d28d1b8dSDouglas Gregor OS << "header \"" << Headers[I]->getName() << "\"\n"; 91d28d1b8dSDouglas Gregor } 92d28d1b8dSDouglas Gregor 93d28d1b8dSDouglas Gregor for (llvm::StringMap<Module *>::const_iterator MI = SubModules.begin(), 94d28d1b8dSDouglas Gregor MIEnd = SubModules.end(); 95d28d1b8dSDouglas Gregor MI != MIEnd; ++MI) 96d28d1b8dSDouglas Gregor MI->getValue()->print(OS, Indent + 2); 97d28d1b8dSDouglas Gregor 98d28d1b8dSDouglas Gregor indent(OS, Indent); 99d28d1b8dSDouglas Gregor OS << "}\n"; 100d28d1b8dSDouglas Gregor } 101d28d1b8dSDouglas Gregor 102d28d1b8dSDouglas Gregor void ModuleMap::Module::dump() const { 103d28d1b8dSDouglas Gregor print(llvm::errs()); 104d28d1b8dSDouglas Gregor } 105d28d1b8dSDouglas 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 209*514b636aSDouglas Gregor const FileEntry * 210*514b636aSDouglas Gregor ModuleMap::getContainingModuleMapFile(ModuleMap::Module *Module) { 211*514b636aSDouglas Gregor if (Module->DefinitionLoc.isInvalid() || !SourceMgr) 212*514b636aSDouglas Gregor return 0; 213*514b636aSDouglas Gregor 214*514b636aSDouglas Gregor return SourceMgr->getFileEntryForID( 215*514b636aSDouglas Gregor SourceMgr->getFileID(Module->DefinitionLoc)); 216*514b636aSDouglas Gregor } 217*514b636aSDouglas Gregor 218718292f2SDouglas Gregor void ModuleMap::dump() { 219718292f2SDouglas Gregor llvm::errs() << "Modules:"; 220718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 221718292f2SDouglas Gregor MEnd = Modules.end(); 222718292f2SDouglas Gregor M != MEnd; ++M) 223d28d1b8dSDouglas Gregor M->getValue()->print(llvm::errs(), 2); 224718292f2SDouglas Gregor 225718292f2SDouglas Gregor llvm::errs() << "Headers:"; 226718292f2SDouglas Gregor for (llvm::DenseMap<const FileEntry *, Module *>::iterator 227718292f2SDouglas Gregor H = Headers.begin(), 228718292f2SDouglas Gregor HEnd = Headers.end(); 229718292f2SDouglas Gregor H != HEnd; ++H) { 230718292f2SDouglas Gregor llvm::errs() << " \"" << H->first->getName() << "\" -> " 231718292f2SDouglas Gregor << H->second->getFullModuleName() << "\n"; 232718292f2SDouglas Gregor } 233718292f2SDouglas Gregor } 234718292f2SDouglas Gregor 235718292f2SDouglas Gregor //----------------------------------------------------------------------------// 236718292f2SDouglas Gregor // Module map file parser 237718292f2SDouglas Gregor //----------------------------------------------------------------------------// 238718292f2SDouglas Gregor 239718292f2SDouglas Gregor namespace clang { 240718292f2SDouglas Gregor /// \brief A token in a module map file. 241718292f2SDouglas Gregor struct MMToken { 242718292f2SDouglas Gregor enum TokenKind { 243718292f2SDouglas Gregor EndOfFile, 244718292f2SDouglas Gregor HeaderKeyword, 245718292f2SDouglas Gregor Identifier, 246718292f2SDouglas Gregor ExplicitKeyword, 247755b2055SDouglas Gregor FrameworkKeyword, 248718292f2SDouglas Gregor ModuleKeyword, 249718292f2SDouglas Gregor UmbrellaKeyword, 250718292f2SDouglas Gregor StringLiteral, 251718292f2SDouglas Gregor LBrace, 252718292f2SDouglas Gregor RBrace 253718292f2SDouglas Gregor } Kind; 254718292f2SDouglas Gregor 255718292f2SDouglas Gregor unsigned Location; 256718292f2SDouglas Gregor unsigned StringLength; 257718292f2SDouglas Gregor const char *StringData; 258718292f2SDouglas Gregor 259718292f2SDouglas Gregor void clear() { 260718292f2SDouglas Gregor Kind = EndOfFile; 261718292f2SDouglas Gregor Location = 0; 262718292f2SDouglas Gregor StringLength = 0; 263718292f2SDouglas Gregor StringData = 0; 264718292f2SDouglas Gregor } 265718292f2SDouglas Gregor 266718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 267718292f2SDouglas Gregor 268718292f2SDouglas Gregor SourceLocation getLocation() const { 269718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 270718292f2SDouglas Gregor } 271718292f2SDouglas Gregor 272718292f2SDouglas Gregor StringRef getString() const { 273718292f2SDouglas Gregor return StringRef(StringData, StringLength); 274718292f2SDouglas Gregor } 275718292f2SDouglas Gregor }; 276718292f2SDouglas Gregor 277718292f2SDouglas Gregor class ModuleMapParser { 278718292f2SDouglas Gregor Lexer &L; 279718292f2SDouglas Gregor SourceManager &SourceMgr; 280718292f2SDouglas Gregor DiagnosticsEngine &Diags; 281718292f2SDouglas Gregor ModuleMap ⤅ 282718292f2SDouglas Gregor 2835257fc63SDouglas Gregor /// \brief The directory that this module map resides in. 2845257fc63SDouglas Gregor const DirectoryEntry *Directory; 2855257fc63SDouglas Gregor 286718292f2SDouglas Gregor /// \brief Whether an error occurred. 287718292f2SDouglas Gregor bool HadError; 288718292f2SDouglas Gregor 289718292f2SDouglas Gregor /// \brief Default target information, used only for string literal 290718292f2SDouglas Gregor /// parsing. 291718292f2SDouglas Gregor TargetInfo *Target; 292718292f2SDouglas Gregor 293718292f2SDouglas Gregor /// \brief Stores string data for the various string literals referenced 294718292f2SDouglas Gregor /// during parsing. 295718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 296718292f2SDouglas Gregor 297718292f2SDouglas Gregor /// \brief The current token. 298718292f2SDouglas Gregor MMToken Tok; 299718292f2SDouglas Gregor 300718292f2SDouglas Gregor /// \brief The active module. 301718292f2SDouglas Gregor ModuleMap::Module *ActiveModule; 302718292f2SDouglas Gregor 303718292f2SDouglas Gregor /// \brief Consume the current token and return its location. 304718292f2SDouglas Gregor SourceLocation consumeToken(); 305718292f2SDouglas Gregor 306718292f2SDouglas Gregor /// \brief Skip tokens until we reach the a token with the given kind 307718292f2SDouglas Gregor /// (or the end of the file). 308718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 309718292f2SDouglas Gregor 310718292f2SDouglas Gregor void parseModuleDecl(); 311718292f2SDouglas Gregor void parseUmbrellaDecl(); 312718292f2SDouglas Gregor void parseHeaderDecl(); 313718292f2SDouglas Gregor 314718292f2SDouglas Gregor public: 315718292f2SDouglas Gregor typedef ModuleMap::Module Module; 316718292f2SDouglas Gregor 317718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 318718292f2SDouglas Gregor DiagnosticsEngine &Diags, 3195257fc63SDouglas Gregor ModuleMap &Map, 3205257fc63SDouglas Gregor const DirectoryEntry *Directory) 3215257fc63SDouglas Gregor : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map), 3225257fc63SDouglas Gregor Directory(Directory), HadError(false), ActiveModule(0) 323718292f2SDouglas Gregor { 324718292f2SDouglas Gregor TargetOptions TargetOpts; 325718292f2SDouglas Gregor TargetOpts.Triple = llvm::sys::getDefaultTargetTriple(); 326718292f2SDouglas Gregor Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); 327718292f2SDouglas Gregor 328718292f2SDouglas Gregor Tok.clear(); 329718292f2SDouglas Gregor consumeToken(); 330718292f2SDouglas Gregor } 331718292f2SDouglas Gregor 332718292f2SDouglas Gregor bool parseModuleMapFile(); 333718292f2SDouglas Gregor }; 334718292f2SDouglas Gregor } 335718292f2SDouglas Gregor 336718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 337718292f2SDouglas Gregor retry: 338718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 339718292f2SDouglas Gregor Tok.clear(); 340718292f2SDouglas Gregor 341718292f2SDouglas Gregor Token LToken; 342718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 343718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 344718292f2SDouglas Gregor switch (LToken.getKind()) { 345718292f2SDouglas Gregor case tok::raw_identifier: 346718292f2SDouglas Gregor Tok.StringData = LToken.getRawIdentifierData(); 347718292f2SDouglas Gregor Tok.StringLength = LToken.getLength(); 348718292f2SDouglas Gregor Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString()) 349718292f2SDouglas Gregor .Case("header", MMToken::HeaderKeyword) 350718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 351755b2055SDouglas Gregor .Case("framework", MMToken::FrameworkKeyword) 352718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 353718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 354718292f2SDouglas Gregor .Default(MMToken::Identifier); 355718292f2SDouglas Gregor break; 356718292f2SDouglas Gregor 357718292f2SDouglas Gregor case tok::eof: 358718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 359718292f2SDouglas Gregor break; 360718292f2SDouglas Gregor 361718292f2SDouglas Gregor case tok::l_brace: 362718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 363718292f2SDouglas Gregor break; 364718292f2SDouglas Gregor 365718292f2SDouglas Gregor case tok::r_brace: 366718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 367718292f2SDouglas Gregor break; 368718292f2SDouglas Gregor 369718292f2SDouglas Gregor case tok::string_literal: { 370718292f2SDouglas Gregor // Parse the string literal. 371718292f2SDouglas Gregor LangOptions LangOpts; 372718292f2SDouglas Gregor StringLiteralParser StringLiteral(<oken, 1, SourceMgr, LangOpts, *Target); 373718292f2SDouglas Gregor if (StringLiteral.hadError) 374718292f2SDouglas Gregor goto retry; 375718292f2SDouglas Gregor 376718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 377718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 378718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 379718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 380718292f2SDouglas Gregor Saved[Length] = 0; 381718292f2SDouglas Gregor 382718292f2SDouglas Gregor // Form the token. 383718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 384718292f2SDouglas Gregor Tok.StringData = Saved; 385718292f2SDouglas Gregor Tok.StringLength = Length; 386718292f2SDouglas Gregor break; 387718292f2SDouglas Gregor } 388718292f2SDouglas Gregor 389718292f2SDouglas Gregor case tok::comment: 390718292f2SDouglas Gregor goto retry; 391718292f2SDouglas Gregor 392718292f2SDouglas Gregor default: 393718292f2SDouglas Gregor Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token); 394718292f2SDouglas Gregor HadError = true; 395718292f2SDouglas Gregor goto retry; 396718292f2SDouglas Gregor } 397718292f2SDouglas Gregor 398718292f2SDouglas Gregor return Result; 399718292f2SDouglas Gregor } 400718292f2SDouglas Gregor 401718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 402718292f2SDouglas Gregor unsigned braceDepth = 0; 403718292f2SDouglas Gregor do { 404718292f2SDouglas Gregor switch (Tok.Kind) { 405718292f2SDouglas Gregor case MMToken::EndOfFile: 406718292f2SDouglas Gregor return; 407718292f2SDouglas Gregor 408718292f2SDouglas Gregor case MMToken::LBrace: 409718292f2SDouglas Gregor if (Tok.is(K) && braceDepth == 0) 410718292f2SDouglas Gregor return; 411718292f2SDouglas Gregor 412718292f2SDouglas Gregor ++braceDepth; 413718292f2SDouglas Gregor break; 414718292f2SDouglas Gregor 415718292f2SDouglas Gregor case MMToken::RBrace: 416718292f2SDouglas Gregor if (braceDepth > 0) 417718292f2SDouglas Gregor --braceDepth; 418718292f2SDouglas Gregor else if (Tok.is(K)) 419718292f2SDouglas Gregor return; 420718292f2SDouglas Gregor break; 421718292f2SDouglas Gregor 422718292f2SDouglas Gregor default: 423718292f2SDouglas Gregor if (braceDepth == 0 && Tok.is(K)) 424718292f2SDouglas Gregor return; 425718292f2SDouglas Gregor break; 426718292f2SDouglas Gregor } 427718292f2SDouglas Gregor 428718292f2SDouglas Gregor consumeToken(); 429718292f2SDouglas Gregor } while (true); 430718292f2SDouglas Gregor } 431718292f2SDouglas Gregor 432718292f2SDouglas Gregor /// \brief Parse a module declaration. 433718292f2SDouglas Gregor /// 434718292f2SDouglas Gregor /// module-declaration: 435755b2055SDouglas Gregor /// 'framework'[opt] 'module' identifier { module-member* } 436718292f2SDouglas Gregor /// 437718292f2SDouglas Gregor /// module-member: 438718292f2SDouglas Gregor /// umbrella-declaration 439718292f2SDouglas Gregor /// header-declaration 440718292f2SDouglas Gregor /// 'explicit'[opt] module-declaration 441718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 442755b2055SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 443755b2055SDouglas Gregor Tok.is(MMToken::FrameworkKeyword)); 444718292f2SDouglas Gregor 445755b2055SDouglas Gregor // Parse 'framework' or 'explicit' keyword, if present. 446755b2055SDouglas Gregor bool Framework = false; 447718292f2SDouglas Gregor bool Explicit = false; 448755b2055SDouglas Gregor 449755b2055SDouglas Gregor if (Tok.is(MMToken::FrameworkKeyword)) { 450755b2055SDouglas Gregor consumeToken(); 451755b2055SDouglas Gregor Framework = true; 452755b2055SDouglas Gregor } 453755b2055SDouglas Gregor // Parse 'explicit' keyword, if present. 454755b2055SDouglas Gregor else if (Tok.is(MMToken::ExplicitKeyword)) { 455718292f2SDouglas Gregor consumeToken(); 456718292f2SDouglas Gregor Explicit = true; 457718292f2SDouglas Gregor } 458718292f2SDouglas Gregor 459718292f2SDouglas Gregor // Parse 'module' keyword. 460718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 461718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), 462718292f2SDouglas Gregor diag::err_mmap_expected_module_after_explicit); 463718292f2SDouglas Gregor consumeToken(); 464718292f2SDouglas Gregor HadError = true; 465718292f2SDouglas Gregor return; 466718292f2SDouglas Gregor } 467718292f2SDouglas Gregor consumeToken(); // 'module' keyword 468718292f2SDouglas Gregor 469718292f2SDouglas Gregor // Parse the module name. 470718292f2SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 471718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 472718292f2SDouglas Gregor HadError = true; 473718292f2SDouglas Gregor return; 474718292f2SDouglas Gregor } 475718292f2SDouglas Gregor StringRef ModuleName = Tok.getString(); 476718292f2SDouglas Gregor SourceLocation ModuleNameLoc = consumeToken(); 477718292f2SDouglas Gregor 478718292f2SDouglas Gregor // Parse the opening brace. 479718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 480718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 481718292f2SDouglas Gregor << ModuleName; 482718292f2SDouglas Gregor HadError = true; 483718292f2SDouglas Gregor return; 484718292f2SDouglas Gregor } 485718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 486718292f2SDouglas Gregor 487718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 488718292f2SDouglas Gregor llvm::StringMap<Module *> &ModuleSpace 489718292f2SDouglas Gregor = ActiveModule? ActiveModule->SubModules : Map.Modules; 490718292f2SDouglas Gregor llvm::StringMap<Module *>::iterator ExistingModule 491718292f2SDouglas Gregor = ModuleSpace.find(ModuleName); 492718292f2SDouglas Gregor if (ExistingModule != ModuleSpace.end()) { 493718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 494718292f2SDouglas Gregor << ModuleName; 495718292f2SDouglas Gregor Diags.Report(ExistingModule->getValue()->DefinitionLoc, 496718292f2SDouglas Gregor diag::note_mmap_prev_definition); 497718292f2SDouglas Gregor 498718292f2SDouglas Gregor // Skip the module definition. 499718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 500718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 501718292f2SDouglas Gregor consumeToken(); 502718292f2SDouglas Gregor 503718292f2SDouglas Gregor HadError = true; 504718292f2SDouglas Gregor return; 505718292f2SDouglas Gregor } 506718292f2SDouglas Gregor 507718292f2SDouglas Gregor // Start defining this module. 508755b2055SDouglas Gregor ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework, 509755b2055SDouglas Gregor Explicit); 510718292f2SDouglas Gregor ModuleSpace[ModuleName] = ActiveModule; 511718292f2SDouglas Gregor 512718292f2SDouglas Gregor bool Done = false; 513718292f2SDouglas Gregor do { 514718292f2SDouglas Gregor switch (Tok.Kind) { 515718292f2SDouglas Gregor case MMToken::EndOfFile: 516718292f2SDouglas Gregor case MMToken::RBrace: 517718292f2SDouglas Gregor Done = true; 518718292f2SDouglas Gregor break; 519718292f2SDouglas Gregor 520718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 521718292f2SDouglas Gregor case MMToken::ModuleKeyword: 522718292f2SDouglas Gregor parseModuleDecl(); 523718292f2SDouglas Gregor break; 524718292f2SDouglas Gregor 525718292f2SDouglas Gregor case MMToken::HeaderKeyword: 526718292f2SDouglas Gregor parseHeaderDecl(); 527718292f2SDouglas Gregor break; 528718292f2SDouglas Gregor 529718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 530718292f2SDouglas Gregor parseUmbrellaDecl(); 531718292f2SDouglas Gregor break; 532718292f2SDouglas Gregor 533718292f2SDouglas Gregor default: 534718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 535718292f2SDouglas Gregor consumeToken(); 536718292f2SDouglas Gregor break; 537718292f2SDouglas Gregor } 538718292f2SDouglas Gregor } while (!Done); 539718292f2SDouglas Gregor 540718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 541718292f2SDouglas Gregor consumeToken(); 542718292f2SDouglas Gregor else { 543718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 544718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 545718292f2SDouglas Gregor HadError = true; 546718292f2SDouglas Gregor } 547718292f2SDouglas Gregor 548718292f2SDouglas Gregor // We're done parsing this module. Pop back to our parent scope. 549718292f2SDouglas Gregor ActiveModule = ActiveModule->Parent; 550718292f2SDouglas Gregor } 551718292f2SDouglas Gregor 552718292f2SDouglas Gregor /// \brief Parse an umbrella header declaration. 553718292f2SDouglas Gregor /// 554718292f2SDouglas Gregor /// umbrella-declaration: 555718292f2SDouglas Gregor /// 'umbrella' string-literal 556718292f2SDouglas Gregor void ModuleMapParser::parseUmbrellaDecl() { 557718292f2SDouglas Gregor assert(Tok.is(MMToken::UmbrellaKeyword)); 558718292f2SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 559718292f2SDouglas Gregor 560718292f2SDouglas Gregor // Parse the header name. 561718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 562718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 563718292f2SDouglas Gregor << "umbrella"; 564718292f2SDouglas Gregor HadError = true; 565718292f2SDouglas Gregor return; 566718292f2SDouglas Gregor } 567718292f2SDouglas Gregor StringRef FileName = Tok.getString(); 568718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 569718292f2SDouglas Gregor 5705257fc63SDouglas Gregor // Check whether we already have an umbrella header. 5715257fc63SDouglas Gregor if (ActiveModule->UmbrellaHeader) { 5725257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict) 5735257fc63SDouglas Gregor << ActiveModule->getFullModuleName() 5745257fc63SDouglas Gregor << ActiveModule->UmbrellaHeader->getName(); 5755257fc63SDouglas Gregor HadError = true; 5765257fc63SDouglas Gregor return; 5775257fc63SDouglas Gregor } 5785257fc63SDouglas Gregor 5795257fc63SDouglas Gregor // Only top-level modules can have umbrella headers. 5805257fc63SDouglas Gregor if (ActiveModule->Parent) { 5815257fc63SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule) 5825257fc63SDouglas Gregor << ActiveModule->getFullModuleName(); 5835257fc63SDouglas Gregor HadError = true; 5845257fc63SDouglas Gregor return; 5855257fc63SDouglas Gregor } 5865257fc63SDouglas Gregor 5875257fc63SDouglas Gregor // Look for this file. 5885257fc63SDouglas Gregor llvm::SmallString<128> PathName; 5895257fc63SDouglas Gregor PathName += Directory->getName(); 590755b2055SDouglas Gregor unsigned PathLength = PathName.size(); 591755b2055SDouglas Gregor const FileEntry *File = 0; 592755b2055SDouglas Gregor if (ActiveModule->isPartOfFramework()) { 593755b2055SDouglas Gregor // Check whether this file is in the public headers. 594755b2055SDouglas Gregor llvm::sys::path::append(PathName, "Headers"); 5955257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 596755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 597755b2055SDouglas Gregor 598755b2055SDouglas Gregor if (!File) { 599755b2055SDouglas Gregor // Check whether this file is in the private headers. 600755b2055SDouglas Gregor PathName.resize(PathLength); 601755b2055SDouglas Gregor llvm::sys::path::append(PathName, "PrivateHeaders"); 602755b2055SDouglas Gregor llvm::sys::path::append(PathName, FileName); 603755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 604755b2055SDouglas Gregor } 605755b2055SDouglas Gregor 606755b2055SDouglas Gregor // FIXME: Deal with subframeworks. 607755b2055SDouglas Gregor } else { 608755b2055SDouglas Gregor // Lookup for normal headers. 609755b2055SDouglas Gregor llvm::sys::path::append(PathName, FileName); 610755b2055SDouglas Gregor File = SourceMgr.getFileManager().getFile(PathName); 611755b2055SDouglas Gregor } 6125257fc63SDouglas Gregor 6135257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 6145257fc63SDouglas Gregor // Come up with a lazy way to do this. 615755b2055SDouglas Gregor if (File) { 6165257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 6175257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 6185257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 6195257fc63SDouglas Gregor HadError = true; 620b65dbfffSDouglas Gregor } else if ((OwningModule = Map.UmbrellaDirs[Directory])) { 621b65dbfffSDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 622b65dbfffSDouglas Gregor << OwningModule->getFullModuleName(); 623b65dbfffSDouglas Gregor HadError = true; 6245257fc63SDouglas Gregor } else { 6255257fc63SDouglas Gregor // Record this umbrella header. 6265257fc63SDouglas Gregor ActiveModule->UmbrellaHeader = File; 6275257fc63SDouglas Gregor Map.Headers[File] = ActiveModule; 628b65dbfffSDouglas Gregor Map.UmbrellaDirs[Directory] = ActiveModule; 6295257fc63SDouglas Gregor } 6305257fc63SDouglas Gregor } else { 6315257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 6325257fc63SDouglas Gregor << true << FileName; 6335257fc63SDouglas Gregor HadError = true; 6345257fc63SDouglas Gregor } 635718292f2SDouglas Gregor } 636718292f2SDouglas Gregor 637718292f2SDouglas Gregor /// \brief Parse a header declaration. 638718292f2SDouglas Gregor /// 639718292f2SDouglas Gregor /// header-declaration: 640718292f2SDouglas Gregor /// 'header' string-literal 641718292f2SDouglas Gregor void ModuleMapParser::parseHeaderDecl() { 642718292f2SDouglas Gregor assert(Tok.is(MMToken::HeaderKeyword)); 6431871ed3dSBenjamin Kramer consumeToken(); 644718292f2SDouglas Gregor 645718292f2SDouglas Gregor // Parse the header name. 646718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 647718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 648718292f2SDouglas Gregor << "header"; 649718292f2SDouglas Gregor HadError = true; 650718292f2SDouglas Gregor return; 651718292f2SDouglas Gregor } 652718292f2SDouglas Gregor StringRef FileName = Tok.getString(); 653718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 654718292f2SDouglas Gregor 6555257fc63SDouglas Gregor // Look for this file. 6565257fc63SDouglas Gregor llvm::SmallString<128> PathName; 6575257fc63SDouglas Gregor PathName += Directory->getName(); 658755b2055SDouglas Gregor 659755b2055SDouglas Gregor if (ActiveModule->isPartOfFramework()) 660755b2055SDouglas Gregor llvm::sys::path::append(PathName, "Headers"); 661755b2055SDouglas Gregor 6625257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 6635257fc63SDouglas Gregor 6645257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 6655257fc63SDouglas Gregor // Come up with a lazy way to do this. 6665257fc63SDouglas Gregor if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) { 6675257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 6685257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 6695257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 6705257fc63SDouglas Gregor HadError = true; 6715257fc63SDouglas Gregor } else { 6725257fc63SDouglas Gregor // Record this file. 6735257fc63SDouglas Gregor ActiveModule->Headers.push_back(File); 6745257fc63SDouglas Gregor Map.Headers[File] = ActiveModule; 6755257fc63SDouglas Gregor } 6765257fc63SDouglas Gregor } else { 6775257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 6785257fc63SDouglas Gregor << false << FileName; 6795257fc63SDouglas Gregor HadError = true; 6805257fc63SDouglas Gregor } 681718292f2SDouglas Gregor } 682718292f2SDouglas Gregor 683718292f2SDouglas Gregor /// \brief Parse a module map file. 684718292f2SDouglas Gregor /// 685718292f2SDouglas Gregor /// module-map-file: 686718292f2SDouglas Gregor /// module-declaration* 687718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 688718292f2SDouglas Gregor do { 689718292f2SDouglas Gregor switch (Tok.Kind) { 690718292f2SDouglas Gregor case MMToken::EndOfFile: 691718292f2SDouglas Gregor return HadError; 692718292f2SDouglas Gregor 693718292f2SDouglas Gregor case MMToken::ModuleKeyword: 694755b2055SDouglas Gregor case MMToken::FrameworkKeyword: 695718292f2SDouglas Gregor parseModuleDecl(); 696718292f2SDouglas Gregor break; 697718292f2SDouglas Gregor 698718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 699718292f2SDouglas Gregor case MMToken::HeaderKeyword: 700718292f2SDouglas Gregor case MMToken::Identifier: 701718292f2SDouglas Gregor case MMToken::LBrace: 702718292f2SDouglas Gregor case MMToken::RBrace: 703718292f2SDouglas Gregor case MMToken::StringLiteral: 704718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 705718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 706718292f2SDouglas Gregor HadError = true; 707718292f2SDouglas Gregor consumeToken(); 708718292f2SDouglas Gregor break; 709718292f2SDouglas Gregor } 710718292f2SDouglas Gregor } while (true); 711718292f2SDouglas Gregor 712718292f2SDouglas Gregor return HadError; 713718292f2SDouglas Gregor } 714718292f2SDouglas Gregor 715718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) { 716718292f2SDouglas Gregor FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User); 717718292f2SDouglas Gregor const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID); 718718292f2SDouglas Gregor if (!Buffer) 719718292f2SDouglas Gregor return true; 720718292f2SDouglas Gregor 721718292f2SDouglas Gregor // Parse this module map file. 722718292f2SDouglas Gregor Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts); 723718292f2SDouglas Gregor Diags->getClient()->BeginSourceFile(LangOpts); 7245257fc63SDouglas Gregor ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir()); 725718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 726718292f2SDouglas Gregor Diags->getClient()->EndSourceFile(); 727718292f2SDouglas Gregor 728718292f2SDouglas Gregor return Result; 729718292f2SDouglas Gregor } 730