1 //===--- FrontendAction.cpp -----------------------------------------------===// 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 #include "clang/Frontend/FrontendAction.h" 11 #include "clang/AST/ASTConsumer.h" 12 #include "clang/AST/ASTContext.h" 13 #include "clang/AST/DeclGroup.h" 14 #include "clang/Frontend/ASTUnit.h" 15 #include "clang/Frontend/ChainedIncludesSource.h" 16 #include "clang/Frontend/CompilerInstance.h" 17 #include "clang/Frontend/FrontendDiagnostic.h" 18 #include "clang/Frontend/FrontendPluginRegistry.h" 19 #include "clang/Frontend/LayoutOverrideSource.h" 20 #include "clang/Frontend/MultiplexConsumer.h" 21 #include "clang/Lex/HeaderSearch.h" 22 #include "clang/Lex/Preprocessor.h" 23 #include "clang/Parse/ParseAST.h" 24 #include "clang/Serialization/ASTDeserializationListener.h" 25 #include "clang/Serialization/ASTReader.h" 26 #include "clang/Serialization/GlobalModuleIndex.h" 27 #include "llvm/Support/ErrorHandling.h" 28 #include "llvm/Support/FileSystem.h" 29 #include "llvm/Support/MemoryBuffer.h" 30 #include "llvm/Support/Timer.h" 31 #include "llvm/Support/raw_ostream.h" 32 #include "llvm/Support/system_error.h" 33 using namespace clang; 34 35 namespace { 36 37 class DelegatingDeserializationListener : public ASTDeserializationListener { 38 ASTDeserializationListener *Previous; 39 40 public: 41 explicit DelegatingDeserializationListener( 42 ASTDeserializationListener *Previous) 43 : Previous(Previous) { } 44 45 virtual void ReaderInitialized(ASTReader *Reader) { 46 if (Previous) 47 Previous->ReaderInitialized(Reader); 48 } 49 virtual void IdentifierRead(serialization::IdentID ID, 50 IdentifierInfo *II) { 51 if (Previous) 52 Previous->IdentifierRead(ID, II); 53 } 54 virtual void TypeRead(serialization::TypeIdx Idx, QualType T) { 55 if (Previous) 56 Previous->TypeRead(Idx, T); 57 } 58 virtual void DeclRead(serialization::DeclID ID, const Decl *D) { 59 if (Previous) 60 Previous->DeclRead(ID, D); 61 } 62 virtual void SelectorRead(serialization::SelectorID ID, Selector Sel) { 63 if (Previous) 64 Previous->SelectorRead(ID, Sel); 65 } 66 virtual void MacroDefinitionRead(serialization::PreprocessedEntityID PPID, 67 MacroDefinition *MD) { 68 if (Previous) 69 Previous->MacroDefinitionRead(PPID, MD); 70 } 71 }; 72 73 /// \brief Dumps deserialized declarations. 74 class DeserializedDeclsDumper : public DelegatingDeserializationListener { 75 public: 76 explicit DeserializedDeclsDumper(ASTDeserializationListener *Previous) 77 : DelegatingDeserializationListener(Previous) { } 78 79 virtual void DeclRead(serialization::DeclID ID, const Decl *D) { 80 llvm::outs() << "PCH DECL: " << D->getDeclKindName(); 81 if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) 82 llvm::outs() << " - " << *ND; 83 llvm::outs() << "\n"; 84 85 DelegatingDeserializationListener::DeclRead(ID, D); 86 } 87 }; 88 89 /// \brief Checks deserialized declarations and emits error if a name 90 /// matches one given in command-line using -error-on-deserialized-decl. 91 class DeserializedDeclsChecker : public DelegatingDeserializationListener { 92 ASTContext &Ctx; 93 std::set<std::string> NamesToCheck; 94 95 public: 96 DeserializedDeclsChecker(ASTContext &Ctx, 97 const std::set<std::string> &NamesToCheck, 98 ASTDeserializationListener *Previous) 99 : DelegatingDeserializationListener(Previous), 100 Ctx(Ctx), NamesToCheck(NamesToCheck) { } 101 102 virtual void DeclRead(serialization::DeclID ID, const Decl *D) { 103 if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) 104 if (NamesToCheck.find(ND->getNameAsString()) != NamesToCheck.end()) { 105 unsigned DiagID 106 = Ctx.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, 107 "%0 was deserialized"); 108 Ctx.getDiagnostics().Report(Ctx.getFullLoc(D->getLocation()), DiagID) 109 << ND->getNameAsString(); 110 } 111 112 DelegatingDeserializationListener::DeclRead(ID, D); 113 } 114 }; 115 116 } // end anonymous namespace 117 118 FrontendAction::FrontendAction() : Instance(0) {} 119 120 FrontendAction::~FrontendAction() {} 121 122 void FrontendAction::setCurrentInput(const FrontendInputFile &CurrentInput, 123 ASTUnit *AST) { 124 this->CurrentInput = CurrentInput; 125 CurrentASTUnit.reset(AST); 126 } 127 128 ASTConsumer* FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI, 129 StringRef InFile) { 130 ASTConsumer* Consumer = CreateASTConsumer(CI, InFile); 131 if (!Consumer) 132 return 0; 133 134 if (CI.getFrontendOpts().AddPluginActions.size() == 0) 135 return Consumer; 136 137 // Make sure the non-plugin consumer is first, so that plugins can't 138 // modifiy the AST. 139 std::vector<ASTConsumer*> Consumers(1, Consumer); 140 141 for (size_t i = 0, e = CI.getFrontendOpts().AddPluginActions.size(); 142 i != e; ++i) { 143 // This is O(|plugins| * |add_plugins|), but since both numbers are 144 // way below 50 in practice, that's ok. 145 for (FrontendPluginRegistry::iterator 146 it = FrontendPluginRegistry::begin(), 147 ie = FrontendPluginRegistry::end(); 148 it != ie; ++it) { 149 if (it->getName() == CI.getFrontendOpts().AddPluginActions[i]) { 150 OwningPtr<PluginASTAction> P(it->instantiate()); 151 FrontendAction* c = P.get(); 152 if (P->ParseArgs(CI, CI.getFrontendOpts().AddPluginArgs[i])) 153 Consumers.push_back(c->CreateASTConsumer(CI, InFile)); 154 } 155 } 156 } 157 158 return new MultiplexConsumer(Consumers); 159 } 160 161 162 bool FrontendAction::BeginSourceFile(CompilerInstance &CI, 163 const FrontendInputFile &Input) { 164 assert(!Instance && "Already processing a source file!"); 165 assert(!Input.isEmpty() && "Unexpected empty filename!"); 166 setCurrentInput(Input); 167 setCompilerInstance(&CI); 168 169 StringRef InputFile = Input.getFile(); 170 bool HasBegunSourceFile = false; 171 if (!BeginInvocation(CI)) 172 goto failure; 173 174 // AST files follow a very different path, since they share objects via the 175 // AST unit. 176 if (Input.getKind() == IK_AST) { 177 assert(!usesPreprocessorOnly() && 178 "Attempt to pass AST file to preprocessor only action!"); 179 assert(hasASTFileSupport() && 180 "This action does not have AST file support!"); 181 182 IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics()); 183 std::string Error; 184 ASTUnit *AST = ASTUnit::LoadFromASTFile(InputFile, Diags, 185 CI.getFileSystemOpts()); 186 if (!AST) 187 goto failure; 188 189 setCurrentInput(Input, AST); 190 191 // Inform the diagnostic client we are processing a source file. 192 CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0); 193 HasBegunSourceFile = true; 194 195 // Set the shared objects, these are reset when we finish processing the 196 // file, otherwise the CompilerInstance will happily destroy them. 197 CI.setFileManager(&AST->getFileManager()); 198 CI.setSourceManager(&AST->getSourceManager()); 199 CI.setPreprocessor(&AST->getPreprocessor()); 200 CI.setASTContext(&AST->getASTContext()); 201 202 // Initialize the action. 203 if (!BeginSourceFileAction(CI, InputFile)) 204 goto failure; 205 206 // Create the AST consumer. 207 CI.setASTConsumer(CreateWrappedASTConsumer(CI, InputFile)); 208 if (!CI.hasASTConsumer()) 209 goto failure; 210 211 return true; 212 } 213 214 // Set up the file and source managers, if needed. 215 if (!CI.hasFileManager()) 216 CI.createFileManager(); 217 if (!CI.hasSourceManager()) 218 CI.createSourceManager(CI.getFileManager()); 219 220 // IR files bypass the rest of initialization. 221 if (Input.getKind() == IK_LLVM_IR) { 222 assert(hasIRSupport() && 223 "This action does not have IR file support!"); 224 225 // Inform the diagnostic client we are processing a source file. 226 CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0); 227 HasBegunSourceFile = true; 228 229 // Initialize the action. 230 if (!BeginSourceFileAction(CI, InputFile)) 231 goto failure; 232 233 return true; 234 } 235 236 // If the implicit PCH include is actually a directory, rather than 237 // a single file, search for a suitable PCH file in that directory. 238 if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { 239 FileManager &FileMgr = CI.getFileManager(); 240 PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); 241 StringRef PCHInclude = PPOpts.ImplicitPCHInclude; 242 if (const DirectoryEntry *PCHDir = FileMgr.getDirectory(PCHInclude)) { 243 llvm::error_code EC; 244 SmallString<128> DirNative; 245 llvm::sys::path::native(PCHDir->getName(), DirNative); 246 bool Found = false; 247 for (llvm::sys::fs::directory_iterator Dir(DirNative.str(), EC), DirEnd; 248 Dir != DirEnd && !EC; Dir.increment(EC)) { 249 // Check whether this is an acceptable AST file. 250 if (ASTReader::isAcceptableASTFile(Dir->path(), FileMgr, 251 CI.getLangOpts(), 252 CI.getTargetOpts(), 253 CI.getPreprocessorOpts())) { 254 PPOpts.ImplicitPCHInclude = Dir->path(); 255 Found = true; 256 break; 257 } 258 } 259 260 if (!Found) { 261 CI.getDiagnostics().Report(diag::err_fe_no_pch_in_dir) << PCHInclude; 262 return true; 263 } 264 } 265 } 266 267 // Set up the preprocessor. 268 CI.createPreprocessor(); 269 270 // Inform the diagnostic client we are processing a source file. 271 CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 272 &CI.getPreprocessor()); 273 HasBegunSourceFile = true; 274 275 // Initialize the action. 276 if (!BeginSourceFileAction(CI, InputFile)) 277 goto failure; 278 279 // Create the AST context and consumer unless this is a preprocessor only 280 // action. 281 if (!usesPreprocessorOnly()) { 282 CI.createASTContext(); 283 284 OwningPtr<ASTConsumer> Consumer( 285 CreateWrappedASTConsumer(CI, InputFile)); 286 if (!Consumer) 287 goto failure; 288 289 CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener()); 290 291 if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) { 292 // Convert headers to PCH and chain them. 293 OwningPtr<ExternalASTSource> source; 294 source.reset(ChainedIncludesSource::create(CI)); 295 if (!source) 296 goto failure; 297 CI.setModuleManager(static_cast<ASTReader*>( 298 &static_cast<ChainedIncludesSource*>(source.get())->getFinalReader())); 299 CI.getASTContext().setExternalSource(source); 300 301 } else if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { 302 // Use PCH. 303 assert(hasPCHSupport() && "This action does not have PCH support!"); 304 ASTDeserializationListener *DeserialListener = 305 Consumer->GetASTDeserializationListener(); 306 if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls) 307 DeserialListener = new DeserializedDeclsDumper(DeserialListener); 308 if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty()) 309 DeserialListener = new DeserializedDeclsChecker(CI.getASTContext(), 310 CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn, 311 DeserialListener); 312 CI.createPCHExternalASTSource( 313 CI.getPreprocessorOpts().ImplicitPCHInclude, 314 CI.getPreprocessorOpts().DisablePCHValidation, 315 CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, 316 DeserialListener); 317 if (!CI.getASTContext().getExternalSource()) 318 goto failure; 319 } 320 321 CI.setASTConsumer(Consumer.take()); 322 if (!CI.hasASTConsumer()) 323 goto failure; 324 } 325 326 // Initialize built-in info as long as we aren't using an external AST 327 // source. 328 if (!CI.hasASTContext() || !CI.getASTContext().getExternalSource()) { 329 Preprocessor &PP = CI.getPreprocessor(); 330 PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), 331 PP.getLangOpts()); 332 } 333 334 // If there is a layout overrides file, attach an external AST source that 335 // provides the layouts from that file. 336 if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() && 337 CI.hasASTContext() && !CI.getASTContext().getExternalSource()) { 338 OwningPtr<ExternalASTSource> 339 Override(new LayoutOverrideSource( 340 CI.getFrontendOpts().OverrideRecordLayoutsFile)); 341 CI.getASTContext().setExternalSource(Override); 342 } 343 344 return true; 345 346 // If we failed, reset state since the client will not end up calling the 347 // matching EndSourceFile(). 348 failure: 349 if (isCurrentFileAST()) { 350 CI.setASTContext(0); 351 CI.setPreprocessor(0); 352 CI.setSourceManager(0); 353 CI.setFileManager(0); 354 } 355 356 if (HasBegunSourceFile) 357 CI.getDiagnosticClient().EndSourceFile(); 358 CI.clearOutputFiles(/*EraseFiles=*/true); 359 setCurrentInput(FrontendInputFile()); 360 setCompilerInstance(0); 361 return false; 362 } 363 364 bool FrontendAction::Execute() { 365 CompilerInstance &CI = getCompilerInstance(); 366 367 // Initialize the main file entry. This needs to be delayed until after PCH 368 // has loaded. 369 if (!isCurrentFileAST()) { 370 if (!CI.InitializeSourceManager(getCurrentInput())) 371 return false; 372 } 373 374 if (CI.hasFrontendTimer()) { 375 llvm::TimeRegion Timer(CI.getFrontendTimer()); 376 ExecuteAction(); 377 } 378 else ExecuteAction(); 379 380 // If we are supposed to rebuild the global module index, do so now unless 381 // there were any module-build failures. 382 if (CI.shouldBuildGlobalModuleIndex() && CI.hasFileManager() && 383 CI.hasPreprocessor()) { 384 GlobalModuleIndex::writeIndex( 385 CI.getFileManager(), 386 CI.getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); 387 } 388 389 return true; 390 } 391 392 void FrontendAction::EndSourceFile() { 393 CompilerInstance &CI = getCompilerInstance(); 394 395 // Inform the diagnostic client we are done with this source file. 396 CI.getDiagnosticClient().EndSourceFile(); 397 398 // Finalize the action. 399 EndSourceFileAction(); 400 401 // Release the consumer and the AST, in that order since the consumer may 402 // perform actions in its destructor which require the context. 403 // 404 // FIXME: There is more per-file stuff we could just drop here? 405 if (CI.getFrontendOpts().DisableFree) { 406 CI.takeASTConsumer(); 407 if (!isCurrentFileAST()) { 408 CI.takeSema(); 409 CI.resetAndLeakASTContext(); 410 } 411 } else { 412 if (!isCurrentFileAST()) { 413 CI.setSema(0); 414 CI.setASTContext(0); 415 } 416 CI.setASTConsumer(0); 417 } 418 419 // Inform the preprocessor we are done. 420 if (CI.hasPreprocessor()) 421 CI.getPreprocessor().EndSourceFile(); 422 423 if (CI.getFrontendOpts().ShowStats) { 424 llvm::errs() << "\nSTATISTICS FOR '" << getCurrentFile() << "':\n"; 425 CI.getPreprocessor().PrintStats(); 426 CI.getPreprocessor().getIdentifierTable().PrintStats(); 427 CI.getPreprocessor().getHeaderSearchInfo().PrintStats(); 428 CI.getSourceManager().PrintStats(); 429 llvm::errs() << "\n"; 430 } 431 432 // Cleanup the output streams, and erase the output files if instructed by the 433 // FrontendAction. 434 CI.clearOutputFiles(/*EraseFiles=*/shouldEraseOutputFiles()); 435 436 if (isCurrentFileAST()) { 437 CI.takeSema(); 438 CI.resetAndLeakASTContext(); 439 CI.resetAndLeakPreprocessor(); 440 CI.resetAndLeakSourceManager(); 441 CI.resetAndLeakFileManager(); 442 } 443 444 setCompilerInstance(0); 445 setCurrentInput(FrontendInputFile()); 446 } 447 448 bool FrontendAction::shouldEraseOutputFiles() { 449 return getCompilerInstance().getDiagnostics().hasErrorOccurred(); 450 } 451 452 //===----------------------------------------------------------------------===// 453 // Utility Actions 454 //===----------------------------------------------------------------------===// 455 456 void ASTFrontendAction::ExecuteAction() { 457 CompilerInstance &CI = getCompilerInstance(); 458 if (!CI.hasPreprocessor()) 459 return; 460 461 // FIXME: Move the truncation aspect of this into Sema, we delayed this till 462 // here so the source manager would be initialized. 463 if (hasCodeCompletionSupport() && 464 !CI.getFrontendOpts().CodeCompletionAt.FileName.empty()) 465 CI.createCodeCompletionConsumer(); 466 467 // Use a code completion consumer? 468 CodeCompleteConsumer *CompletionConsumer = 0; 469 if (CI.hasCodeCompletionConsumer()) 470 CompletionConsumer = &CI.getCodeCompletionConsumer(); 471 472 if (!CI.hasSema()) 473 CI.createSema(getTranslationUnitKind(), CompletionConsumer); 474 475 ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats, 476 CI.getFrontendOpts().SkipFunctionBodies); 477 } 478 479 void PluginASTAction::anchor() { } 480 481 ASTConsumer * 482 PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI, 483 StringRef InFile) { 484 llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!"); 485 } 486 487 ASTConsumer *WrapperFrontendAction::CreateASTConsumer(CompilerInstance &CI, 488 StringRef InFile) { 489 return WrappedAction->CreateASTConsumer(CI, InFile); 490 } 491 bool WrapperFrontendAction::BeginInvocation(CompilerInstance &CI) { 492 return WrappedAction->BeginInvocation(CI); 493 } 494 bool WrapperFrontendAction::BeginSourceFileAction(CompilerInstance &CI, 495 StringRef Filename) { 496 WrappedAction->setCurrentInput(getCurrentInput()); 497 WrappedAction->setCompilerInstance(&CI); 498 return WrappedAction->BeginSourceFileAction(CI, Filename); 499 } 500 void WrapperFrontendAction::ExecuteAction() { 501 WrappedAction->ExecuteAction(); 502 } 503 void WrapperFrontendAction::EndSourceFileAction() { 504 WrappedAction->EndSourceFileAction(); 505 } 506 507 bool WrapperFrontendAction::usesPreprocessorOnly() const { 508 return WrappedAction->usesPreprocessorOnly(); 509 } 510 TranslationUnitKind WrapperFrontendAction::getTranslationUnitKind() { 511 return WrappedAction->getTranslationUnitKind(); 512 } 513 bool WrapperFrontendAction::hasPCHSupport() const { 514 return WrappedAction->hasPCHSupport(); 515 } 516 bool WrapperFrontendAction::hasASTFileSupport() const { 517 return WrappedAction->hasASTFileSupport(); 518 } 519 bool WrapperFrontendAction::hasIRSupport() const { 520 return WrappedAction->hasIRSupport(); 521 } 522 bool WrapperFrontendAction::hasCodeCompletionSupport() const { 523 return WrappedAction->hasCodeCompletionSupport(); 524 } 525 526 WrapperFrontendAction::WrapperFrontendAction(FrontendAction *WrappedAction) 527 : WrappedAction(WrappedAction) {} 528 529