brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.5 KiB · 73a6a8c Raw
311 lines · cpp
1//===- IndexingAction.cpp - Frontend index action -------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "clang/Index/IndexingAction.h"10#include "IndexingContext.h"11#include "clang/Frontend/CompilerInstance.h"12#include "clang/Frontend/FrontendAction.h"13#include "clang/Index/IndexDataConsumer.h"14#include "clang/Lex/PPCallbacks.h"15#include "clang/Lex/Preprocessor.h"16#include "clang/Serialization/ASTReader.h"17#include <memory>18 19using namespace clang;20using namespace clang::index;21 22namespace {23 24class IndexPPCallbacks final : public PPCallbacks {25  std::shared_ptr<IndexingContext> IndexCtx;26 27public:28  IndexPPCallbacks(std::shared_ptr<IndexingContext> IndexCtx)29      : IndexCtx(std::move(IndexCtx)) {}30 31  void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,32                    SourceRange Range, const MacroArgs *Args) override {33    IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),34                                   Range.getBegin(), *MD.getMacroInfo());35  }36 37  void MacroDefined(const Token &MacroNameTok,38                    const MacroDirective *MD) override {39    IndexCtx->handleMacroDefined(*MacroNameTok.getIdentifierInfo(),40                                 MacroNameTok.getLocation(),41                                 *MD->getMacroInfo());42  }43 44  void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD,45                      const MacroDirective *Undef) override {46    if (!MD.getMacroInfo())  // Ignore noop #undef.47      return;48    IndexCtx->handleMacroUndefined(*MacroNameTok.getIdentifierInfo(),49                                   MacroNameTok.getLocation(),50                                   *MD.getMacroInfo());51  }52 53  void Defined(const Token &MacroNameTok, const MacroDefinition &MD,54               SourceRange Range) override {55    if (!MD.getMacroInfo()) // Ignore nonexistent macro.56      return;57    // Note: this is defined(M), not #define M58    IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),59                                   MacroNameTok.getLocation(),60                                   *MD.getMacroInfo());61  }62  void Ifdef(SourceLocation Loc, const Token &MacroNameTok,63             const MacroDefinition &MD) override {64    if (!MD.getMacroInfo()) // Ignore non-existent macro.65      return;66    IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),67                                   MacroNameTok.getLocation(),68                                   *MD.getMacroInfo());69  }70  void Ifndef(SourceLocation Loc, const Token &MacroNameTok,71              const MacroDefinition &MD) override {72    if (!MD.getMacroInfo()) // Ignore nonexistent macro.73      return;74    IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),75                                   MacroNameTok.getLocation(),76                                   *MD.getMacroInfo());77  }78 79  using PPCallbacks::Elifdef;80  using PPCallbacks::Elifndef;81  void Elifdef(SourceLocation Loc, const Token &MacroNameTok,82               const MacroDefinition &MD) override {83    if (!MD.getMacroInfo()) // Ignore non-existent macro.84      return;85    IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),86                                   MacroNameTok.getLocation(),87                                   *MD.getMacroInfo());88  }89  void Elifndef(SourceLocation Loc, const Token &MacroNameTok,90                const MacroDefinition &MD) override {91    if (!MD.getMacroInfo()) // Ignore non-existent macro.92      return;93    IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),94                                   MacroNameTok.getLocation(),95                                   *MD.getMacroInfo());96  }97};98 99class IndexASTConsumer final : public ASTConsumer {100  std::shared_ptr<IndexDataConsumer> DataConsumer;101  std::shared_ptr<IndexingContext> IndexCtx;102  std::shared_ptr<Preprocessor> PP;103  std::function<bool(const Decl *)> ShouldSkipFunctionBody;104 105public:106  IndexASTConsumer(std::shared_ptr<IndexDataConsumer> DataConsumer,107                   const IndexingOptions &Opts,108                   std::shared_ptr<Preprocessor> PP,109                   std::function<bool(const Decl *)> ShouldSkipFunctionBody)110      : DataConsumer(std::move(DataConsumer)),111        IndexCtx(new IndexingContext(Opts, *this->DataConsumer)),112        PP(std::move(PP)),113        ShouldSkipFunctionBody(std::move(ShouldSkipFunctionBody)) {114    assert(this->DataConsumer != nullptr);115    assert(this->PP != nullptr);116  }117 118protected:119  void Initialize(ASTContext &Context) override {120    IndexCtx->setASTContext(Context);121    IndexCtx->getDataConsumer().initialize(Context);122    IndexCtx->getDataConsumer().setPreprocessor(PP);123    PP->addPPCallbacks(std::make_unique<IndexPPCallbacks>(IndexCtx));124  }125 126  bool HandleTopLevelDecl(DeclGroupRef DG) override {127    return IndexCtx->indexDeclGroupRef(DG);128  }129 130  void HandleInterestingDecl(DeclGroupRef DG) override {131    // Ignore deserialized decls.132  }133 134  void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {135    IndexCtx->indexDeclGroupRef(DG);136  }137 138  void HandleTranslationUnit(ASTContext &Ctx) override {139    DataConsumer->finish();140  }141 142  bool shouldSkipFunctionBody(Decl *D) override {143    return ShouldSkipFunctionBody(D);144  }145};146 147class IndexAction final : public ASTFrontendAction {148  std::shared_ptr<IndexDataConsumer> DataConsumer;149  IndexingOptions Opts;150 151public:152  IndexAction(std::shared_ptr<IndexDataConsumer> DataConsumer,153              const IndexingOptions &Opts)154      : DataConsumer(std::move(DataConsumer)), Opts(Opts) {155    assert(this->DataConsumer != nullptr);156  }157 158protected:159  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,160                                                 StringRef InFile) override {161    return std::make_unique<IndexASTConsumer>(162        DataConsumer, Opts, CI.getPreprocessorPtr(),163        /*ShouldSkipFunctionBody=*/[](const Decl *) { return false; });164  }165};166 167} // anonymous namespace168 169std::unique_ptr<ASTConsumer> index::createIndexingASTConsumer(170    std::shared_ptr<IndexDataConsumer> DataConsumer,171    const IndexingOptions &Opts, std::shared_ptr<Preprocessor> PP,172    std::function<bool(const Decl *)> ShouldSkipFunctionBody) {173  return std::make_unique<IndexASTConsumer>(DataConsumer, Opts, PP,174                                            ShouldSkipFunctionBody);175}176 177std::unique_ptr<ASTConsumer> clang::index::createIndexingASTConsumer(178    std::shared_ptr<IndexDataConsumer> DataConsumer,179    const IndexingOptions &Opts, std::shared_ptr<Preprocessor> PP) {180  std::function<bool(const Decl *)> ShouldSkipFunctionBody = [](const Decl *) {181    return false;182  };183  if (Opts.ShouldTraverseDecl)184    ShouldSkipFunctionBody =185        [ShouldTraverseDecl(Opts.ShouldTraverseDecl)](const Decl *D) {186          return !ShouldTraverseDecl(D);187        };188  return createIndexingASTConsumer(std::move(DataConsumer), Opts, std::move(PP),189                                   std::move(ShouldSkipFunctionBody));190}191 192std::unique_ptr<FrontendAction>193index::createIndexingAction(std::shared_ptr<IndexDataConsumer> DataConsumer,194                            const IndexingOptions &Opts) {195  assert(DataConsumer != nullptr);196  return std::make_unique<IndexAction>(std::move(DataConsumer), Opts);197}198 199static bool topLevelDeclVisitor(void *context, const Decl *D) {200  IndexingContext &IndexCtx = *static_cast<IndexingContext *>(context);201  return IndexCtx.indexTopLevelDecl(D);202}203 204static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx) {205  Unit.visitLocalTopLevelDecls(&IndexCtx, topLevelDeclVisitor);206}207 208static void indexPreprocessorMacro(const IdentifierInfo *II,209                                   const MacroInfo *MI,210                                   MacroDirective::Kind DirectiveKind,211                                   SourceLocation Loc,212                                   IndexDataConsumer &DataConsumer) {213  // When using modules, it may happen that we find #undef of a macro that214  // was defined in another module. In such case, MI may be nullptr, since215  // we only look for macro definitions in the current TU. In that case,216  // there is nothing to index.217  if (!MI)218    return;219 220  // Skip implicit visibility change.221  if (DirectiveKind == MacroDirective::MD_Visibility)222    return;223 224  auto Role = DirectiveKind == MacroDirective::MD_Define225                  ? SymbolRole::Definition226                  : SymbolRole::Undefinition;227  DataConsumer.handleMacroOccurrence(II, MI, static_cast<unsigned>(Role), Loc);228}229 230static void indexPreprocessorMacros(Preprocessor &PP,231                                    IndexDataConsumer &DataConsumer) {232  for (const auto &M : PP.macros()) {233    for (auto *MD = M.second.getLatest(); MD; MD = MD->getPrevious()) {234      indexPreprocessorMacro(M.first, MD->getMacroInfo(), MD->getKind(),235                             MD->getLocation(), DataConsumer);236    }237  }238}239 240static void indexPreprocessorModuleMacros(Preprocessor &PP,241                                          serialization::ModuleFile &Mod,242                                          IndexDataConsumer &DataConsumer) {243  for (const auto &M : PP.macros()) {244    if (M.second.getLatest() == nullptr) {245      for (auto *MM : PP.getLeafModuleMacros(M.first)) {246        auto *OwningMod = MM->getOwningModule();247        if (OwningMod && OwningMod->getASTFile() == Mod.File) {248          if (auto *MI = MM->getMacroInfo()) {249            indexPreprocessorMacro(M.first, MI, MacroDirective::MD_Define,250                                   MI->getDefinitionLoc(), DataConsumer);251          }252        }253      }254    }255  }256}257 258void index::indexASTUnit(ASTUnit &Unit, IndexDataConsumer &DataConsumer,259                         IndexingOptions Opts) {260  IndexingContext IndexCtx(Opts, DataConsumer);261  IndexCtx.setASTContext(Unit.getASTContext());262  DataConsumer.initialize(Unit.getASTContext());263  DataConsumer.setPreprocessor(Unit.getPreprocessorPtr());264 265  if (Opts.IndexMacrosInPreprocessor)266    indexPreprocessorMacros(Unit.getPreprocessor(), DataConsumer);267  indexTranslationUnit(Unit, IndexCtx);268  DataConsumer.finish();269}270 271void index::indexTopLevelDecls(ASTContext &Ctx, Preprocessor &PP,272                               ArrayRef<const Decl *> Decls,273                               IndexDataConsumer &DataConsumer,274                               IndexingOptions Opts) {275  IndexingContext IndexCtx(Opts, DataConsumer);276  IndexCtx.setASTContext(Ctx);277 278  DataConsumer.initialize(Ctx);279 280  if (Opts.IndexMacrosInPreprocessor)281    indexPreprocessorMacros(PP, DataConsumer);282 283  for (const Decl *D : Decls)284    IndexCtx.indexTopLevelDecl(D);285  DataConsumer.finish();286}287 288std::unique_ptr<PPCallbacks>289index::indexMacrosCallback(IndexDataConsumer &Consumer, IndexingOptions Opts) {290  return std::make_unique<IndexPPCallbacks>(291      std::make_shared<IndexingContext>(Opts, Consumer));292}293 294void index::indexModuleFile(serialization::ModuleFile &Mod, ASTReader &Reader,295                            IndexDataConsumer &DataConsumer,296                            IndexingOptions Opts) {297  ASTContext &Ctx = Reader.getContext();298  IndexingContext IndexCtx(Opts, DataConsumer);299  IndexCtx.setASTContext(Ctx);300  DataConsumer.initialize(Ctx);301 302  if (Opts.IndexMacrosInPreprocessor) {303    indexPreprocessorModuleMacros(Reader.getPreprocessor(), Mod, DataConsumer);304  }305 306  for (const Decl *D : Reader.getModuleFileLevelDecls(Mod)) {307    IndexCtx.indexTopLevelDecl(D);308  }309  DataConsumer.finish();310}311