1*718292f2SDouglas Gregor //===--- ModuleMap.cpp - Describe the layout of modules ---------*- C++ -*-===// 2*718292f2SDouglas Gregor // 3*718292f2SDouglas Gregor // The LLVM Compiler Infrastructure 4*718292f2SDouglas Gregor // 5*718292f2SDouglas Gregor // This file is distributed under the University of Illinois Open Source 6*718292f2SDouglas Gregor // License. See LICENSE.TXT for details. 7*718292f2SDouglas Gregor // 8*718292f2SDouglas Gregor //===----------------------------------------------------------------------===// 9*718292f2SDouglas Gregor // 10*718292f2SDouglas Gregor // This file defines the ModuleMap implementation, which describes the layout 11*718292f2SDouglas Gregor // of a module as it relates to headers. 12*718292f2SDouglas Gregor // 13*718292f2SDouglas Gregor //===----------------------------------------------------------------------===// 14*718292f2SDouglas Gregor #include "clang/Lex/ModuleMap.h" 15*718292f2SDouglas Gregor #include "clang/Lex/Lexer.h" 16*718292f2SDouglas Gregor #include "clang/Lex/LiteralSupport.h" 17*718292f2SDouglas Gregor #include "clang/Lex/LexDiagnostic.h" 18*718292f2SDouglas Gregor #include "clang/Basic/Diagnostic.h" 19*718292f2SDouglas Gregor #include "clang/Basic/FileManager.h" 20*718292f2SDouglas Gregor #include "clang/Basic/TargetInfo.h" 21*718292f2SDouglas Gregor #include "clang/Basic/TargetOptions.h" 22*718292f2SDouglas Gregor #include "llvm/Support/Allocator.h" 23*718292f2SDouglas Gregor #include "llvm/Support/Host.h" 24*718292f2SDouglas Gregor #include "llvm/Support/raw_ostream.h" 25*718292f2SDouglas Gregor #include "llvm/ADT/StringRef.h" 26*718292f2SDouglas Gregor #include "llvm/ADT/StringSwitch.h" 27*718292f2SDouglas Gregor using namespace clang; 28*718292f2SDouglas Gregor 29*718292f2SDouglas Gregor //----------------------------------------------------------------------------// 30*718292f2SDouglas Gregor // Module 31*718292f2SDouglas Gregor //----------------------------------------------------------------------------// 32*718292f2SDouglas Gregor 33*718292f2SDouglas Gregor std::string ModuleMap::Module::getFullModuleName() const { 34*718292f2SDouglas Gregor llvm::SmallVector<StringRef, 2> Names; 35*718292f2SDouglas Gregor 36*718292f2SDouglas Gregor // Build up the set of module names (from innermost to outermost). 37*718292f2SDouglas Gregor for (const Module *M = this; M; M = M->Parent) 38*718292f2SDouglas Gregor Names.push_back(M->Name); 39*718292f2SDouglas Gregor 40*718292f2SDouglas Gregor std::string Result; 41*718292f2SDouglas Gregor for (llvm::SmallVector<StringRef, 2>::reverse_iterator I = Names.rbegin(), 42*718292f2SDouglas Gregor IEnd = Names.rend(); 43*718292f2SDouglas Gregor I != IEnd; ++I) { 44*718292f2SDouglas Gregor if (!Result.empty()) 45*718292f2SDouglas Gregor Result += '.'; 46*718292f2SDouglas Gregor 47*718292f2SDouglas Gregor Result += *I; 48*718292f2SDouglas Gregor } 49*718292f2SDouglas Gregor 50*718292f2SDouglas Gregor return Result; 51*718292f2SDouglas Gregor } 52*718292f2SDouglas Gregor 53*718292f2SDouglas Gregor //----------------------------------------------------------------------------// 54*718292f2SDouglas Gregor // Module map 55*718292f2SDouglas Gregor //----------------------------------------------------------------------------// 56*718292f2SDouglas Gregor 57*718292f2SDouglas Gregor ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) { 58*718292f2SDouglas Gregor llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs); 59*718292f2SDouglas Gregor Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>( 60*718292f2SDouglas Gregor new DiagnosticsEngine(DiagIDs)); 61*718292f2SDouglas Gregor Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true); 62*718292f2SDouglas Gregor SourceMgr = new SourceManager(*Diags, FileMgr); 63*718292f2SDouglas Gregor } 64*718292f2SDouglas Gregor 65*718292f2SDouglas Gregor ModuleMap::~ModuleMap() { 66*718292f2SDouglas Gregor delete SourceMgr; 67*718292f2SDouglas Gregor } 68*718292f2SDouglas Gregor 69*718292f2SDouglas Gregor static void indent(llvm::raw_ostream &OS, unsigned Spaces) { 70*718292f2SDouglas Gregor OS << std::string(' ', Spaces); 71*718292f2SDouglas Gregor } 72*718292f2SDouglas Gregor 73*718292f2SDouglas Gregor static void dumpModule(llvm::raw_ostream &OS, ModuleMap::Module *M, 74*718292f2SDouglas Gregor unsigned Indent) { 75*718292f2SDouglas Gregor indent(OS, Indent); 76*718292f2SDouglas Gregor if (M->IsExplicit) 77*718292f2SDouglas Gregor OS << "explicit "; 78*718292f2SDouglas Gregor OS << M->Name << " {\n"; 79*718292f2SDouglas Gregor 80*718292f2SDouglas Gregor if (M->UmbrellaHeader) { 81*718292f2SDouglas Gregor indent(OS, Indent + 2); 82*718292f2SDouglas Gregor OS << "umbrella \"" << M->UmbrellaHeader->getName() << "\"\n"; 83*718292f2SDouglas Gregor } 84*718292f2SDouglas Gregor 85*718292f2SDouglas Gregor for (unsigned I = 0, N = M->Headers.size(); I != N; ++I) { 86*718292f2SDouglas Gregor indent(OS, Indent + 2); 87*718292f2SDouglas Gregor OS << "header \"" << M->Headers[I]->getName() << "\"\n"; 88*718292f2SDouglas Gregor } 89*718292f2SDouglas Gregor 90*718292f2SDouglas Gregor for (llvm::StringMap<ModuleMap::Module *>::iterator 91*718292f2SDouglas Gregor MI = M->SubModules.begin(), 92*718292f2SDouglas Gregor MIEnd = M->SubModules.end(); 93*718292f2SDouglas Gregor MI != MIEnd; ++MI) 94*718292f2SDouglas Gregor dumpModule(llvm::errs(), MI->getValue(), Indent + 2); 95*718292f2SDouglas Gregor 96*718292f2SDouglas Gregor indent(OS, Indent); 97*718292f2SDouglas Gregor OS << "}\n"; 98*718292f2SDouglas Gregor } 99*718292f2SDouglas Gregor 100*718292f2SDouglas Gregor void ModuleMap::dump() { 101*718292f2SDouglas Gregor llvm::errs() << "Modules:"; 102*718292f2SDouglas Gregor for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 103*718292f2SDouglas Gregor MEnd = Modules.end(); 104*718292f2SDouglas Gregor M != MEnd; ++M) 105*718292f2SDouglas Gregor dumpModule(llvm::errs(), M->getValue(), 2); 106*718292f2SDouglas Gregor 107*718292f2SDouglas Gregor llvm::errs() << "Headers:"; 108*718292f2SDouglas Gregor for (llvm::DenseMap<const FileEntry *, Module *>::iterator 109*718292f2SDouglas Gregor H = Headers.begin(), 110*718292f2SDouglas Gregor HEnd = Headers.end(); 111*718292f2SDouglas Gregor H != HEnd; ++H) { 112*718292f2SDouglas Gregor llvm::errs() << " \"" << H->first->getName() << "\" -> " 113*718292f2SDouglas Gregor << H->second->getFullModuleName() << "\n"; 114*718292f2SDouglas Gregor } 115*718292f2SDouglas Gregor } 116*718292f2SDouglas Gregor 117*718292f2SDouglas Gregor //----------------------------------------------------------------------------// 118*718292f2SDouglas Gregor // Module map file parser 119*718292f2SDouglas Gregor //----------------------------------------------------------------------------// 120*718292f2SDouglas Gregor 121*718292f2SDouglas Gregor namespace clang { 122*718292f2SDouglas Gregor /// \brief A token in a module map file. 123*718292f2SDouglas Gregor struct MMToken { 124*718292f2SDouglas Gregor enum TokenKind { 125*718292f2SDouglas Gregor EndOfFile, 126*718292f2SDouglas Gregor HeaderKeyword, 127*718292f2SDouglas Gregor Identifier, 128*718292f2SDouglas Gregor ExplicitKeyword, 129*718292f2SDouglas Gregor ModuleKeyword, 130*718292f2SDouglas Gregor UmbrellaKeyword, 131*718292f2SDouglas Gregor StringLiteral, 132*718292f2SDouglas Gregor LBrace, 133*718292f2SDouglas Gregor RBrace 134*718292f2SDouglas Gregor } Kind; 135*718292f2SDouglas Gregor 136*718292f2SDouglas Gregor unsigned Location; 137*718292f2SDouglas Gregor unsigned StringLength; 138*718292f2SDouglas Gregor const char *StringData; 139*718292f2SDouglas Gregor 140*718292f2SDouglas Gregor void clear() { 141*718292f2SDouglas Gregor Kind = EndOfFile; 142*718292f2SDouglas Gregor Location = 0; 143*718292f2SDouglas Gregor StringLength = 0; 144*718292f2SDouglas Gregor StringData = 0; 145*718292f2SDouglas Gregor } 146*718292f2SDouglas Gregor 147*718292f2SDouglas Gregor bool is(TokenKind K) const { return Kind == K; } 148*718292f2SDouglas Gregor 149*718292f2SDouglas Gregor SourceLocation getLocation() const { 150*718292f2SDouglas Gregor return SourceLocation::getFromRawEncoding(Location); 151*718292f2SDouglas Gregor } 152*718292f2SDouglas Gregor 153*718292f2SDouglas Gregor StringRef getString() const { 154*718292f2SDouglas Gregor return StringRef(StringData, StringLength); 155*718292f2SDouglas Gregor } 156*718292f2SDouglas Gregor }; 157*718292f2SDouglas Gregor 158*718292f2SDouglas Gregor class ModuleMapParser { 159*718292f2SDouglas Gregor Lexer &L; 160*718292f2SDouglas Gregor SourceManager &SourceMgr; 161*718292f2SDouglas Gregor DiagnosticsEngine &Diags; 162*718292f2SDouglas Gregor ModuleMap ⤅ 163*718292f2SDouglas Gregor 164*718292f2SDouglas Gregor /// \brief Whether an error occurred. 165*718292f2SDouglas Gregor bool HadError; 166*718292f2SDouglas Gregor 167*718292f2SDouglas Gregor /// \brief Default target information, used only for string literal 168*718292f2SDouglas Gregor /// parsing. 169*718292f2SDouglas Gregor TargetInfo *Target; 170*718292f2SDouglas Gregor 171*718292f2SDouglas Gregor /// \brief Stores string data for the various string literals referenced 172*718292f2SDouglas Gregor /// during parsing. 173*718292f2SDouglas Gregor llvm::BumpPtrAllocator StringData; 174*718292f2SDouglas Gregor 175*718292f2SDouglas Gregor /// \brief The current token. 176*718292f2SDouglas Gregor MMToken Tok; 177*718292f2SDouglas Gregor 178*718292f2SDouglas Gregor /// \brief The active module. 179*718292f2SDouglas Gregor ModuleMap::Module *ActiveModule; 180*718292f2SDouglas Gregor 181*718292f2SDouglas Gregor /// \brief Consume the current token and return its location. 182*718292f2SDouglas Gregor SourceLocation consumeToken(); 183*718292f2SDouglas Gregor 184*718292f2SDouglas Gregor /// \brief Skip tokens until we reach the a token with the given kind 185*718292f2SDouglas Gregor /// (or the end of the file). 186*718292f2SDouglas Gregor void skipUntil(MMToken::TokenKind K); 187*718292f2SDouglas Gregor 188*718292f2SDouglas Gregor void parseModuleDecl(); 189*718292f2SDouglas Gregor void parseUmbrellaDecl(); 190*718292f2SDouglas Gregor void parseHeaderDecl(); 191*718292f2SDouglas Gregor 192*718292f2SDouglas Gregor public: 193*718292f2SDouglas Gregor typedef ModuleMap::Module Module; 194*718292f2SDouglas Gregor 195*718292f2SDouglas Gregor explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 196*718292f2SDouglas Gregor DiagnosticsEngine &Diags, 197*718292f2SDouglas Gregor ModuleMap &Map) 198*718292f2SDouglas Gregor : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map), HadError(false), 199*718292f2SDouglas Gregor ActiveModule(0) 200*718292f2SDouglas Gregor { 201*718292f2SDouglas Gregor TargetOptions TargetOpts; 202*718292f2SDouglas Gregor TargetOpts.Triple = llvm::sys::getDefaultTargetTriple(); 203*718292f2SDouglas Gregor Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); 204*718292f2SDouglas Gregor 205*718292f2SDouglas Gregor Tok.clear(); 206*718292f2SDouglas Gregor consumeToken(); 207*718292f2SDouglas Gregor } 208*718292f2SDouglas Gregor 209*718292f2SDouglas Gregor bool parseModuleMapFile(); 210*718292f2SDouglas Gregor }; 211*718292f2SDouglas Gregor } 212*718292f2SDouglas Gregor 213*718292f2SDouglas Gregor SourceLocation ModuleMapParser::consumeToken() { 214*718292f2SDouglas Gregor retry: 215*718292f2SDouglas Gregor SourceLocation Result = Tok.getLocation(); 216*718292f2SDouglas Gregor Tok.clear(); 217*718292f2SDouglas Gregor 218*718292f2SDouglas Gregor Token LToken; 219*718292f2SDouglas Gregor L.LexFromRawLexer(LToken); 220*718292f2SDouglas Gregor Tok.Location = LToken.getLocation().getRawEncoding(); 221*718292f2SDouglas Gregor switch (LToken.getKind()) { 222*718292f2SDouglas Gregor case tok::raw_identifier: 223*718292f2SDouglas Gregor Tok.StringData = LToken.getRawIdentifierData(); 224*718292f2SDouglas Gregor Tok.StringLength = LToken.getLength(); 225*718292f2SDouglas Gregor Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString()) 226*718292f2SDouglas Gregor .Case("header", MMToken::HeaderKeyword) 227*718292f2SDouglas Gregor .Case("explicit", MMToken::ExplicitKeyword) 228*718292f2SDouglas Gregor .Case("module", MMToken::ModuleKeyword) 229*718292f2SDouglas Gregor .Case("umbrella", MMToken::UmbrellaKeyword) 230*718292f2SDouglas Gregor .Default(MMToken::Identifier); 231*718292f2SDouglas Gregor break; 232*718292f2SDouglas Gregor 233*718292f2SDouglas Gregor case tok::eof: 234*718292f2SDouglas Gregor Tok.Kind = MMToken::EndOfFile; 235*718292f2SDouglas Gregor break; 236*718292f2SDouglas Gregor 237*718292f2SDouglas Gregor case tok::l_brace: 238*718292f2SDouglas Gregor Tok.Kind = MMToken::LBrace; 239*718292f2SDouglas Gregor break; 240*718292f2SDouglas Gregor 241*718292f2SDouglas Gregor case tok::r_brace: 242*718292f2SDouglas Gregor Tok.Kind = MMToken::RBrace; 243*718292f2SDouglas Gregor break; 244*718292f2SDouglas Gregor 245*718292f2SDouglas Gregor case tok::string_literal: { 246*718292f2SDouglas Gregor // Parse the string literal. 247*718292f2SDouglas Gregor LangOptions LangOpts; 248*718292f2SDouglas Gregor StringLiteralParser StringLiteral(<oken, 1, SourceMgr, LangOpts, *Target); 249*718292f2SDouglas Gregor if (StringLiteral.hadError) 250*718292f2SDouglas Gregor goto retry; 251*718292f2SDouglas Gregor 252*718292f2SDouglas Gregor // Copy the string literal into our string data allocator. 253*718292f2SDouglas Gregor unsigned Length = StringLiteral.GetStringLength(); 254*718292f2SDouglas Gregor char *Saved = StringData.Allocate<char>(Length + 1); 255*718292f2SDouglas Gregor memcpy(Saved, StringLiteral.GetString().data(), Length); 256*718292f2SDouglas Gregor Saved[Length] = 0; 257*718292f2SDouglas Gregor 258*718292f2SDouglas Gregor // Form the token. 259*718292f2SDouglas Gregor Tok.Kind = MMToken::StringLiteral; 260*718292f2SDouglas Gregor Tok.StringData = Saved; 261*718292f2SDouglas Gregor Tok.StringLength = Length; 262*718292f2SDouglas Gregor break; 263*718292f2SDouglas Gregor } 264*718292f2SDouglas Gregor 265*718292f2SDouglas Gregor case tok::comment: 266*718292f2SDouglas Gregor goto retry; 267*718292f2SDouglas Gregor 268*718292f2SDouglas Gregor default: 269*718292f2SDouglas Gregor Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token); 270*718292f2SDouglas Gregor HadError = true; 271*718292f2SDouglas Gregor goto retry; 272*718292f2SDouglas Gregor } 273*718292f2SDouglas Gregor 274*718292f2SDouglas Gregor return Result; 275*718292f2SDouglas Gregor } 276*718292f2SDouglas Gregor 277*718292f2SDouglas Gregor void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 278*718292f2SDouglas Gregor unsigned braceDepth = 0; 279*718292f2SDouglas Gregor do { 280*718292f2SDouglas Gregor switch (Tok.Kind) { 281*718292f2SDouglas Gregor case MMToken::EndOfFile: 282*718292f2SDouglas Gregor return; 283*718292f2SDouglas Gregor 284*718292f2SDouglas Gregor case MMToken::LBrace: 285*718292f2SDouglas Gregor if (Tok.is(K) && braceDepth == 0) 286*718292f2SDouglas Gregor return; 287*718292f2SDouglas Gregor 288*718292f2SDouglas Gregor ++braceDepth; 289*718292f2SDouglas Gregor break; 290*718292f2SDouglas Gregor 291*718292f2SDouglas Gregor case MMToken::RBrace: 292*718292f2SDouglas Gregor if (braceDepth > 0) 293*718292f2SDouglas Gregor --braceDepth; 294*718292f2SDouglas Gregor else if (Tok.is(K)) 295*718292f2SDouglas Gregor return; 296*718292f2SDouglas Gregor break; 297*718292f2SDouglas Gregor 298*718292f2SDouglas Gregor default: 299*718292f2SDouglas Gregor if (braceDepth == 0 && Tok.is(K)) 300*718292f2SDouglas Gregor return; 301*718292f2SDouglas Gregor break; 302*718292f2SDouglas Gregor } 303*718292f2SDouglas Gregor 304*718292f2SDouglas Gregor consumeToken(); 305*718292f2SDouglas Gregor } while (true); 306*718292f2SDouglas Gregor } 307*718292f2SDouglas Gregor 308*718292f2SDouglas Gregor /// \brief Parse a module declaration. 309*718292f2SDouglas Gregor /// 310*718292f2SDouglas Gregor /// module-declaration: 311*718292f2SDouglas Gregor /// 'module' identifier { module-member* } 312*718292f2SDouglas Gregor /// 313*718292f2SDouglas Gregor /// module-member: 314*718292f2SDouglas Gregor /// umbrella-declaration 315*718292f2SDouglas Gregor /// header-declaration 316*718292f2SDouglas Gregor /// 'explicit'[opt] module-declaration 317*718292f2SDouglas Gregor void ModuleMapParser::parseModuleDecl() { 318*718292f2SDouglas Gregor assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword)); 319*718292f2SDouglas Gregor 320*718292f2SDouglas Gregor // Parse 'explicit' keyword, if present. 321*718292f2SDouglas Gregor bool Explicit = false; 322*718292f2SDouglas Gregor if (Tok.is(MMToken::ExplicitKeyword)) { 323*718292f2SDouglas Gregor consumeToken(); 324*718292f2SDouglas Gregor Explicit = true; 325*718292f2SDouglas Gregor } 326*718292f2SDouglas Gregor 327*718292f2SDouglas Gregor // Parse 'module' keyword. 328*718292f2SDouglas Gregor if (!Tok.is(MMToken::ModuleKeyword)) { 329*718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), 330*718292f2SDouglas Gregor diag::err_mmap_expected_module_after_explicit); 331*718292f2SDouglas Gregor consumeToken(); 332*718292f2SDouglas Gregor HadError = true; 333*718292f2SDouglas Gregor return; 334*718292f2SDouglas Gregor } 335*718292f2SDouglas Gregor consumeToken(); // 'module' keyword 336*718292f2SDouglas Gregor 337*718292f2SDouglas Gregor // Parse the module name. 338*718292f2SDouglas Gregor if (!Tok.is(MMToken::Identifier)) { 339*718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 340*718292f2SDouglas Gregor HadError = true; 341*718292f2SDouglas Gregor return; 342*718292f2SDouglas Gregor } 343*718292f2SDouglas Gregor StringRef ModuleName = Tok.getString(); 344*718292f2SDouglas Gregor SourceLocation ModuleNameLoc = consumeToken(); 345*718292f2SDouglas Gregor 346*718292f2SDouglas Gregor // Parse the opening brace. 347*718292f2SDouglas Gregor if (!Tok.is(MMToken::LBrace)) { 348*718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 349*718292f2SDouglas Gregor << ModuleName; 350*718292f2SDouglas Gregor HadError = true; 351*718292f2SDouglas Gregor return; 352*718292f2SDouglas Gregor } 353*718292f2SDouglas Gregor SourceLocation LBraceLoc = consumeToken(); 354*718292f2SDouglas Gregor 355*718292f2SDouglas Gregor // Determine whether this (sub)module has already been defined. 356*718292f2SDouglas Gregor llvm::StringMap<Module *> &ModuleSpace 357*718292f2SDouglas Gregor = ActiveModule? ActiveModule->SubModules : Map.Modules; 358*718292f2SDouglas Gregor llvm::StringMap<Module *>::iterator ExistingModule 359*718292f2SDouglas Gregor = ModuleSpace.find(ModuleName); 360*718292f2SDouglas Gregor if (ExistingModule != ModuleSpace.end()) { 361*718292f2SDouglas Gregor Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 362*718292f2SDouglas Gregor << ModuleName; 363*718292f2SDouglas Gregor Diags.Report(ExistingModule->getValue()->DefinitionLoc, 364*718292f2SDouglas Gregor diag::note_mmap_prev_definition); 365*718292f2SDouglas Gregor 366*718292f2SDouglas Gregor // Skip the module definition. 367*718292f2SDouglas Gregor skipUntil(MMToken::RBrace); 368*718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 369*718292f2SDouglas Gregor consumeToken(); 370*718292f2SDouglas Gregor 371*718292f2SDouglas Gregor HadError = true; 372*718292f2SDouglas Gregor return; 373*718292f2SDouglas Gregor } 374*718292f2SDouglas Gregor 375*718292f2SDouglas Gregor // Start defining this module. 376*718292f2SDouglas Gregor ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Explicit); 377*718292f2SDouglas Gregor ModuleSpace[ModuleName] = ActiveModule; 378*718292f2SDouglas Gregor 379*718292f2SDouglas Gregor bool Done = false; 380*718292f2SDouglas Gregor do { 381*718292f2SDouglas Gregor switch (Tok.Kind) { 382*718292f2SDouglas Gregor case MMToken::EndOfFile: 383*718292f2SDouglas Gregor case MMToken::RBrace: 384*718292f2SDouglas Gregor Done = true; 385*718292f2SDouglas Gregor break; 386*718292f2SDouglas Gregor 387*718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 388*718292f2SDouglas Gregor case MMToken::ModuleKeyword: 389*718292f2SDouglas Gregor parseModuleDecl(); 390*718292f2SDouglas Gregor break; 391*718292f2SDouglas Gregor 392*718292f2SDouglas Gregor case MMToken::HeaderKeyword: 393*718292f2SDouglas Gregor parseHeaderDecl(); 394*718292f2SDouglas Gregor break; 395*718292f2SDouglas Gregor 396*718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 397*718292f2SDouglas Gregor parseUmbrellaDecl(); 398*718292f2SDouglas Gregor break; 399*718292f2SDouglas Gregor 400*718292f2SDouglas Gregor default: 401*718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 402*718292f2SDouglas Gregor consumeToken(); 403*718292f2SDouglas Gregor break; 404*718292f2SDouglas Gregor } 405*718292f2SDouglas Gregor } while (!Done); 406*718292f2SDouglas Gregor 407*718292f2SDouglas Gregor if (Tok.is(MMToken::RBrace)) 408*718292f2SDouglas Gregor consumeToken(); 409*718292f2SDouglas Gregor else { 410*718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 411*718292f2SDouglas Gregor Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 412*718292f2SDouglas Gregor HadError = true; 413*718292f2SDouglas Gregor } 414*718292f2SDouglas Gregor 415*718292f2SDouglas Gregor // We're done parsing this module. Pop back to our parent scope. 416*718292f2SDouglas Gregor ActiveModule = ActiveModule->Parent; 417*718292f2SDouglas Gregor } 418*718292f2SDouglas Gregor 419*718292f2SDouglas Gregor /// \brief Parse an umbrella header declaration. 420*718292f2SDouglas Gregor /// 421*718292f2SDouglas Gregor /// umbrella-declaration: 422*718292f2SDouglas Gregor /// 'umbrella' string-literal 423*718292f2SDouglas Gregor void ModuleMapParser::parseUmbrellaDecl() { 424*718292f2SDouglas Gregor assert(Tok.is(MMToken::UmbrellaKeyword)); 425*718292f2SDouglas Gregor SourceLocation UmbrellaLoc = consumeToken(); 426*718292f2SDouglas Gregor 427*718292f2SDouglas Gregor // Parse the header name. 428*718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 429*718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 430*718292f2SDouglas Gregor << "umbrella"; 431*718292f2SDouglas Gregor HadError = true; 432*718292f2SDouglas Gregor return; 433*718292f2SDouglas Gregor } 434*718292f2SDouglas Gregor StringRef FileName = Tok.getString(); 435*718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 436*718292f2SDouglas Gregor 437*718292f2SDouglas Gregor // FIXME: Record the umbrella header. 438*718292f2SDouglas Gregor } 439*718292f2SDouglas Gregor 440*718292f2SDouglas Gregor /// \brief Parse a header declaration. 441*718292f2SDouglas Gregor /// 442*718292f2SDouglas Gregor /// header-declaration: 443*718292f2SDouglas Gregor /// 'header' string-literal 444*718292f2SDouglas Gregor void ModuleMapParser::parseHeaderDecl() { 445*718292f2SDouglas Gregor assert(Tok.is(MMToken::HeaderKeyword)); 446*718292f2SDouglas Gregor SourceLocation HeaderLoc = consumeToken(); 447*718292f2SDouglas Gregor 448*718292f2SDouglas Gregor // Parse the header name. 449*718292f2SDouglas Gregor if (!Tok.is(MMToken::StringLiteral)) { 450*718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 451*718292f2SDouglas Gregor << "header"; 452*718292f2SDouglas Gregor HadError = true; 453*718292f2SDouglas Gregor return; 454*718292f2SDouglas Gregor } 455*718292f2SDouglas Gregor StringRef FileName = Tok.getString(); 456*718292f2SDouglas Gregor SourceLocation FileNameLoc = consumeToken(); 457*718292f2SDouglas Gregor 458*718292f2SDouglas Gregor // FIXME: Record the header. 459*718292f2SDouglas Gregor } 460*718292f2SDouglas Gregor 461*718292f2SDouglas Gregor /// \brief Parse a module map file. 462*718292f2SDouglas Gregor /// 463*718292f2SDouglas Gregor /// module-map-file: 464*718292f2SDouglas Gregor /// module-declaration* 465*718292f2SDouglas Gregor bool ModuleMapParser::parseModuleMapFile() { 466*718292f2SDouglas Gregor do { 467*718292f2SDouglas Gregor switch (Tok.Kind) { 468*718292f2SDouglas Gregor case MMToken::EndOfFile: 469*718292f2SDouglas Gregor return HadError; 470*718292f2SDouglas Gregor 471*718292f2SDouglas Gregor case MMToken::ModuleKeyword: 472*718292f2SDouglas Gregor parseModuleDecl(); 473*718292f2SDouglas Gregor break; 474*718292f2SDouglas Gregor 475*718292f2SDouglas Gregor case MMToken::ExplicitKeyword: 476*718292f2SDouglas Gregor case MMToken::HeaderKeyword: 477*718292f2SDouglas Gregor case MMToken::Identifier: 478*718292f2SDouglas Gregor case MMToken::LBrace: 479*718292f2SDouglas Gregor case MMToken::RBrace: 480*718292f2SDouglas Gregor case MMToken::StringLiteral: 481*718292f2SDouglas Gregor case MMToken::UmbrellaKeyword: 482*718292f2SDouglas Gregor Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 483*718292f2SDouglas Gregor HadError = true; 484*718292f2SDouglas Gregor consumeToken(); 485*718292f2SDouglas Gregor break; 486*718292f2SDouglas Gregor } 487*718292f2SDouglas Gregor } while (true); 488*718292f2SDouglas Gregor 489*718292f2SDouglas Gregor return HadError; 490*718292f2SDouglas Gregor } 491*718292f2SDouglas Gregor 492*718292f2SDouglas Gregor bool ModuleMap::parseModuleMapFile(const FileEntry *File) { 493*718292f2SDouglas Gregor FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User); 494*718292f2SDouglas Gregor const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID); 495*718292f2SDouglas Gregor if (!Buffer) 496*718292f2SDouglas Gregor return true; 497*718292f2SDouglas Gregor 498*718292f2SDouglas Gregor // Parse this module map file. 499*718292f2SDouglas Gregor Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts); 500*718292f2SDouglas Gregor Diags->getClient()->BeginSourceFile(LangOpts); 501*718292f2SDouglas Gregor ModuleMapParser Parser(L, *SourceMgr, *Diags, *this); 502*718292f2SDouglas Gregor bool Result = Parser.parseModuleMapFile(); 503*718292f2SDouglas Gregor Diags->getClient()->EndSourceFile(); 504*718292f2SDouglas Gregor 505*718292f2SDouglas Gregor return Result; 506*718292f2SDouglas Gregor } 507