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