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