ModuleMap.cpp revision 7f5fd8e79c5e528da0307792efd354ffa202722d
1//===--- ModuleMap.cpp - Describe the layout of modules ---------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines the ModuleMap implementation, which describes the layout 11// of a module as it relates to headers. 12// 13//===----------------------------------------------------------------------===// 14#include "clang/Lex/ModuleMap.h" 15#include "clang/Lex/Lexer.h" 16#include "clang/Lex/LiteralSupport.h" 17#include "clang/Lex/LexDiagnostic.h" 18#include "clang/Basic/Diagnostic.h" 19#include "clang/Basic/FileManager.h" 20#include "clang/Basic/TargetInfo.h" 21#include "clang/Basic/TargetOptions.h" 22#include "llvm/Support/Allocator.h" 23#include "llvm/Support/Host.h" 24#include "llvm/Support/PathV2.h" 25#include "llvm/Support/raw_ostream.h" 26#include "llvm/ADT/StringRef.h" 27#include "llvm/ADT/StringSwitch.h" 28using namespace clang; 29 30//----------------------------------------------------------------------------// 31// Module 32//----------------------------------------------------------------------------// 33 34ModuleMap::Module::~Module() { 35 for (llvm::StringMap<Module *>::iterator I = SubModules.begin(), 36 IEnd = SubModules.end(); 37 I != IEnd; ++I) { 38 delete I->getValue(); 39 } 40 41} 42 43std::string ModuleMap::Module::getFullModuleName() const { 44 llvm::SmallVector<StringRef, 2> Names; 45 46 // Build up the set of module names (from innermost to outermost). 47 for (const Module *M = this; M; M = M->Parent) 48 Names.push_back(M->Name); 49 50 std::string Result; 51 for (llvm::SmallVector<StringRef, 2>::reverse_iterator I = Names.rbegin(), 52 IEnd = Names.rend(); 53 I != IEnd; ++I) { 54 if (!Result.empty()) 55 Result += '.'; 56 57 Result += *I; 58 } 59 60 return Result; 61} 62 63StringRef ModuleMap::Module::getTopLevelModuleName() const { 64 const Module *Top = this; 65 while (Top->Parent) 66 Top = Top->Parent; 67 68 return Top->Name; 69} 70 71static void indent(llvm::raw_ostream &OS, unsigned Spaces) { 72 OS << std::string(Spaces, ' '); 73} 74 75void ModuleMap::Module::print(llvm::raw_ostream &OS, unsigned Indent) const { 76 indent(OS, Indent); 77 if (IsFramework) 78 OS << "framework "; 79 if (IsExplicit) 80 OS << "explicit "; 81 OS << "module " << Name << " {\n"; 82 83 if (UmbrellaHeader) { 84 indent(OS, Indent + 2); 85 OS << "umbrella \""; 86 OS.write_escaped(UmbrellaHeader->getName()); 87 OS << "\"\n"; 88 } 89 90 for (unsigned I = 0, N = Headers.size(); I != N; ++I) { 91 indent(OS, Indent + 2); 92 OS << "header \""; 93 OS.write_escaped(Headers[I]->getName()); 94 OS << "\"\n"; 95 } 96 97 for (llvm::StringMap<Module *>::const_iterator MI = SubModules.begin(), 98 MIEnd = SubModules.end(); 99 MI != MIEnd; ++MI) 100 MI->getValue()->print(OS, Indent + 2); 101 102 indent(OS, Indent); 103 OS << "}\n"; 104} 105 106void ModuleMap::Module::dump() const { 107 print(llvm::errs()); 108} 109 110//----------------------------------------------------------------------------// 111// Module map 112//----------------------------------------------------------------------------// 113 114ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) { 115 llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs); 116 Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>( 117 new DiagnosticsEngine(DiagIDs)); 118 Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true); 119 SourceMgr = new SourceManager(*Diags, FileMgr); 120} 121 122ModuleMap::~ModuleMap() { 123 for (llvm::StringMap<Module *>::iterator I = Modules.begin(), 124 IEnd = Modules.end(); 125 I != IEnd; ++I) { 126 delete I->getValue(); 127 } 128 129 delete SourceMgr; 130} 131 132ModuleMap::Module *ModuleMap::findModuleForHeader(const FileEntry *File) { 133 llvm::DenseMap<const FileEntry *, Module *>::iterator Known 134 = Headers.find(File); 135 if (Known != Headers.end()) 136 return Known->second; 137 138 const DirectoryEntry *Dir = File->getDir(); 139 llvm::DenseMap<const DirectoryEntry *, Module *>::iterator KnownDir 140 = UmbrellaDirs.find(Dir); 141 if (KnownDir != UmbrellaDirs.end()) 142 return KnownDir->second; 143 144 // Walk up the directory hierarchy looking for umbrella headers. 145 llvm::SmallVector<const DirectoryEntry *, 2> SkippedDirs; 146 StringRef DirName = Dir->getName(); 147 do { 148 // Retrieve our parent path. 149 DirName = llvm::sys::path::parent_path(DirName); 150 if (DirName.empty()) 151 break; 152 153 // Resolve the parent path to a directory entry. 154 Dir = SourceMgr->getFileManager().getDirectory(DirName); 155 if (!Dir) 156 break; 157 158 KnownDir = UmbrellaDirs.find(Dir); 159 if (KnownDir != UmbrellaDirs.end()) { 160 Module *Result = KnownDir->second; 161 162 // Record each of the directories we stepped through as being part of 163 // the module we found, since the umbrella header covers them all. 164 for (unsigned I = 0, N = SkippedDirs.size(); I != N; ++I) 165 UmbrellaDirs[SkippedDirs[I]] = Result; 166 167 return Result; 168 } 169 170 SkippedDirs.push_back(Dir); 171 } while (true); 172 173 return 0; 174} 175 176ModuleMap::Module *ModuleMap::findModule(StringRef Name) { 177 llvm::StringMap<Module *>::iterator Known = Modules.find(Name); 178 if (Known != Modules.end()) 179 return Known->getValue(); 180 181 return 0; 182} 183 184ModuleMap::Module * 185ModuleMap::inferFrameworkModule(StringRef ModuleName, 186 const DirectoryEntry *FrameworkDir) { 187 // Check whether we've already found this module. 188 if (Module *Module = findModule(ModuleName)) 189 return Module; 190 191 // Look for an umbrella header. 192 llvm::SmallString<128> UmbrellaName = StringRef(FrameworkDir->getName()); 193 llvm::sys::path::append(UmbrellaName, "Headers"); 194 llvm::sys::path::append(UmbrellaName, ModuleName + ".h"); 195 const FileEntry *UmbrellaHeader 196 = SourceMgr->getFileManager().getFile(UmbrellaName); 197 198 // FIXME: If there's no umbrella header, we could probably scan the 199 // framework to load *everything*. But, it's not clear that this is a good 200 // idea. 201 if (!UmbrellaHeader) 202 return 0; 203 204 Module *Result = new Module(ModuleName, SourceLocation(), 205 /*IsFramework=*/true); 206 Result->UmbrellaHeader = UmbrellaHeader; 207 Headers[UmbrellaHeader] = Result; 208 UmbrellaDirs[FrameworkDir] = Result; 209 Modules[ModuleName] = Result; 210 return Result; 211} 212 213const FileEntry * 214ModuleMap::getContainingModuleMapFile(ModuleMap::Module *Module) { 215 if (Module->DefinitionLoc.isInvalid() || !SourceMgr) 216 return 0; 217 218 return SourceMgr->getFileEntryForID( 219 SourceMgr->getFileID(Module->DefinitionLoc)); 220} 221 222void ModuleMap::dump() { 223 llvm::errs() << "Modules:"; 224 for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 225 MEnd = Modules.end(); 226 M != MEnd; ++M) 227 M->getValue()->print(llvm::errs(), 2); 228 229 llvm::errs() << "Headers:"; 230 for (llvm::DenseMap<const FileEntry *, Module *>::iterator 231 H = Headers.begin(), 232 HEnd = Headers.end(); 233 H != HEnd; ++H) { 234 llvm::errs() << " \"" << H->first->getName() << "\" -> " 235 << H->second->getFullModuleName() << "\n"; 236 } 237} 238 239//----------------------------------------------------------------------------// 240// Module map file parser 241//----------------------------------------------------------------------------// 242 243namespace clang { 244 /// \brief A token in a module map file. 245 struct MMToken { 246 enum TokenKind { 247 EndOfFile, 248 HeaderKeyword, 249 Identifier, 250 ExplicitKeyword, 251 FrameworkKeyword, 252 ModuleKeyword, 253 UmbrellaKeyword, 254 StringLiteral, 255 LBrace, 256 RBrace 257 } Kind; 258 259 unsigned Location; 260 unsigned StringLength; 261 const char *StringData; 262 263 void clear() { 264 Kind = EndOfFile; 265 Location = 0; 266 StringLength = 0; 267 StringData = 0; 268 } 269 270 bool is(TokenKind K) const { return Kind == K; } 271 272 SourceLocation getLocation() const { 273 return SourceLocation::getFromRawEncoding(Location); 274 } 275 276 StringRef getString() const { 277 return StringRef(StringData, StringLength); 278 } 279 }; 280 281 class ModuleMapParser { 282 Lexer &L; 283 SourceManager &SourceMgr; 284 DiagnosticsEngine &Diags; 285 ModuleMap ⤅ 286 287 /// \brief The directory that this module map resides in. 288 const DirectoryEntry *Directory; 289 290 /// \brief Whether an error occurred. 291 bool HadError; 292 293 /// \brief Default target information, used only for string literal 294 /// parsing. 295 TargetInfo *Target; 296 297 /// \brief Stores string data for the various string literals referenced 298 /// during parsing. 299 llvm::BumpPtrAllocator StringData; 300 301 /// \brief The current token. 302 MMToken Tok; 303 304 /// \brief The active module. 305 ModuleMap::Module *ActiveModule; 306 307 /// \brief Consume the current token and return its location. 308 SourceLocation consumeToken(); 309 310 /// \brief Skip tokens until we reach the a token with the given kind 311 /// (or the end of the file). 312 void skipUntil(MMToken::TokenKind K); 313 314 void parseModuleDecl(); 315 void parseUmbrellaDecl(); 316 void parseHeaderDecl(); 317 318 public: 319 typedef ModuleMap::Module Module; 320 321 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 322 DiagnosticsEngine &Diags, 323 ModuleMap &Map, 324 const DirectoryEntry *Directory) 325 : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map), 326 Directory(Directory), HadError(false), ActiveModule(0) 327 { 328 TargetOptions TargetOpts; 329 TargetOpts.Triple = llvm::sys::getDefaultTargetTriple(); 330 Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); 331 332 Tok.clear(); 333 consumeToken(); 334 } 335 336 bool parseModuleMapFile(); 337 }; 338} 339 340SourceLocation ModuleMapParser::consumeToken() { 341retry: 342 SourceLocation Result = Tok.getLocation(); 343 Tok.clear(); 344 345 Token LToken; 346 L.LexFromRawLexer(LToken); 347 Tok.Location = LToken.getLocation().getRawEncoding(); 348 switch (LToken.getKind()) { 349 case tok::raw_identifier: 350 Tok.StringData = LToken.getRawIdentifierData(); 351 Tok.StringLength = LToken.getLength(); 352 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString()) 353 .Case("header", MMToken::HeaderKeyword) 354 .Case("explicit", MMToken::ExplicitKeyword) 355 .Case("framework", MMToken::FrameworkKeyword) 356 .Case("module", MMToken::ModuleKeyword) 357 .Case("umbrella", MMToken::UmbrellaKeyword) 358 .Default(MMToken::Identifier); 359 break; 360 361 case tok::eof: 362 Tok.Kind = MMToken::EndOfFile; 363 break; 364 365 case tok::l_brace: 366 Tok.Kind = MMToken::LBrace; 367 break; 368 369 case tok::r_brace: 370 Tok.Kind = MMToken::RBrace; 371 break; 372 373 case tok::string_literal: { 374 // Parse the string literal. 375 LangOptions LangOpts; 376 StringLiteralParser StringLiteral(<oken, 1, SourceMgr, LangOpts, *Target); 377 if (StringLiteral.hadError) 378 goto retry; 379 380 // Copy the string literal into our string data allocator. 381 unsigned Length = StringLiteral.GetStringLength(); 382 char *Saved = StringData.Allocate<char>(Length + 1); 383 memcpy(Saved, StringLiteral.GetString().data(), Length); 384 Saved[Length] = 0; 385 386 // Form the token. 387 Tok.Kind = MMToken::StringLiteral; 388 Tok.StringData = Saved; 389 Tok.StringLength = Length; 390 break; 391 } 392 393 case tok::comment: 394 goto retry; 395 396 default: 397 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token); 398 HadError = true; 399 goto retry; 400 } 401 402 return Result; 403} 404 405void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 406 unsigned braceDepth = 0; 407 do { 408 switch (Tok.Kind) { 409 case MMToken::EndOfFile: 410 return; 411 412 case MMToken::LBrace: 413 if (Tok.is(K) && braceDepth == 0) 414 return; 415 416 ++braceDepth; 417 break; 418 419 case MMToken::RBrace: 420 if (braceDepth > 0) 421 --braceDepth; 422 else if (Tok.is(K)) 423 return; 424 break; 425 426 default: 427 if (braceDepth == 0 && Tok.is(K)) 428 return; 429 break; 430 } 431 432 consumeToken(); 433 } while (true); 434} 435 436/// \brief Parse a module declaration. 437/// 438/// module-declaration: 439/// 'framework'[opt] 'module' identifier { module-member* } 440/// 441/// module-member: 442/// umbrella-declaration 443/// header-declaration 444/// 'explicit'[opt] module-declaration 445void ModuleMapParser::parseModuleDecl() { 446 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword) || 447 Tok.is(MMToken::FrameworkKeyword)); 448 449 // Parse 'framework' or 'explicit' keyword, if present. 450 bool Framework = false; 451 bool Explicit = false; 452 453 if (Tok.is(MMToken::FrameworkKeyword)) { 454 consumeToken(); 455 Framework = true; 456 } 457 // Parse 'explicit' keyword, if present. 458 else if (Tok.is(MMToken::ExplicitKeyword)) { 459 consumeToken(); 460 Explicit = true; 461 } 462 463 // Parse 'module' keyword. 464 if (!Tok.is(MMToken::ModuleKeyword)) { 465 Diags.Report(Tok.getLocation(), 466 diag::err_mmap_expected_module_after_explicit); 467 consumeToken(); 468 HadError = true; 469 return; 470 } 471 consumeToken(); // 'module' keyword 472 473 // Parse the module name. 474 if (!Tok.is(MMToken::Identifier)) { 475 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 476 HadError = true; 477 return; 478 } 479 StringRef ModuleName = Tok.getString(); 480 SourceLocation ModuleNameLoc = consumeToken(); 481 482 // Parse the opening brace. 483 if (!Tok.is(MMToken::LBrace)) { 484 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 485 << ModuleName; 486 HadError = true; 487 return; 488 } 489 SourceLocation LBraceLoc = consumeToken(); 490 491 // Determine whether this (sub)module has already been defined. 492 llvm::StringMap<Module *> &ModuleSpace 493 = ActiveModule? ActiveModule->SubModules : Map.Modules; 494 llvm::StringMap<Module *>::iterator ExistingModule 495 = ModuleSpace.find(ModuleName); 496 if (ExistingModule != ModuleSpace.end()) { 497 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 498 << ModuleName; 499 Diags.Report(ExistingModule->getValue()->DefinitionLoc, 500 diag::note_mmap_prev_definition); 501 502 // Skip the module definition. 503 skipUntil(MMToken::RBrace); 504 if (Tok.is(MMToken::RBrace)) 505 consumeToken(); 506 507 HadError = true; 508 return; 509 } 510 511 // Start defining this module. 512 ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Framework, 513 Explicit); 514 ModuleSpace[ModuleName] = ActiveModule; 515 516 bool Done = false; 517 do { 518 switch (Tok.Kind) { 519 case MMToken::EndOfFile: 520 case MMToken::RBrace: 521 Done = true; 522 break; 523 524 case MMToken::ExplicitKeyword: 525 case MMToken::ModuleKeyword: 526 parseModuleDecl(); 527 break; 528 529 case MMToken::HeaderKeyword: 530 parseHeaderDecl(); 531 break; 532 533 case MMToken::UmbrellaKeyword: 534 parseUmbrellaDecl(); 535 break; 536 537 default: 538 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 539 consumeToken(); 540 break; 541 } 542 } while (!Done); 543 544 if (Tok.is(MMToken::RBrace)) 545 consumeToken(); 546 else { 547 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 548 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 549 HadError = true; 550 } 551 552 // We're done parsing this module. Pop back to our parent scope. 553 ActiveModule = ActiveModule->Parent; 554} 555 556/// \brief Parse an umbrella header declaration. 557/// 558/// umbrella-declaration: 559/// 'umbrella' string-literal 560void ModuleMapParser::parseUmbrellaDecl() { 561 assert(Tok.is(MMToken::UmbrellaKeyword)); 562 SourceLocation UmbrellaLoc = consumeToken(); 563 564 // Parse the header name. 565 if (!Tok.is(MMToken::StringLiteral)) { 566 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 567 << "umbrella"; 568 HadError = true; 569 return; 570 } 571 StringRef FileName = Tok.getString(); 572 SourceLocation FileNameLoc = consumeToken(); 573 574 // Check whether we already have an umbrella header. 575 if (ActiveModule->UmbrellaHeader) { 576 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict) 577 << ActiveModule->getFullModuleName() 578 << ActiveModule->UmbrellaHeader->getName(); 579 HadError = true; 580 return; 581 } 582 583 // Only top-level modules can have umbrella headers. 584 if (ActiveModule->Parent) { 585 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule) 586 << ActiveModule->getFullModuleName(); 587 HadError = true; 588 return; 589 } 590 591 // Look for this file. 592 llvm::SmallString<128> PathName; 593 const FileEntry *File = 0; 594 595 if (llvm::sys::path::is_absolute(FileName)) { 596 PathName = FileName; 597 File = SourceMgr.getFileManager().getFile(PathName); 598 } else { 599 // Search for the header file within the search directory. 600 PathName += Directory->getName(); 601 unsigned PathLength = PathName.size(); 602 if (ActiveModule->isPartOfFramework()) { 603 // Check whether this file is in the public headers. 604 llvm::sys::path::append(PathName, "Headers"); 605 llvm::sys::path::append(PathName, FileName); 606 File = SourceMgr.getFileManager().getFile(PathName); 607 608 if (!File) { 609 // Check whether this file is in the private headers. 610 PathName.resize(PathLength); 611 llvm::sys::path::append(PathName, "PrivateHeaders"); 612 llvm::sys::path::append(PathName, FileName); 613 File = SourceMgr.getFileManager().getFile(PathName); 614 } 615 616 // FIXME: Deal with subframeworks. 617 } else { 618 // Lookup for normal headers. 619 llvm::sys::path::append(PathName, FileName); 620 File = SourceMgr.getFileManager().getFile(PathName); 621 } 622 } 623 624 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 625 // Come up with a lazy way to do this. 626 if (File) { 627 if (const Module *OwningModule = Map.Headers[File]) { 628 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 629 << FileName << OwningModule->getFullModuleName(); 630 HadError = true; 631 } else if ((OwningModule = Map.UmbrellaDirs[Directory])) { 632 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_clash) 633 << OwningModule->getFullModuleName(); 634 HadError = true; 635 } else { 636 // Record this umbrella header. 637 ActiveModule->UmbrellaHeader = File; 638 Map.Headers[File] = ActiveModule; 639 Map.UmbrellaDirs[Directory] = ActiveModule; 640 } 641 } else { 642 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 643 << true << FileName; 644 HadError = true; 645 } 646} 647 648/// \brief Parse a header declaration. 649/// 650/// header-declaration: 651/// 'header' string-literal 652void ModuleMapParser::parseHeaderDecl() { 653 assert(Tok.is(MMToken::HeaderKeyword)); 654 consumeToken(); 655 656 // Parse the header name. 657 if (!Tok.is(MMToken::StringLiteral)) { 658 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 659 << "header"; 660 HadError = true; 661 return; 662 } 663 StringRef FileName = Tok.getString(); 664 SourceLocation FileNameLoc = consumeToken(); 665 666 // Look for this file. 667 llvm::SmallString<128> PathName; 668 if (llvm::sys::path::is_relative(FileName)) { 669 // FIXME: Change this search to also look for private headers! 670 PathName += Directory->getName(); 671 672 if (ActiveModule->isPartOfFramework()) 673 llvm::sys::path::append(PathName, "Headers"); 674 } 675 676 llvm::sys::path::append(PathName, FileName); 677 678 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 679 // Come up with a lazy way to do this. 680 if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) { 681 if (const Module *OwningModule = Map.Headers[File]) { 682 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 683 << FileName << OwningModule->getFullModuleName(); 684 HadError = true; 685 } else { 686 // Record this file. 687 ActiveModule->Headers.push_back(File); 688 Map.Headers[File] = ActiveModule; 689 } 690 } else { 691 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 692 << false << FileName; 693 HadError = true; 694 } 695} 696 697/// \brief Parse a module map file. 698/// 699/// module-map-file: 700/// module-declaration* 701bool ModuleMapParser::parseModuleMapFile() { 702 do { 703 switch (Tok.Kind) { 704 case MMToken::EndOfFile: 705 return HadError; 706 707 case MMToken::ModuleKeyword: 708 case MMToken::FrameworkKeyword: 709 parseModuleDecl(); 710 break; 711 712 case MMToken::ExplicitKeyword: 713 case MMToken::HeaderKeyword: 714 case MMToken::Identifier: 715 case MMToken::LBrace: 716 case MMToken::RBrace: 717 case MMToken::StringLiteral: 718 case MMToken::UmbrellaKeyword: 719 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 720 HadError = true; 721 consumeToken(); 722 break; 723 } 724 } while (true); 725 726 return HadError; 727} 728 729bool ModuleMap::parseModuleMapFile(const FileEntry *File) { 730 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User); 731 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID); 732 if (!Buffer) 733 return true; 734 735 // Parse this module map file. 736 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts); 737 Diags->getClient()->BeginSourceFile(LangOpts); 738 ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir()); 739 bool Result = Parser.parseModuleMapFile(); 740 Diags->getClient()->EndSourceFile(); 741 742 return Result; 743} 744