ModuleMap.cpp revision 484535e45b4d301847a157e943c7823da5d40884
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 34std::string ModuleMap::Module::getFullModuleName() const { 35 llvm::SmallVector<StringRef, 2> Names; 36 37 // Build up the set of module names (from innermost to outermost). 38 for (const Module *M = this; M; M = M->Parent) 39 Names.push_back(M->Name); 40 41 std::string Result; 42 for (llvm::SmallVector<StringRef, 2>::reverse_iterator I = Names.rbegin(), 43 IEnd = Names.rend(); 44 I != IEnd; ++I) { 45 if (!Result.empty()) 46 Result += '.'; 47 48 Result += *I; 49 } 50 51 return Result; 52} 53 54StringRef ModuleMap::Module::getTopLevelModuleName() const { 55 const Module *Top = this; 56 while (Top->Parent) 57 Top = Top->Parent; 58 59 return Top->Name; 60} 61 62//----------------------------------------------------------------------------// 63// Module map 64//----------------------------------------------------------------------------// 65 66ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC) { 67 llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs); 68 Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>( 69 new DiagnosticsEngine(DiagIDs)); 70 Diags->setClient(DC.clone(*Diags), /*ShouldOwnClient=*/true); 71 SourceMgr = new SourceManager(*Diags, FileMgr); 72} 73 74ModuleMap::~ModuleMap() { 75 delete SourceMgr; 76} 77 78ModuleMap::Module *ModuleMap::findModuleForHeader(const FileEntry *File) { 79 llvm::DenseMap<const FileEntry *, Module *>::iterator Known 80 = Headers.find(File); 81 if (Known != Headers.end()) 82 return Known->second; 83 84 return 0; 85} 86 87ModuleMap::Module *ModuleMap::findModule(StringRef Name) { 88 llvm::StringMap<Module *>::iterator Known = Modules.find(Name); 89 if (Known != Modules.end()) 90 return Known->getValue(); 91 92 return 0; 93} 94 95static void indent(llvm::raw_ostream &OS, unsigned Spaces) { 96 OS << std::string(' ', Spaces); 97} 98 99static void dumpModule(llvm::raw_ostream &OS, ModuleMap::Module *M, 100 unsigned Indent) { 101 indent(OS, Indent); 102 if (M->IsExplicit) 103 OS << "explicit "; 104 OS << M->Name << " {\n"; 105 106 if (M->UmbrellaHeader) { 107 indent(OS, Indent + 2); 108 OS << "umbrella \"" << M->UmbrellaHeader->getName() << "\"\n"; 109 } 110 111 for (unsigned I = 0, N = M->Headers.size(); I != N; ++I) { 112 indent(OS, Indent + 2); 113 OS << "header \"" << M->Headers[I]->getName() << "\"\n"; 114 } 115 116 for (llvm::StringMap<ModuleMap::Module *>::iterator 117 MI = M->SubModules.begin(), 118 MIEnd = M->SubModules.end(); 119 MI != MIEnd; ++MI) 120 dumpModule(llvm::errs(), MI->getValue(), Indent + 2); 121 122 indent(OS, Indent); 123 OS << "}\n"; 124} 125 126void ModuleMap::dump() { 127 llvm::errs() << "Modules:"; 128 for (llvm::StringMap<Module *>::iterator M = Modules.begin(), 129 MEnd = Modules.end(); 130 M != MEnd; ++M) 131 dumpModule(llvm::errs(), M->getValue(), 2); 132 133 llvm::errs() << "Headers:"; 134 for (llvm::DenseMap<const FileEntry *, Module *>::iterator 135 H = Headers.begin(), 136 HEnd = Headers.end(); 137 H != HEnd; ++H) { 138 llvm::errs() << " \"" << H->first->getName() << "\" -> " 139 << H->second->getFullModuleName() << "\n"; 140 } 141} 142 143//----------------------------------------------------------------------------// 144// Module map file parser 145//----------------------------------------------------------------------------// 146 147namespace clang { 148 /// \brief A token in a module map file. 149 struct MMToken { 150 enum TokenKind { 151 EndOfFile, 152 HeaderKeyword, 153 Identifier, 154 ExplicitKeyword, 155 ModuleKeyword, 156 UmbrellaKeyword, 157 StringLiteral, 158 LBrace, 159 RBrace 160 } Kind; 161 162 unsigned Location; 163 unsigned StringLength; 164 const char *StringData; 165 166 void clear() { 167 Kind = EndOfFile; 168 Location = 0; 169 StringLength = 0; 170 StringData = 0; 171 } 172 173 bool is(TokenKind K) const { return Kind == K; } 174 175 SourceLocation getLocation() const { 176 return SourceLocation::getFromRawEncoding(Location); 177 } 178 179 StringRef getString() const { 180 return StringRef(StringData, StringLength); 181 } 182 }; 183 184 class ModuleMapParser { 185 Lexer &L; 186 SourceManager &SourceMgr; 187 DiagnosticsEngine &Diags; 188 ModuleMap ⤅ 189 190 /// \brief The directory that this module map resides in. 191 const DirectoryEntry *Directory; 192 193 /// \brief Whether an error occurred. 194 bool HadError; 195 196 /// \brief Default target information, used only for string literal 197 /// parsing. 198 TargetInfo *Target; 199 200 /// \brief Stores string data for the various string literals referenced 201 /// during parsing. 202 llvm::BumpPtrAllocator StringData; 203 204 /// \brief The current token. 205 MMToken Tok; 206 207 /// \brief The active module. 208 ModuleMap::Module *ActiveModule; 209 210 /// \brief Consume the current token and return its location. 211 SourceLocation consumeToken(); 212 213 /// \brief Skip tokens until we reach the a token with the given kind 214 /// (or the end of the file). 215 void skipUntil(MMToken::TokenKind K); 216 217 void parseModuleDecl(); 218 void parseUmbrellaDecl(); 219 void parseHeaderDecl(); 220 221 public: 222 typedef ModuleMap::Module Module; 223 224 explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, 225 DiagnosticsEngine &Diags, 226 ModuleMap &Map, 227 const DirectoryEntry *Directory) 228 : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map), 229 Directory(Directory), HadError(false), ActiveModule(0) 230 { 231 TargetOptions TargetOpts; 232 TargetOpts.Triple = llvm::sys::getDefaultTargetTriple(); 233 Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts); 234 235 Tok.clear(); 236 consumeToken(); 237 } 238 239 bool parseModuleMapFile(); 240 }; 241} 242 243SourceLocation ModuleMapParser::consumeToken() { 244retry: 245 SourceLocation Result = Tok.getLocation(); 246 Tok.clear(); 247 248 Token LToken; 249 L.LexFromRawLexer(LToken); 250 Tok.Location = LToken.getLocation().getRawEncoding(); 251 switch (LToken.getKind()) { 252 case tok::raw_identifier: 253 Tok.StringData = LToken.getRawIdentifierData(); 254 Tok.StringLength = LToken.getLength(); 255 Tok.Kind = llvm::StringSwitch<MMToken::TokenKind>(Tok.getString()) 256 .Case("header", MMToken::HeaderKeyword) 257 .Case("explicit", MMToken::ExplicitKeyword) 258 .Case("module", MMToken::ModuleKeyword) 259 .Case("umbrella", MMToken::UmbrellaKeyword) 260 .Default(MMToken::Identifier); 261 break; 262 263 case tok::eof: 264 Tok.Kind = MMToken::EndOfFile; 265 break; 266 267 case tok::l_brace: 268 Tok.Kind = MMToken::LBrace; 269 break; 270 271 case tok::r_brace: 272 Tok.Kind = MMToken::RBrace; 273 break; 274 275 case tok::string_literal: { 276 // Parse the string literal. 277 LangOptions LangOpts; 278 StringLiteralParser StringLiteral(<oken, 1, SourceMgr, LangOpts, *Target); 279 if (StringLiteral.hadError) 280 goto retry; 281 282 // Copy the string literal into our string data allocator. 283 unsigned Length = StringLiteral.GetStringLength(); 284 char *Saved = StringData.Allocate<char>(Length + 1); 285 memcpy(Saved, StringLiteral.GetString().data(), Length); 286 Saved[Length] = 0; 287 288 // Form the token. 289 Tok.Kind = MMToken::StringLiteral; 290 Tok.StringData = Saved; 291 Tok.StringLength = Length; 292 break; 293 } 294 295 case tok::comment: 296 goto retry; 297 298 default: 299 Diags.Report(LToken.getLocation(), diag::err_mmap_unknown_token); 300 HadError = true; 301 goto retry; 302 } 303 304 return Result; 305} 306 307void ModuleMapParser::skipUntil(MMToken::TokenKind K) { 308 unsigned braceDepth = 0; 309 do { 310 switch (Tok.Kind) { 311 case MMToken::EndOfFile: 312 return; 313 314 case MMToken::LBrace: 315 if (Tok.is(K) && braceDepth == 0) 316 return; 317 318 ++braceDepth; 319 break; 320 321 case MMToken::RBrace: 322 if (braceDepth > 0) 323 --braceDepth; 324 else if (Tok.is(K)) 325 return; 326 break; 327 328 default: 329 if (braceDepth == 0 && Tok.is(K)) 330 return; 331 break; 332 } 333 334 consumeToken(); 335 } while (true); 336} 337 338/// \brief Parse a module declaration. 339/// 340/// module-declaration: 341/// 'module' identifier { module-member* } 342/// 343/// module-member: 344/// umbrella-declaration 345/// header-declaration 346/// 'explicit'[opt] module-declaration 347void ModuleMapParser::parseModuleDecl() { 348 assert(Tok.is(MMToken::ExplicitKeyword) || Tok.is(MMToken::ModuleKeyword)); 349 350 // Parse 'explicit' keyword, if present. 351 bool Explicit = false; 352 if (Tok.is(MMToken::ExplicitKeyword)) { 353 consumeToken(); 354 Explicit = true; 355 } 356 357 // Parse 'module' keyword. 358 if (!Tok.is(MMToken::ModuleKeyword)) { 359 Diags.Report(Tok.getLocation(), 360 diag::err_mmap_expected_module_after_explicit); 361 consumeToken(); 362 HadError = true; 363 return; 364 } 365 consumeToken(); // 'module' keyword 366 367 // Parse the module name. 368 if (!Tok.is(MMToken::Identifier)) { 369 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module_name); 370 HadError = true; 371 return; 372 } 373 StringRef ModuleName = Tok.getString(); 374 SourceLocation ModuleNameLoc = consumeToken(); 375 376 // Parse the opening brace. 377 if (!Tok.is(MMToken::LBrace)) { 378 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_lbrace) 379 << ModuleName; 380 HadError = true; 381 return; 382 } 383 SourceLocation LBraceLoc = consumeToken(); 384 385 // Determine whether this (sub)module has already been defined. 386 llvm::StringMap<Module *> &ModuleSpace 387 = ActiveModule? ActiveModule->SubModules : Map.Modules; 388 llvm::StringMap<Module *>::iterator ExistingModule 389 = ModuleSpace.find(ModuleName); 390 if (ExistingModule != ModuleSpace.end()) { 391 Diags.Report(ModuleNameLoc, diag::err_mmap_module_redefinition) 392 << ModuleName; 393 Diags.Report(ExistingModule->getValue()->DefinitionLoc, 394 diag::note_mmap_prev_definition); 395 396 // Skip the module definition. 397 skipUntil(MMToken::RBrace); 398 if (Tok.is(MMToken::RBrace)) 399 consumeToken(); 400 401 HadError = true; 402 return; 403 } 404 405 // Start defining this module. 406 ActiveModule = new Module(ModuleName, ModuleNameLoc, ActiveModule, Explicit); 407 ModuleSpace[ModuleName] = ActiveModule; 408 409 bool Done = false; 410 do { 411 switch (Tok.Kind) { 412 case MMToken::EndOfFile: 413 case MMToken::RBrace: 414 Done = true; 415 break; 416 417 case MMToken::ExplicitKeyword: 418 case MMToken::ModuleKeyword: 419 parseModuleDecl(); 420 break; 421 422 case MMToken::HeaderKeyword: 423 parseHeaderDecl(); 424 break; 425 426 case MMToken::UmbrellaKeyword: 427 parseUmbrellaDecl(); 428 break; 429 430 default: 431 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_member); 432 consumeToken(); 433 break; 434 } 435 } while (!Done); 436 437 if (Tok.is(MMToken::RBrace)) 438 consumeToken(); 439 else { 440 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_rbrace); 441 Diags.Report(LBraceLoc, diag::note_mmap_lbrace_match); 442 HadError = true; 443 } 444 445 // We're done parsing this module. Pop back to our parent scope. 446 ActiveModule = ActiveModule->Parent; 447} 448 449/// \brief Parse an umbrella header declaration. 450/// 451/// umbrella-declaration: 452/// 'umbrella' string-literal 453void ModuleMapParser::parseUmbrellaDecl() { 454 assert(Tok.is(MMToken::UmbrellaKeyword)); 455 SourceLocation UmbrellaLoc = consumeToken(); 456 457 // Parse the header name. 458 if (!Tok.is(MMToken::StringLiteral)) { 459 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 460 << "umbrella"; 461 HadError = true; 462 return; 463 } 464 StringRef FileName = Tok.getString(); 465 SourceLocation FileNameLoc = consumeToken(); 466 467 // Check whether we already have an umbrella header. 468 if (ActiveModule->UmbrellaHeader) { 469 Diags.Report(FileNameLoc, diag::err_mmap_umbrella_header_conflict) 470 << ActiveModule->getFullModuleName() 471 << ActiveModule->UmbrellaHeader->getName(); 472 HadError = true; 473 return; 474 } 475 476 // Only top-level modules can have umbrella headers. 477 if (ActiveModule->Parent) { 478 Diags.Report(UmbrellaLoc, diag::err_mmap_umbrella_header_submodule) 479 << ActiveModule->getFullModuleName(); 480 HadError = true; 481 return; 482 } 483 484 // Look for this file. 485 llvm::SmallString<128> PathName; 486 PathName += Directory->getName(); 487 llvm::sys::path::append(PathName, FileName); 488 489 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 490 // Come up with a lazy way to do this. 491 if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) { 492 if (const Module *OwningModule = Map.Headers[File]) { 493 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 494 << FileName << OwningModule->getFullModuleName(); 495 HadError = true; 496 } else { 497 // Record this umbrella header. 498 ActiveModule->UmbrellaHeader = File; 499 Map.Headers[File] = ActiveModule; 500 } 501 } else { 502 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 503 << true << FileName; 504 HadError = true; 505 } 506} 507 508/// \brief Parse a header declaration. 509/// 510/// header-declaration: 511/// 'header' string-literal 512void ModuleMapParser::parseHeaderDecl() { 513 assert(Tok.is(MMToken::HeaderKeyword)); 514 SourceLocation HeaderLoc = consumeToken(); 515 516 // Parse the header name. 517 if (!Tok.is(MMToken::StringLiteral)) { 518 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_header) 519 << "header"; 520 HadError = true; 521 return; 522 } 523 StringRef FileName = Tok.getString(); 524 SourceLocation FileNameLoc = consumeToken(); 525 526 // Look for this file. 527 llvm::SmallString<128> PathName; 528 PathName += Directory->getName(); 529 llvm::sys::path::append(PathName, FileName); 530 531 // FIXME: We shouldn't be eagerly stat'ing every file named in a module map. 532 // Come up with a lazy way to do this. 533 if (const FileEntry *File = SourceMgr.getFileManager().getFile(PathName)) { 534 if (const Module *OwningModule = Map.Headers[File]) { 535 Diags.Report(FileNameLoc, diag::err_mmap_header_conflict) 536 << FileName << OwningModule->getFullModuleName(); 537 HadError = true; 538 } else { 539 // Record this file. 540 ActiveModule->Headers.push_back(File); 541 Map.Headers[File] = ActiveModule; 542 } 543 } else { 544 Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) 545 << false << FileName; 546 HadError = true; 547 } 548} 549 550/// \brief Parse a module map file. 551/// 552/// module-map-file: 553/// module-declaration* 554bool ModuleMapParser::parseModuleMapFile() { 555 do { 556 switch (Tok.Kind) { 557 case MMToken::EndOfFile: 558 return HadError; 559 560 case MMToken::ModuleKeyword: 561 parseModuleDecl(); 562 break; 563 564 case MMToken::ExplicitKeyword: 565 case MMToken::HeaderKeyword: 566 case MMToken::Identifier: 567 case MMToken::LBrace: 568 case MMToken::RBrace: 569 case MMToken::StringLiteral: 570 case MMToken::UmbrellaKeyword: 571 Diags.Report(Tok.getLocation(), diag::err_mmap_expected_module); 572 HadError = true; 573 consumeToken(); 574 break; 575 } 576 } while (true); 577 578 return HadError; 579} 580 581bool ModuleMap::parseModuleMapFile(const FileEntry *File) { 582 FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User); 583 const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID); 584 if (!Buffer) 585 return true; 586 587 // Parse this module map file. 588 Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, LangOpts); 589 Diags->getClient()->BeginSourceFile(LangOpts); 590 ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir()); 591 bool Result = Parser.parseModuleMapFile(); 592 Diags->getClient()->EndSourceFile(); 593 594 return Result; 595} 596