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