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