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