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