clang API Documentation
00001 //===--- FrontendAction.cpp -----------------------------------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "clang/Frontend/FrontendAction.h" 00011 #include "clang/AST/ASTConsumer.h" 00012 #include "clang/AST/ASTContext.h" 00013 #include "clang/AST/DeclGroup.h" 00014 #include "clang/Lex/HeaderSearch.h" 00015 #include "clang/Lex/Preprocessor.h" 00016 #include "clang/Frontend/ASTUnit.h" 00017 #include "clang/Frontend/ChainedIncludesSource.h" 00018 #include "clang/Frontend/CompilerInstance.h" 00019 #include "clang/Frontend/FrontendDiagnostic.h" 00020 #include "clang/Frontend/FrontendPluginRegistry.h" 00021 #include "clang/Frontend/LayoutOverrideSource.h" 00022 #include "clang/Frontend/MultiplexConsumer.h" 00023 #include "clang/Parse/ParseAST.h" 00024 #include "clang/Serialization/ASTDeserializationListener.h" 00025 #include "clang/Serialization/ASTReader.h" 00026 #include "llvm/Support/MemoryBuffer.h" 00027 #include "llvm/Support/Timer.h" 00028 #include "llvm/Support/ErrorHandling.h" 00029 #include "llvm/Support/raw_ostream.h" 00030 using namespace clang; 00031 00032 namespace { 00033 00034 class DelegatingDeserializationListener : public ASTDeserializationListener { 00035 ASTDeserializationListener *Previous; 00036 00037 public: 00038 explicit DelegatingDeserializationListener( 00039 ASTDeserializationListener *Previous) 00040 : Previous(Previous) { } 00041 00042 virtual void ReaderInitialized(ASTReader *Reader) { 00043 if (Previous) 00044 Previous->ReaderInitialized(Reader); 00045 } 00046 virtual void IdentifierRead(serialization::IdentID ID, 00047 IdentifierInfo *II) { 00048 if (Previous) 00049 Previous->IdentifierRead(ID, II); 00050 } 00051 virtual void TypeRead(serialization::TypeIdx Idx, QualType T) { 00052 if (Previous) 00053 Previous->TypeRead(Idx, T); 00054 } 00055 virtual void DeclRead(serialization::DeclID ID, const Decl *D) { 00056 if (Previous) 00057 Previous->DeclRead(ID, D); 00058 } 00059 virtual void SelectorRead(serialization::SelectorID ID, Selector Sel) { 00060 if (Previous) 00061 Previous->SelectorRead(ID, Sel); 00062 } 00063 virtual void MacroDefinitionRead(serialization::PreprocessedEntityID PPID, 00064 MacroDefinition *MD) { 00065 if (Previous) 00066 Previous->MacroDefinitionRead(PPID, MD); 00067 } 00068 }; 00069 00070 /// \brief Dumps deserialized declarations. 00071 class DeserializedDeclsDumper : public DelegatingDeserializationListener { 00072 public: 00073 explicit DeserializedDeclsDumper(ASTDeserializationListener *Previous) 00074 : DelegatingDeserializationListener(Previous) { } 00075 00076 virtual void DeclRead(serialization::DeclID ID, const Decl *D) { 00077 llvm::outs() << "PCH DECL: " << D->getDeclKindName(); 00078 if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) 00079 llvm::outs() << " - " << *ND; 00080 llvm::outs() << "\n"; 00081 00082 DelegatingDeserializationListener::DeclRead(ID, D); 00083 } 00084 }; 00085 00086 /// \brief Checks deserialized declarations and emits error if a name 00087 /// matches one given in command-line using -error-on-deserialized-decl. 00088 class DeserializedDeclsChecker : public DelegatingDeserializationListener { 00089 ASTContext &Ctx; 00090 std::set<std::string> NamesToCheck; 00091 00092 public: 00093 DeserializedDeclsChecker(ASTContext &Ctx, 00094 const std::set<std::string> &NamesToCheck, 00095 ASTDeserializationListener *Previous) 00096 : DelegatingDeserializationListener(Previous), 00097 Ctx(Ctx), NamesToCheck(NamesToCheck) { } 00098 00099 virtual void DeclRead(serialization::DeclID ID, const Decl *D) { 00100 if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) 00101 if (NamesToCheck.find(ND->getNameAsString()) != NamesToCheck.end()) { 00102 unsigned DiagID 00103 = Ctx.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, 00104 "%0 was deserialized"); 00105 Ctx.getDiagnostics().Report(Ctx.getFullLoc(D->getLocation()), DiagID) 00106 << ND->getNameAsString(); 00107 } 00108 00109 DelegatingDeserializationListener::DeclRead(ID, D); 00110 } 00111 }; 00112 00113 } // end anonymous namespace 00114 00115 FrontendAction::FrontendAction() : Instance(0) {} 00116 00117 FrontendAction::~FrontendAction() {} 00118 00119 void FrontendAction::setCurrentInput(const FrontendInputFile &CurrentInput, 00120 ASTUnit *AST) { 00121 this->CurrentInput = CurrentInput; 00122 CurrentASTUnit.reset(AST); 00123 } 00124 00125 ASTConsumer* FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI, 00126 StringRef InFile) { 00127 ASTConsumer* Consumer = CreateASTConsumer(CI, InFile); 00128 if (!Consumer) 00129 return 0; 00130 00131 if (CI.getFrontendOpts().AddPluginActions.size() == 0) 00132 return Consumer; 00133 00134 // Make sure the non-plugin consumer is first, so that plugins can't 00135 // modifiy the AST. 00136 std::vector<ASTConsumer*> Consumers(1, Consumer); 00137 00138 for (size_t i = 0, e = CI.getFrontendOpts().AddPluginActions.size(); 00139 i != e; ++i) { 00140 // This is O(|plugins| * |add_plugins|), but since both numbers are 00141 // way below 50 in practice, that's ok. 00142 for (FrontendPluginRegistry::iterator 00143 it = FrontendPluginRegistry::begin(), 00144 ie = FrontendPluginRegistry::end(); 00145 it != ie; ++it) { 00146 if (it->getName() == CI.getFrontendOpts().AddPluginActions[i]) { 00147 OwningPtr<PluginASTAction> P(it->instantiate()); 00148 FrontendAction* c = P.get(); 00149 if (P->ParseArgs(CI, CI.getFrontendOpts().AddPluginArgs[i])) 00150 Consumers.push_back(c->CreateASTConsumer(CI, InFile)); 00151 } 00152 } 00153 } 00154 00155 return new MultiplexConsumer(Consumers); 00156 } 00157 00158 bool FrontendAction::BeginSourceFile(CompilerInstance &CI, 00159 const FrontendInputFile &Input) { 00160 assert(!Instance && "Already processing a source file!"); 00161 assert(!Input.File.empty() && "Unexpected empty filename!"); 00162 setCurrentInput(Input); 00163 setCompilerInstance(&CI); 00164 00165 if (!BeginInvocation(CI)) 00166 goto failure; 00167 00168 // AST files follow a very different path, since they share objects via the 00169 // AST unit. 00170 if (Input.Kind == IK_AST) { 00171 assert(!usesPreprocessorOnly() && 00172 "Attempt to pass AST file to preprocessor only action!"); 00173 assert(hasASTFileSupport() && 00174 "This action does not have AST file support!"); 00175 00176 IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics()); 00177 std::string Error; 00178 ASTUnit *AST = ASTUnit::LoadFromASTFile(Input.File, Diags, 00179 CI.getFileSystemOpts()); 00180 if (!AST) 00181 goto failure; 00182 00183 setCurrentInput(Input, AST); 00184 00185 // Set the shared objects, these are reset when we finish processing the 00186 // file, otherwise the CompilerInstance will happily destroy them. 00187 CI.setFileManager(&AST->getFileManager()); 00188 CI.setSourceManager(&AST->getSourceManager()); 00189 CI.setPreprocessor(&AST->getPreprocessor()); 00190 CI.setASTContext(&AST->getASTContext()); 00191 00192 // Initialize the action. 00193 if (!BeginSourceFileAction(CI, Input.File)) 00194 goto failure; 00195 00196 /// Create the AST consumer. 00197 CI.setASTConsumer(CreateWrappedASTConsumer(CI, Input.File)); 00198 if (!CI.hasASTConsumer()) 00199 goto failure; 00200 00201 return true; 00202 } 00203 00204 // Set up the file and source managers, if needed. 00205 if (!CI.hasFileManager()) 00206 CI.createFileManager(); 00207 if (!CI.hasSourceManager()) 00208 CI.createSourceManager(CI.getFileManager()); 00209 00210 // IR files bypass the rest of initialization. 00211 if (Input.Kind == IK_LLVM_IR) { 00212 assert(hasIRSupport() && 00213 "This action does not have IR file support!"); 00214 00215 // Inform the diagnostic client we are processing a source file. 00216 CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 0); 00217 00218 // Initialize the action. 00219 if (!BeginSourceFileAction(CI, Input.File)) 00220 goto failure; 00221 00222 return true; 00223 } 00224 00225 // Set up the preprocessor. 00226 CI.createPreprocessor(); 00227 00228 // Inform the diagnostic client we are processing a source file. 00229 CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts(), 00230 &CI.getPreprocessor()); 00231 00232 // Initialize the action. 00233 if (!BeginSourceFileAction(CI, Input.File)) 00234 goto failure; 00235 00236 /// Create the AST context and consumer unless this is a preprocessor only 00237 /// action. 00238 if (!usesPreprocessorOnly()) { 00239 CI.createASTContext(); 00240 00241 OwningPtr<ASTConsumer> Consumer( 00242 CreateWrappedASTConsumer(CI, Input.File)); 00243 if (!Consumer) 00244 goto failure; 00245 00246 CI.getASTContext().setASTMutationListener(Consumer->GetASTMutationListener()); 00247 00248 if (!CI.getPreprocessorOpts().ChainedIncludes.empty()) { 00249 // Convert headers to PCH and chain them. 00250 OwningPtr<ExternalASTSource> source; 00251 source.reset(ChainedIncludesSource::create(CI)); 00252 if (!source) 00253 goto failure; 00254 CI.getASTContext().setExternalSource(source); 00255 00256 } else if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty()) { 00257 // Use PCH. 00258 assert(hasPCHSupport() && "This action does not have PCH support!"); 00259 ASTDeserializationListener *DeserialListener = 00260 Consumer->GetASTDeserializationListener(); 00261 if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls) 00262 DeserialListener = new DeserializedDeclsDumper(DeserialListener); 00263 if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty()) 00264 DeserialListener = new DeserializedDeclsChecker(CI.getASTContext(), 00265 CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn, 00266 DeserialListener); 00267 CI.createPCHExternalASTSource( 00268 CI.getPreprocessorOpts().ImplicitPCHInclude, 00269 CI.getPreprocessorOpts().DisablePCHValidation, 00270 CI.getPreprocessorOpts().DisableStatCache, 00271 CI.getPreprocessorOpts().AllowPCHWithCompilerErrors, 00272 DeserialListener); 00273 if (!CI.getASTContext().getExternalSource()) 00274 goto failure; 00275 } 00276 00277 CI.setASTConsumer(Consumer.take()); 00278 if (!CI.hasASTConsumer()) 00279 goto failure; 00280 } 00281 00282 // Initialize built-in info as long as we aren't using an external AST 00283 // source. 00284 if (!CI.hasASTContext() || !CI.getASTContext().getExternalSource()) { 00285 Preprocessor &PP = CI.getPreprocessor(); 00286 PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), 00287 PP.getLangOpts()); 00288 } 00289 00290 // If there is a layout overrides file, attach an external AST source that 00291 // provides the layouts from that file. 00292 if (!CI.getFrontendOpts().OverrideRecordLayoutsFile.empty() && 00293 CI.hasASTContext() && !CI.getASTContext().getExternalSource()) { 00294 OwningPtr<ExternalASTSource> 00295 Override(new LayoutOverrideSource( 00296 CI.getFrontendOpts().OverrideRecordLayoutsFile)); 00297 CI.getASTContext().setExternalSource(Override); 00298 } 00299 00300 return true; 00301 00302 // If we failed, reset state since the client will not end up calling the 00303 // matching EndSourceFile(). 00304 failure: 00305 if (isCurrentFileAST()) { 00306 CI.setASTContext(0); 00307 CI.setPreprocessor(0); 00308 CI.setSourceManager(0); 00309 CI.setFileManager(0); 00310 } 00311 00312 CI.getDiagnosticClient().EndSourceFile(); 00313 setCurrentInput(FrontendInputFile()); 00314 setCompilerInstance(0); 00315 return false; 00316 } 00317 00318 void FrontendAction::Execute() { 00319 CompilerInstance &CI = getCompilerInstance(); 00320 00321 // Initialize the main file entry. This needs to be delayed until after PCH 00322 // has loaded. 00323 if (!isCurrentFileAST()) { 00324 if (!CI.InitializeSourceManager(getCurrentFile(), 00325 getCurrentInput().IsSystem 00326 ? SrcMgr::C_System 00327 : SrcMgr::C_User)) 00328 return; 00329 } 00330 00331 if (CI.hasFrontendTimer()) { 00332 llvm::TimeRegion Timer(CI.getFrontendTimer()); 00333 ExecuteAction(); 00334 } 00335 else ExecuteAction(); 00336 } 00337 00338 void FrontendAction::EndSourceFile() { 00339 CompilerInstance &CI = getCompilerInstance(); 00340 00341 // Inform the diagnostic client we are done with this source file. 00342 CI.getDiagnosticClient().EndSourceFile(); 00343 00344 // Finalize the action. 00345 EndSourceFileAction(); 00346 00347 // Release the consumer and the AST, in that order since the consumer may 00348 // perform actions in its destructor which require the context. 00349 // 00350 // FIXME: There is more per-file stuff we could just drop here? 00351 if (CI.getFrontendOpts().DisableFree) { 00352 CI.takeASTConsumer(); 00353 if (!isCurrentFileAST()) { 00354 CI.takeSema(); 00355 CI.resetAndLeakASTContext(); 00356 } 00357 } else { 00358 if (!isCurrentFileAST()) { 00359 CI.setSema(0); 00360 CI.setASTContext(0); 00361 } 00362 CI.setASTConsumer(0); 00363 } 00364 00365 // Inform the preprocessor we are done. 00366 if (CI.hasPreprocessor()) 00367 CI.getPreprocessor().EndSourceFile(); 00368 00369 if (CI.getFrontendOpts().ShowStats) { 00370 llvm::errs() << "\nSTATISTICS FOR '" << getCurrentFile() << "':\n"; 00371 CI.getPreprocessor().PrintStats(); 00372 CI.getPreprocessor().getIdentifierTable().PrintStats(); 00373 CI.getPreprocessor().getHeaderSearchInfo().PrintStats(); 00374 CI.getSourceManager().PrintStats(); 00375 llvm::errs() << "\n"; 00376 } 00377 00378 // Cleanup the output streams, and erase the output files if we encountered 00379 // an error. 00380 CI.clearOutputFiles(/*EraseFiles=*/CI.getDiagnostics().hasErrorOccurred()); 00381 00382 if (isCurrentFileAST()) { 00383 CI.takeSema(); 00384 CI.resetAndLeakASTContext(); 00385 CI.resetAndLeakPreprocessor(); 00386 CI.resetAndLeakSourceManager(); 00387 CI.resetAndLeakFileManager(); 00388 } 00389 00390 setCompilerInstance(0); 00391 setCurrentInput(FrontendInputFile()); 00392 } 00393 00394 //===----------------------------------------------------------------------===// 00395 // Utility Actions 00396 //===----------------------------------------------------------------------===// 00397 00398 void ASTFrontendAction::ExecuteAction() { 00399 CompilerInstance &CI = getCompilerInstance(); 00400 00401 // FIXME: Move the truncation aspect of this into Sema, we delayed this till 00402 // here so the source manager would be initialized. 00403 if (hasCodeCompletionSupport() && 00404 !CI.getFrontendOpts().CodeCompletionAt.FileName.empty()) 00405 CI.createCodeCompletionConsumer(); 00406 00407 // Use a code completion consumer? 00408 CodeCompleteConsumer *CompletionConsumer = 0; 00409 if (CI.hasCodeCompletionConsumer()) 00410 CompletionConsumer = &CI.getCodeCompletionConsumer(); 00411 00412 if (!CI.hasSema()) 00413 CI.createSema(getTranslationUnitKind(), CompletionConsumer); 00414 00415 ParseAST(CI.getSema(), CI.getFrontendOpts().ShowStats, 00416 CI.getFrontendOpts().SkipFunctionBodies); 00417 } 00418 00419 void PluginASTAction::anchor() { } 00420 00421 ASTConsumer * 00422 PreprocessorFrontendAction::CreateASTConsumer(CompilerInstance &CI, 00423 StringRef InFile) { 00424 llvm_unreachable("Invalid CreateASTConsumer on preprocessor action!"); 00425 } 00426 00427 ASTConsumer *WrapperFrontendAction::CreateASTConsumer(CompilerInstance &CI, 00428 StringRef InFile) { 00429 return WrappedAction->CreateASTConsumer(CI, InFile); 00430 } 00431 bool WrapperFrontendAction::BeginInvocation(CompilerInstance &CI) { 00432 return WrappedAction->BeginInvocation(CI); 00433 } 00434 bool WrapperFrontendAction::BeginSourceFileAction(CompilerInstance &CI, 00435 StringRef Filename) { 00436 WrappedAction->setCurrentInput(getCurrentInput()); 00437 WrappedAction->setCompilerInstance(&CI); 00438 return WrappedAction->BeginSourceFileAction(CI, Filename); 00439 } 00440 void WrapperFrontendAction::ExecuteAction() { 00441 WrappedAction->ExecuteAction(); 00442 } 00443 void WrapperFrontendAction::EndSourceFileAction() { 00444 WrappedAction->EndSourceFileAction(); 00445 } 00446 00447 bool WrapperFrontendAction::usesPreprocessorOnly() const { 00448 return WrappedAction->usesPreprocessorOnly(); 00449 } 00450 TranslationUnitKind WrapperFrontendAction::getTranslationUnitKind() { 00451 return WrappedAction->getTranslationUnitKind(); 00452 } 00453 bool WrapperFrontendAction::hasPCHSupport() const { 00454 return WrappedAction->hasPCHSupport(); 00455 } 00456 bool WrapperFrontendAction::hasASTFileSupport() const { 00457 return WrappedAction->hasASTFileSupport(); 00458 } 00459 bool WrapperFrontendAction::hasIRSupport() const { 00460 return WrappedAction->hasIRSupport(); 00461 } 00462 bool WrapperFrontendAction::hasCodeCompletionSupport() const { 00463 return WrappedAction->hasCodeCompletionSupport(); 00464 } 00465 00466 WrapperFrontendAction::WrapperFrontendAction(FrontendAction *WrappedAction) 00467 : WrappedAction(WrappedAction) {} 00468