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" 24*5257fc63SDouglas 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 34718292f2SDouglas Gregor std::string ModuleMap::Module::getFullModuleName() const { 35718292f2SDouglas Gregor llvm::SmallVector<StringRef, 2> Names; 36718292f2SDouglas Gregor 37718292f2SDouglas Gregor // Build up the set of module names (from innermost to outermost). 38718292f2SDouglas Gregor for (const Module *M = this; M; M = M->Parent) 39718292f2SDouglas Gregor Names.push_back(M->Name); 40718292f2SDouglas Gregor 41718292f2SDouglas Gregor std::string Result; 42718292f2SDouglas Gregor for (llvm::SmallVector<StringRef, 2>::reverse_iterator I = Names.rbegin(), 43718292f2SDouglas Gregor IEnd = Names.rend(); 44718292f2SDouglas Gregor I != IEnd; ++I) { 45718292f2SDouglas Gregor if (!Result.empty()) 46718292f2SDouglas Gregor Result += '.'; 47718292f2SDouglas Gregor 48718292f2SDouglas Gregor Result += *I; 49718292f2SDouglas Gregor } 50718292f2SDouglas Gregor 51718292f2SDouglas Gregor return Result; 52718292f2SDouglas Gregor } 53718292f2SDouglas Gregor 54718292f2SDouglas Gregor //----------------------------------------------------------------------------// 55718292f2SDouglas Gregor // Module map 56718292f2SDouglas Gregor //----------------------------------------------------------------------------// 57718292f2SDouglas Gregor 58718292f2SDouglas Gregor ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) { 59718292f2SDouglas Gregor llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs); 60718292f2SDouglas Gregor Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>( 61718292f2SDouglas Gregor new DiagnosticsEngine(DiagIDs)); 62718292f2SDouglas Gregor Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true); 63718292f2SDouglas Gregor SourceMgr = new SourceManager(*Diags, FileMgr); 64718292f2SDouglas Gregor } 65718292f2SDouglas Gregor 66718292f2SDouglas Gregor ModuleMap::~ModuleMap() { 67718292f2SDouglas Gregor delete SourceMgr; 68718292f2SDouglas Gregor } 69718292f2SDouglas Gregor 70718292f2SDouglas Gregor static void indent(llvm::raw_ostream &OS, unsigned Spaces) { 71718292f2SDouglas Gregor OS << std::string(' ', Spaces); 72718292f2SDouglas Gregor } 73718292f2SDouglas Gregor 74718292f2SDouglas Gregor static void dumpModule(llvm::raw_ostream &OS, ModuleMap::Module *M, 75718292f2SDouglas Gregor unsigned Indent) { 76718292f2SDouglas Gregor indent(OS, Indent); 77718292f2SDouglas Gregor if (M->IsExplicit) 78718292f2SDouglas Gregor OS << "explicit "; 79718292f2SDouglas Gregor OS << M->Name << " {\n"; 80718292f2SDouglas Gregor 81718292f2SDouglas Gregor if (M->UmbrellaHeader) { 82718292f2SDouglas Gregor indent(OS, Indent + 2); 83718292f2SDouglas Gregor OS << "umbrella \"" << M->UmbrellaHeader->getName() << "\"\n"; 84718292f2SDouglas Gregor } 85718292f2SDouglas Gregor 86718292f2SDouglas Gregor for (unsigned I = 0, N = M->Headers.size(); I != N; ++I) { 87718292f2SDouglas Gregor indent(OS, Indent + 2); 88718292f2SDouglas Gregor OS << "header \"" << M->Headers[I]->getName() << "\"\n"; 89718292f2SDouglas Gregor } 90718292f2SDouglas Gregor 91718292f2SDouglas Gregor for (llvm::StringMap<ModuleMap::Module *>::iterator 92718292f2SDouglas Gregor MI = M->SubModules.begin(), 93718292f2SDouglas Gregor MIEnd = M->SubModules.end(); 94718292f2SDouglas Gregor MI != MIEnd; ++MI) 95718292f2SDouglas Gregor dumpModule(llvm::errs(), MI->getValue(), Indent + 2); 96718292f2SDouglas Gregor 97718292f2SDouglas Gregor indent(OS, Indent); 98718292f2SDouglas Gregor OS << "}\n"; 99718292f2SDouglas Gregor } 100718292f2SDouglas Gregor 101718292f2SDouglas Gregor void ModuleMap::dump() { 102718292f2SDouglas Gregor llvm::errs() << "Modules:"; 103718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 104718292f2SDouglas Gregor MEnd = Modules.end(); 105718292f2SDouglas Gregor M != MEnd; ++M) 106718292f2SDouglas Gregor dumpModule(llvm::errs(), M->getValue(), 2); 107718292f2SDouglas Gregor 108718292f2SDouglas Gregor llvm::errs() << "Headers:"; 109718292f2SDouglas Gregor for (llvm::DenseMap<const FileEntry *, Module *>::iterator 110718292f2SDouglas Gregor H = Headers.begin(), 111718292f2SDouglas Gregor HEnd = Headers.end(); 112718292f2SDouglas Gregor H != HEnd; ++H) { 113718292f2SDouglas Gregor llvm::errs() << " \"" << H->first->getName() << "\" -> " 114718292f2SDouglas Gregor << H->second->getFullModuleName() << "\n"; 115718292f2SDouglas Gregor } 116718292f2SDouglas Gregor } 117718292f2SDouglas Gregor 118718292f2SDouglas Gregor //----------------------------------------------------------------------------// 119718292f2SDouglas Gregor // Module map file parser 120718292f2SDouglas Gregor //----------------------------------------------------------------------------// 121718292f2SDouglas Gregor 122718292f2SDouglas Gregor namespace clang { 123718292f2SDouglas Gregor /// \brief A token in a module map file. 124718292f2SDouglas Gregor struct MMToken { 125718292f2SDouglas Gregor enum TokenKind { 126718292f2SDouglas Gregor EndOfFile, 127718292f2SDouglas Gregor HeaderKeyword, 128718292f2SDouglas Gregor Identifier, 129718292f2SDouglas Gregor ExplicitKeyword, 130718292f2SDouglas Gregor ModuleKeyword, 131718292f2SDouglas Gregor UmbrellaKeyword, 132718292f2SDouglas Gregor StringLiteral, 133718292f2SDouglas Gregor LBrace, 134718292f2SDouglas Gregor RBrace 135718292f2SDouglas Gregor } Kind; 136718292f2SDouglas Gregor 137718292f2SDouglas Gregor unsigned Location; 138718292f2SDouglas Gregor unsigned StringLength; 139718292f2SDouglas Gregor const char *StringData; 140718292f2SDouglas Gregor 141718292f2SDouglas Gregor void clear() { 142718292f2SDouglas Gregor Kind = EndOfFile; 143718292f2SDouglas Gregor Location = 0; 144718292f2SDouglas Gregor StringLength = 0; 145718292f2SDouglas Gregor StringData = 0; 146718292f2SDouglas Gregor } 147718292f2SDouglas Gregor 148718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 149718292f2SDouglas Gregor 150718292f2SDouglas Gregor SourceLocation getLocation() const { 151718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 152718292f2SDouglas Gregor } 153718292f2SDouglas Gregor 154718292f2SDouglas Gregor StringRef getString() const { 155718292f2SDouglas Gregor return StringRef(StringData, StringLength); 156718292f2SDouglas Gregor } 157718292f2SDouglas Gregor }; 158718292f2SDouglas Gregor 159718292f2SDouglas Gregor class ModuleMapParser { 160718292f2SDouglas Gregor Lexer &L; 161718292f2SDouglas Gregor SourceManager &SourceMgr; 162718292f2SDouglas Gregor DiagnosticsEngine &Diags; 163718292f2SDouglas Gregor ModuleMap ⤅ 164718292f2SDouglas Gregor 165*5257fc63SDouglas Gregor /// \brief The directory that this module map resides in. 166*5257fc63SDouglas Gregor const DirectoryEntry *Directory; 167*5257fc63SDouglas Gregor 168718292f2SDouglas Gregor /// \brief Whether an error occurred. 169718292f2SDouglas Gregor bool HadError; 170718292f2SDouglas Gregor 171718292f2SDouglas Gregor /// \brief Default target information, used only for string literal 172718292f2SDouglas Gregor /// parsing. 173718292f2SDouglas Gregor TargetInfo *Target; 174718292f2SDouglas Gregor 175718292f2SDouglas Gregor /// \brief Stores string data for the various string literals referenced 176718292f2SDouglas Gregor /// during parsing. 177718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 178718292f2SDouglas Gregor 179718292f2SDouglas Gregor /// \brief The current token. 180718292f2SDouglas Gregor MMToken Tok; 181718292f2SDouglas Gregor 182718292f2SDouglas Gregor /// \brief The active module. 183718292f2SDouglas Gregor ModuleMap::Module *ActiveModule; 184718292f2SDouglas Gregor 185718292f2SDouglas Gregor /// \brief Consume the current token and return its location. 186718292f2SDouglas Gregor SourceLocation consumeToken(); 187718292f2SDouglas Gregor 188718292f2SDouglas Gregor /// \brief Skip tokens until we reach the a token with the given kind 189718292f2SDouglas Gregor /// (or the end of the file). 190718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 191718292f2SDouglas Gregor 192718292f2SDouglas Gregor void parseModuleDecl(); 193718292f2SDouglas Gregor void parseUmbrellaDecl(); 194718292f2SDouglas Gregor void parseHeaderDecl(); 195718292f2SDouglas Gregor 196718292f2SDouglas Gregor public: 197718292f2SDouglas Gregor typedef ModuleMap::Module Module; 198718292f2SDouglas Gregor 199718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 200718292f2SDouglas Gregor DiagnosticsEngine &Diags, 201*5257fc63SDouglas Gregor ModuleMap &Map, 202*5257fc63SDouglas Gregor const DirectoryEntry *Directory) 203*5257fc63SDouglas Gregor : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map), 204*5257fc63SDouglas Gregor Directory(Directory), HadError(false), ActiveModule(0) 205718292f2SDouglas Gregor { 206718292f2SDouglas Gregor TargetOptions TargetOpts; 207718292f2SDouglas Gregor TargetOpts.Triple = llvm::sys::getDefaultTargetTriple(); 208718292f2SDouglas Gregor Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); 209718292f2SDouglas Gregor 210718292f2SDouglas Gregor Tok.clear(); 211718292f2SDouglas Gregor consumeToken(); 212718292f2SDouglas Gregor } 213718292f2SDouglas Gregor 214718292f2SDouglas Gregor bool parseModuleMapFile(); 215718292f2SDouglas Gregor }; 216718292f2SDouglas Gregor } 217718292f2SDouglas Gregor 218718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 219718292f2SDouglas Gregor retry: 220718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 221718292f2SDouglas Gregor Tok.clear(); 222718292f2SDouglas Gregor 223718292f2SDouglas Gregor Token LToken; 224718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 225718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 226718292f2SDouglas Gregor switch (LToken.getKind()) { 227718292f2SDouglas Gregor case tok::raw_identifier: 228718292f2SDouglas Gregor Tok.StringData = LToken.getRawIdentifierData(); 229718292f2SDouglas Gregor Tok.StringLength = LToken.getLength(); 230718292f2SDouglas Gregor Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString()) 231718292f2SDouglas Gregor .Case("header", MMToken::HeaderKeyword) 232718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 233718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 234718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 235718292f2SDouglas Gregor .Default(MMToken::Identifier); 236718292f2SDouglas Gregor break; 237718292f2SDouglas Gregor 238718292f2SDouglas Gregor case tok::eof: 239718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 240718292f2SDouglas Gregor break; 241718292f2SDouglas Gregor 242718292f2SDouglas Gregor case tok::l_brace: 243718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 244718292f2SDouglas Gregor break; 245718292f2SDouglas Gregor 246718292f2SDouglas Gregor case tok::r_brace: 247718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 248718292f2SDouglas Gregor break; 249718292f2SDouglas Gregor 250718292f2SDouglas Gregor case tok::string_literal: { 251718292f2SDouglas Gregor // Parse the string literal. 252718292f2SDouglas Gregor LangOptions LangOpts; 253718292f2SDouglas Gregor StringLiteralParser StringLiteral(<oken, 1, SourceMgr, LangOpts, *Target); 254718292f2SDouglas Gregor if (StringLiteral.hadError) 255718292f2SDouglas Gregor goto retry; 256718292f2SDouglas Gregor 257718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 258718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 259718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 260718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 261718292f2SDouglas Gregor Saved[Length] = 0; 262718292f2SDouglas Gregor 263718292f2SDouglas Gregor // Form the token. 264718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 265718292f2SDouglas Gregor Tok.StringData = Saved; 266718292f2SDouglas Gregor Tok.StringLength = Length; 267718292f2SDouglas Gregor break; 268718292f2SDouglas Gregor } 269718292f2SDouglas Gregor 270718292f2SDouglas Gregor case tok::comment: 271718292f2SDouglas Gregor goto retry; 272718292f2SDouglas Gregor 273718292f2SDouglas Gregor default: 274718292f2SDouglas Gregor Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token); 275718292f2SDouglas Gregor HadError = true; 276718292f2SDouglas Gregor goto retry; 277718292f2SDouglas Gregor } 278718292f2SDouglas Gregor 279718292f2SDouglas Gregor return Result; 280718292f2SDouglas Gregor } 281718292f2SDouglas Gregor 282718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 283718292f2SDouglas Gregor unsigned braceDepth = 0; 284718292f2SDouglas Gregor do { 285718292f2SDouglas Gregor switch (Tok.Kind) { 286718292f2SDouglas Gregor case MMToken::EndOfFile: 287718292f2SDouglas Gregor return; 288718292f2SDouglas Gregor 289718292f2SDouglas Gregor case MMToken::LBrace: 290718292f2SDouglas Gregor if (Tok.is(K) && braceDepth == 0) 291718292f2SDouglas Gregor return; 292718292f2SDouglas Gregor 293718292f2SDouglas Gregor ++braceDepth; 294718292f2SDouglas Gregor break; 295718292f2SDouglas Gregor 296718292f2SDouglas Gregor case MMToken::RBrace: 297718292f2SDouglas Gregor if (braceDepth > 0) 298718292f2SDouglas Gregor --braceDepth; 299718292f2SDouglas Gregor else if (Tok.is(K)) 300718292f2SDouglas Gregor return; 301718292f2SDouglas Gregor break; 302718292f2SDouglas Gregor 303718292f2SDouglas Gregor default: 304718292f2SDouglas Gregor if (braceDepth == 0 && Tok.is(K)) 305718292f2SDouglas Gregor return; 306718292f2SDouglas Gregor break; 307718292f2SDouglas Gregor } 308718292f2SDouglas Gregor 309718292f2SDouglas Gregor consumeToken(); 310718292f2SDouglas Gregor } while (true); 311718292f2SDouglas Gregor } 312718292f2SDouglas Gregor 313718292f2SDouglas Gregor /// \brief Parse a module declaration. 314718292f2SDouglas Gregor /// 315718292f2SDouglas Gregor /// module-declaration: 316718292f2SDouglas Gregor /// 'module' identifier { module-member* } 317718292f2SDouglas Gregor /// 318718292f2SDouglas Gregor /// module-member: 319718292f2SDouglas Gregor /// umbrella-declaration 320718292f2SDouglas Gregor /// header-declaration 321718292f2SDouglas Gregor /// 'explicit'[opt] module-declaration 322718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 323718292f2SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword)); 324718292f2SDouglas Gregor 325718292f2SDouglas Gregor // Parse 'explicit' keyword, if present. 326718292f2SDouglas Gregor bool Explicit = false; 327718292f2SDouglas Gregor if (Tok.is(MMToken::ExplicitKeyword)) { 328718292f2SDouglas Gregor consumeToken(); 329718292f2SDouglas Gregor Explicit = true; 330718292f2SDouglas Gregor } 331718292f2SDouglas Gregor 332718292f2SDouglas Gregor // Parse 'module' keyword. 333718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 334718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), 335718292f2SDouglas Gregor diag::err_mmap_expected_module_after_explicit); 336718292f2SDouglas Gregor consumeToken(); 337718292f2SDouglas Gregor HadError = true; 338718292f2SDouglas Gregor return; 339718292f2SDouglas Gregor } 340718292f2SDouglas Gregor consumeToken(); // 'module' keyword 341718292f2SDouglas Gregor 342718292f2SDouglas Gregor // Parse the module name. 343718292f2SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 344718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 345718292f2SDouglas Gregor HadError = true; 346718292f2SDouglas Gregor return; 347718292f2SDouglas Gregor } 348718292f2SDouglas Gregor StringRef ModuleName = Tok.getString(); 349718292f2SDouglas Gregor SourceLocation ModuleNameLoc = consumeToken(); 350718292f2SDouglas Gregor 351718292f2SDouglas Gregor // Parse the opening brace. 352718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 353718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 354718292f2SDouglas Gregor << ModuleName; 355718292f2SDouglas Gregor HadError = true; 356718292f2SDouglas Gregor return; 357718292f2SDouglas Gregor } 358718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 359718292f2SDouglas Gregor 360718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 361718292f2SDouglas Gregor llvm::StringMap<Module *> &ModuleSpace 362718292f2SDouglas Gregor = ActiveModule? ActiveModule->SubModules : Map.Modules; 363718292f2SDouglas Gregor llvm::StringMap<Module *>::iterator ExistingModule 364718292f2SDouglas Gregor = ModuleSpace.find(ModuleName); 365718292f2SDouglas Gregor if (ExistingModule != ModuleSpace.end()) { 366718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 367718292f2SDouglas Gregor << ModuleName; 368718292f2SDouglas Gregor Diags.Report(ExistingModule->getValue()->DefinitionLoc, 369718292f2SDouglas Gregor diag::note_mmap_prev_definition); 370718292f2SDouglas Gregor 371718292f2SDouglas Gregor // Skip the module definition. 372718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 373718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 374718292f2SDouglas Gregor consumeToken(); 375718292f2SDouglas Gregor 376718292f2SDouglas Gregor HadError = true; 377718292f2SDouglas Gregor return; 378718292f2SDouglas Gregor } 379718292f2SDouglas Gregor 380718292f2SDouglas Gregor // Start defining this module. 381718292f2SDouglas Gregor ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Explicit); 382718292f2SDouglas Gregor ModuleSpace[ModuleName] = ActiveModule; 383718292f2SDouglas Gregor 384718292f2SDouglas Gregor bool Done = false; 385718292f2SDouglas Gregor do { 386718292f2SDouglas Gregor switch (Tok.Kind) { 387718292f2SDouglas Gregor case MMToken::EndOfFile: 388718292f2SDouglas Gregor case MMToken::RBrace: 389718292f2SDouglas Gregor Done = true; 390718292f2SDouglas Gregor break; 391718292f2SDouglas Gregor 392718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 393718292f2SDouglas Gregor case MMToken::ModuleKeyword: 394718292f2SDouglas Gregor parseModuleDecl(); 395718292f2SDouglas Gregor break; 396718292f2SDouglas Gregor 397718292f2SDouglas Gregor case MMToken::HeaderKeyword: 398718292f2SDouglas Gregor parseHeaderDecl(); 399718292f2SDouglas Gregor break; 400718292f2SDouglas Gregor 401718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 402718292f2SDouglas Gregor parseUmbrellaDecl(); 403718292f2SDouglas Gregor break; 404718292f2SDouglas Gregor 405718292f2SDouglas Gregor default: 406718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 407718292f2SDouglas Gregor consumeToken(); 408718292f2SDouglas Gregor break; 409718292f2SDouglas Gregor } 410718292f2SDouglas Gregor } while (!Done); 411718292f2SDouglas Gregor 412718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 413718292f2SDouglas Gregor consumeToken(); 414718292f2SDouglas Gregor else { 415718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 416718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 417718292f2SDouglas Gregor HadError = true; 418718292f2SDouglas Gregor } 419718292f2SDouglas Gregor 420718292f2SDouglas Gregor // We're done parsing this module. Pop back to our parent scope. 421718292f2SDouglas Gregor ActiveModule = ActiveModule->Parent; 422718292f2SDouglas Gregor } 423718292f2SDouglas Gregor 424718292f2SDouglas Gregor /// \brief Parse an umbrella header declaration. 425718292f2SDouglas Gregor /// 426718292f2SDouglas Gregor /// umbrella-declaration: 427718292f2SDouglas Gregor /// 'umbrella' string-literal 428718292f2SDouglas Gregor void ModuleMapParser::parseUmbrellaDecl() { 429718292f2SDouglas Gregor assert(Tok.is(MMToken::UmbrellaKeyword)); 430718292f2SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 431718292f2SDouglas Gregor 432718292f2SDouglas Gregor // Parse the header name. 433718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 434718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 435718292f2SDouglas Gregor << "umbrella"; 436718292f2SDouglas Gregor HadError = true; 437718292f2SDouglas Gregor return; 438718292f2SDouglas Gregor } 439718292f2SDouglas Gregor StringRef FileName = Tok.getString(); 440718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 441718292f2SDouglas Gregor 442*5257fc63SDouglas Gregor // Check whether we already have an umbrella header. 443*5257fc63SDouglas Gregor if (ActiveModule->UmbrellaHeader) { 444*5257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict) 445*5257fc63SDouglas Gregor << ActiveModule->getFullModuleName() 446*5257fc63SDouglas Gregor << ActiveModule->UmbrellaHeader->getName(); 447*5257fc63SDouglas Gregor HadError = true; 448*5257fc63SDouglas Gregor return; 449*5257fc63SDouglas Gregor } 450*5257fc63SDouglas Gregor 451*5257fc63SDouglas Gregor // Only top-level modules can have umbrella headers. 452*5257fc63SDouglas Gregor if (ActiveModule->Parent) { 453*5257fc63SDouglas Gregor Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule) 454*5257fc63SDouglas Gregor << ActiveModule->getFullModuleName(); 455*5257fc63SDouglas Gregor HadError = true; 456*5257fc63SDouglas Gregor return; 457*5257fc63SDouglas Gregor } 458*5257fc63SDouglas Gregor 459*5257fc63SDouglas Gregor // Look for this file. 460*5257fc63SDouglas Gregor llvm::SmallString<128> PathName; 461*5257fc63SDouglas Gregor PathName += Directory->getName(); 462*5257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 463*5257fc63SDouglas Gregor 464*5257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 465*5257fc63SDouglas Gregor // Come up with a lazy way to do this. 466*5257fc63SDouglas Gregor if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) { 467*5257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 468*5257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 469*5257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 470*5257fc63SDouglas Gregor HadError = true; 471*5257fc63SDouglas Gregor } else { 472*5257fc63SDouglas Gregor // Record this umbrella header. 473*5257fc63SDouglas Gregor ActiveModule->UmbrellaHeader = File; 474*5257fc63SDouglas Gregor Map.Headers[File] = ActiveModule; 475*5257fc63SDouglas Gregor } 476*5257fc63SDouglas Gregor } else { 477*5257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 478*5257fc63SDouglas Gregor << true << FileName; 479*5257fc63SDouglas Gregor HadError = true; 480*5257fc63SDouglas Gregor } 481718292f2SDouglas Gregor } 482718292f2SDouglas Gregor 483718292f2SDouglas Gregor /// \brief Parse a header declaration. 484718292f2SDouglas Gregor /// 485718292f2SDouglas Gregor /// header-declaration: 486718292f2SDouglas Gregor /// 'header' string-literal 487718292f2SDouglas Gregor void ModuleMapParser::parseHeaderDecl() { 488718292f2SDouglas Gregor assert(Tok.is(MMToken::HeaderKeyword)); 489718292f2SDouglas Gregor SourceLocation HeaderLoc = consumeToken(); 490718292f2SDouglas Gregor 491718292f2SDouglas Gregor // Parse the header name. 492718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 493718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 494718292f2SDouglas Gregor << "header"; 495718292f2SDouglas Gregor HadError = true; 496718292f2SDouglas Gregor return; 497718292f2SDouglas Gregor } 498718292f2SDouglas Gregor StringRef FileName = Tok.getString(); 499718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 500718292f2SDouglas Gregor 501*5257fc63SDouglas Gregor // Look for this file. 502*5257fc63SDouglas Gregor llvm::SmallString<128> PathName; 503*5257fc63SDouglas Gregor PathName += Directory->getName(); 504*5257fc63SDouglas Gregor llvm::sys::path::append(PathName, FileName); 505*5257fc63SDouglas Gregor 506*5257fc63SDouglas Gregor // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 507*5257fc63SDouglas Gregor // Come up with a lazy way to do this. 508*5257fc63SDouglas Gregor if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) { 509*5257fc63SDouglas Gregor if (const Module *OwningModule = Map.Headers[File]) { 510*5257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 511*5257fc63SDouglas Gregor << FileName << OwningModule->getFullModuleName(); 512*5257fc63SDouglas Gregor HadError = true; 513*5257fc63SDouglas Gregor } else { 514*5257fc63SDouglas Gregor // Record this file. 515*5257fc63SDouglas Gregor ActiveModule->Headers.push_back(File); 516*5257fc63SDouglas Gregor Map.Headers[File] = ActiveModule; 517*5257fc63SDouglas Gregor } 518*5257fc63SDouglas Gregor } else { 519*5257fc63SDouglas Gregor Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 520*5257fc63SDouglas Gregor << false << FileName; 521*5257fc63SDouglas Gregor HadError = true; 522*5257fc63SDouglas Gregor } 523718292f2SDouglas Gregor } 524718292f2SDouglas Gregor 525718292f2SDouglas Gregor /// \brief Parse a module map file. 526718292f2SDouglas Gregor /// 527718292f2SDouglas Gregor /// module-map-file: 528718292f2SDouglas Gregor /// module-declaration* 529718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 530718292f2SDouglas Gregor do { 531718292f2SDouglas Gregor switch (Tok.Kind) { 532718292f2SDouglas Gregor case MMToken::EndOfFile: 533718292f2SDouglas Gregor return HadError; 534718292f2SDouglas Gregor 535718292f2SDouglas Gregor case MMToken::ModuleKeyword: 536718292f2SDouglas Gregor parseModuleDecl(); 537718292f2SDouglas Gregor break; 538718292f2SDouglas Gregor 539718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 540718292f2SDouglas Gregor case MMToken::HeaderKeyword: 541718292f2SDouglas Gregor case MMToken::Identifier: 542718292f2SDouglas Gregor case MMToken::LBrace: 543718292f2SDouglas Gregor case MMToken::RBrace: 544718292f2SDouglas Gregor case MMToken::StringLiteral: 545718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 546718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 547718292f2SDouglas Gregor HadError = true; 548718292f2SDouglas Gregor consumeToken(); 549718292f2SDouglas Gregor break; 550718292f2SDouglas Gregor } 551718292f2SDouglas Gregor } while (true); 552718292f2SDouglas Gregor 553718292f2SDouglas Gregor return HadError; 554718292f2SDouglas Gregor } 555718292f2SDouglas Gregor 556718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) { 557718292f2SDouglas Gregor FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User); 558718292f2SDouglas Gregor const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID); 559718292f2SDouglas Gregor if (!Buffer) 560718292f2SDouglas Gregor return true; 561718292f2SDouglas Gregor 562718292f2SDouglas Gregor // Parse this module map file. 563718292f2SDouglas Gregor Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts); 564718292f2SDouglas Gregor Diags->getClient()->BeginSourceFile(LangOpts); 565*5257fc63SDouglas Gregor ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir()); 566718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 567718292f2SDouglas Gregor Diags->getClient()->EndSourceFile(); 568718292f2SDouglas Gregor 569718292f2SDouglas Gregor return Result; 570718292f2SDouglas Gregor } 571