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