clang API Documentation

FrontendAction.cpp
Go to the documentation of this file.
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