Home | History | Annotate | Download | only in Frontend
      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