Path: blob/main/contrib/llvm-project/clang/lib/Index/IndexingAction.cpp
35234 views
//===- IndexingAction.cpp - Frontend index action -------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "clang/Index/IndexingAction.h"9#include "IndexingContext.h"10#include "clang/Frontend/CompilerInstance.h"11#include "clang/Frontend/FrontendAction.h"12#include "clang/Frontend/MultiplexConsumer.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 "llvm/ADT/STLExtras.h"18#include <memory>1920using namespace clang;21using namespace clang::index;2223namespace {2425class IndexPPCallbacks final : public PPCallbacks {26std::shared_ptr<IndexingContext> IndexCtx;2728public:29IndexPPCallbacks(std::shared_ptr<IndexingContext> IndexCtx)30: IndexCtx(std::move(IndexCtx)) {}3132void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,33SourceRange Range, const MacroArgs *Args) override {34IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),35Range.getBegin(), *MD.getMacroInfo());36}3738void MacroDefined(const Token &MacroNameTok,39const MacroDirective *MD) override {40IndexCtx->handleMacroDefined(*MacroNameTok.getIdentifierInfo(),41MacroNameTok.getLocation(),42*MD->getMacroInfo());43}4445void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD,46const MacroDirective *Undef) override {47if (!MD.getMacroInfo()) // Ignore noop #undef.48return;49IndexCtx->handleMacroUndefined(*MacroNameTok.getIdentifierInfo(),50MacroNameTok.getLocation(),51*MD.getMacroInfo());52}5354void Defined(const Token &MacroNameTok, const MacroDefinition &MD,55SourceRange Range) override {56if (!MD.getMacroInfo()) // Ignore nonexistent macro.57return;58// Note: this is defined(M), not #define M59IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),60MacroNameTok.getLocation(),61*MD.getMacroInfo());62}63void Ifdef(SourceLocation Loc, const Token &MacroNameTok,64const MacroDefinition &MD) override {65if (!MD.getMacroInfo()) // Ignore non-existent macro.66return;67IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),68MacroNameTok.getLocation(),69*MD.getMacroInfo());70}71void Ifndef(SourceLocation Loc, const Token &MacroNameTok,72const MacroDefinition &MD) override {73if (!MD.getMacroInfo()) // Ignore nonexistent macro.74return;75IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),76MacroNameTok.getLocation(),77*MD.getMacroInfo());78}7980using PPCallbacks::Elifdef;81using PPCallbacks::Elifndef;82void Elifdef(SourceLocation Loc, const Token &MacroNameTok,83const MacroDefinition &MD) override {84if (!MD.getMacroInfo()) // Ignore non-existent macro.85return;86IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),87MacroNameTok.getLocation(),88*MD.getMacroInfo());89}90void Elifndef(SourceLocation Loc, const Token &MacroNameTok,91const MacroDefinition &MD) override {92if (!MD.getMacroInfo()) // Ignore non-existent macro.93return;94IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),95MacroNameTok.getLocation(),96*MD.getMacroInfo());97}98};99100class IndexASTConsumer final : public ASTConsumer {101std::shared_ptr<IndexDataConsumer> DataConsumer;102std::shared_ptr<IndexingContext> IndexCtx;103std::shared_ptr<Preprocessor> PP;104std::function<bool(const Decl *)> ShouldSkipFunctionBody;105106public:107IndexASTConsumer(std::shared_ptr<IndexDataConsumer> DataConsumer,108const IndexingOptions &Opts,109std::shared_ptr<Preprocessor> PP,110std::function<bool(const Decl *)> ShouldSkipFunctionBody)111: DataConsumer(std::move(DataConsumer)),112IndexCtx(new IndexingContext(Opts, *this->DataConsumer)),113PP(std::move(PP)),114ShouldSkipFunctionBody(std::move(ShouldSkipFunctionBody)) {115assert(this->DataConsumer != nullptr);116assert(this->PP != nullptr);117}118119protected:120void Initialize(ASTContext &Context) override {121IndexCtx->setASTContext(Context);122IndexCtx->getDataConsumer().initialize(Context);123IndexCtx->getDataConsumer().setPreprocessor(PP);124PP->addPPCallbacks(std::make_unique<IndexPPCallbacks>(IndexCtx));125}126127bool HandleTopLevelDecl(DeclGroupRef DG) override {128return IndexCtx->indexDeclGroupRef(DG);129}130131void HandleInterestingDecl(DeclGroupRef DG) override {132// Ignore deserialized decls.133}134135void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {136IndexCtx->indexDeclGroupRef(DG);137}138139void HandleTranslationUnit(ASTContext &Ctx) override {140DataConsumer->finish();141}142143bool shouldSkipFunctionBody(Decl *D) override {144return ShouldSkipFunctionBody(D);145}146};147148class IndexAction final : public ASTFrontendAction {149std::shared_ptr<IndexDataConsumer> DataConsumer;150IndexingOptions Opts;151152public:153IndexAction(std::shared_ptr<IndexDataConsumer> DataConsumer,154const IndexingOptions &Opts)155: DataConsumer(std::move(DataConsumer)), Opts(Opts) {156assert(this->DataConsumer != nullptr);157}158159protected:160std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,161StringRef InFile) override {162return std::make_unique<IndexASTConsumer>(163DataConsumer, Opts, CI.getPreprocessorPtr(),164/*ShouldSkipFunctionBody=*/[](const Decl *) { return false; });165}166};167168} // anonymous namespace169170std::unique_ptr<ASTConsumer> index::createIndexingASTConsumer(171std::shared_ptr<IndexDataConsumer> DataConsumer,172const IndexingOptions &Opts, std::shared_ptr<Preprocessor> PP,173std::function<bool(const Decl *)> ShouldSkipFunctionBody) {174return std::make_unique<IndexASTConsumer>(DataConsumer, Opts, PP,175ShouldSkipFunctionBody);176}177178std::unique_ptr<ASTConsumer> clang::index::createIndexingASTConsumer(179std::shared_ptr<IndexDataConsumer> DataConsumer,180const IndexingOptions &Opts, std::shared_ptr<Preprocessor> PP) {181std::function<bool(const Decl *)> ShouldSkipFunctionBody = [](const Decl *) {182return false;183};184if (Opts.ShouldTraverseDecl)185ShouldSkipFunctionBody =186[ShouldTraverseDecl(Opts.ShouldTraverseDecl)](const Decl *D) {187return !ShouldTraverseDecl(D);188};189return createIndexingASTConsumer(std::move(DataConsumer), Opts, std::move(PP),190std::move(ShouldSkipFunctionBody));191}192193std::unique_ptr<FrontendAction>194index::createIndexingAction(std::shared_ptr<IndexDataConsumer> DataConsumer,195const IndexingOptions &Opts) {196assert(DataConsumer != nullptr);197return std::make_unique<IndexAction>(std::move(DataConsumer), Opts);198}199200static bool topLevelDeclVisitor(void *context, const Decl *D) {201IndexingContext &IndexCtx = *static_cast<IndexingContext *>(context);202return IndexCtx.indexTopLevelDecl(D);203}204205static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx) {206Unit.visitLocalTopLevelDecls(&IndexCtx, topLevelDeclVisitor);207}208209static void indexPreprocessorMacro(const IdentifierInfo *II,210const MacroInfo *MI,211MacroDirective::Kind DirectiveKind,212SourceLocation Loc,213IndexDataConsumer &DataConsumer) {214// When using modules, it may happen that we find #undef of a macro that215// was defined in another module. In such case, MI may be nullptr, since216// we only look for macro definitions in the current TU. In that case,217// there is nothing to index.218if (!MI)219return;220221// Skip implicit visibility change.222if (DirectiveKind == MacroDirective::MD_Visibility)223return;224225auto Role = DirectiveKind == MacroDirective::MD_Define226? SymbolRole::Definition227: SymbolRole::Undefinition;228DataConsumer.handleMacroOccurrence(II, MI, static_cast<unsigned>(Role), Loc);229}230231static void indexPreprocessorMacros(Preprocessor &PP,232IndexDataConsumer &DataConsumer) {233for (const auto &M : PP.macros()) {234for (auto *MD = M.second.getLatest(); MD; MD = MD->getPrevious()) {235indexPreprocessorMacro(M.first, MD->getMacroInfo(), MD->getKind(),236MD->getLocation(), DataConsumer);237}238}239}240241static void indexPreprocessorModuleMacros(Preprocessor &PP,242serialization::ModuleFile &Mod,243IndexDataConsumer &DataConsumer) {244for (const auto &M : PP.macros()) {245if (M.second.getLatest() == nullptr) {246for (auto *MM : PP.getLeafModuleMacros(M.first)) {247auto *OwningMod = MM->getOwningModule();248if (OwningMod && OwningMod->getASTFile() == Mod.File) {249if (auto *MI = MM->getMacroInfo()) {250indexPreprocessorMacro(M.first, MI, MacroDirective::MD_Define,251MI->getDefinitionLoc(), DataConsumer);252}253}254}255}256}257}258259void index::indexASTUnit(ASTUnit &Unit, IndexDataConsumer &DataConsumer,260IndexingOptions Opts) {261IndexingContext IndexCtx(Opts, DataConsumer);262IndexCtx.setASTContext(Unit.getASTContext());263DataConsumer.initialize(Unit.getASTContext());264DataConsumer.setPreprocessor(Unit.getPreprocessorPtr());265266if (Opts.IndexMacrosInPreprocessor)267indexPreprocessorMacros(Unit.getPreprocessor(), DataConsumer);268indexTranslationUnit(Unit, IndexCtx);269DataConsumer.finish();270}271272void index::indexTopLevelDecls(ASTContext &Ctx, Preprocessor &PP,273ArrayRef<const Decl *> Decls,274IndexDataConsumer &DataConsumer,275IndexingOptions Opts) {276IndexingContext IndexCtx(Opts, DataConsumer);277IndexCtx.setASTContext(Ctx);278279DataConsumer.initialize(Ctx);280281if (Opts.IndexMacrosInPreprocessor)282indexPreprocessorMacros(PP, DataConsumer);283284for (const Decl *D : Decls)285IndexCtx.indexTopLevelDecl(D);286DataConsumer.finish();287}288289std::unique_ptr<PPCallbacks>290index::indexMacrosCallback(IndexDataConsumer &Consumer, IndexingOptions Opts) {291return std::make_unique<IndexPPCallbacks>(292std::make_shared<IndexingContext>(Opts, Consumer));293}294295void index::indexModuleFile(serialization::ModuleFile &Mod, ASTReader &Reader,296IndexDataConsumer &DataConsumer,297IndexingOptions Opts) {298ASTContext &Ctx = Reader.getContext();299IndexingContext IndexCtx(Opts, DataConsumer);300IndexCtx.setASTContext(Ctx);301DataConsumer.initialize(Ctx);302303if (Opts.IndexMacrosInPreprocessor) {304indexPreprocessorModuleMacros(Reader.getPreprocessor(), Mod, DataConsumer);305}306307for (const Decl *D : Reader.getModuleFileLevelDecls(Mod)) {308IndexCtx.indexTopLevelDecl(D);309}310DataConsumer.finish();311}312313314