123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511 |
- //===- IndexingContext.cpp - Indexing context data ------------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "IndexingContext.h"
- #include "clang/AST/ASTContext.h"
- #include "clang/AST/Attr.h"
- #include "clang/AST/DeclObjC.h"
- #include "clang/AST/DeclTemplate.h"
- #include "clang/Basic/SourceLocation.h"
- #include "clang/Basic/SourceManager.h"
- #include "clang/Index/IndexDataConsumer.h"
- using namespace clang;
- using namespace index;
- static bool isGeneratedDecl(const Decl *D) {
- if (auto *attr = D->getAttr<ExternalSourceSymbolAttr>()) {
- return attr->getGeneratedDeclaration();
- }
- return false;
- }
- bool IndexingContext::shouldIndex(const Decl *D) {
- return !isGeneratedDecl(D);
- }
- const LangOptions &IndexingContext::getLangOpts() const {
- return Ctx->getLangOpts();
- }
- bool IndexingContext::shouldIndexFunctionLocalSymbols() const {
- return IndexOpts.IndexFunctionLocals;
- }
- bool IndexingContext::shouldIndexImplicitInstantiation() const {
- return IndexOpts.IndexImplicitInstantiation;
- }
- bool IndexingContext::shouldIndexParametersInDeclarations() const {
- return IndexOpts.IndexParametersInDeclarations;
- }
- bool IndexingContext::shouldIndexTemplateParameters() const {
- return IndexOpts.IndexTemplateParameters;
- }
- bool IndexingContext::handleDecl(const Decl *D,
- SymbolRoleSet Roles,
- ArrayRef<SymbolRelation> Relations) {
- return handleDecl(D, D->getLocation(), Roles, Relations);
- }
- bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc,
- SymbolRoleSet Roles,
- ArrayRef<SymbolRelation> Relations,
- const DeclContext *DC) {
- if (!DC)
- DC = D->getDeclContext();
- const Decl *OrigD = D;
- if (isa<ObjCPropertyImplDecl>(D)) {
- D = cast<ObjCPropertyImplDecl>(D)->getPropertyDecl();
- }
- return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC),
- Roles, Relations,
- nullptr, OrigD, DC);
- }
- bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
- const NamedDecl *Parent,
- const DeclContext *DC,
- SymbolRoleSet Roles,
- ArrayRef<SymbolRelation> Relations,
- const Expr *RefE,
- const Decl *RefD) {
- if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
- return true;
- if (!shouldIndexTemplateParameters() &&
- (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
- isa<TemplateTemplateParmDecl>(D))) {
- return true;
- }
- return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
- RefE, RefD, DC);
- }
- static void reportModuleReferences(const Module *Mod,
- ArrayRef<SourceLocation> IdLocs,
- const ImportDecl *ImportD,
- IndexDataConsumer &DataConsumer) {
- if (!Mod)
- return;
- reportModuleReferences(Mod->Parent, IdLocs.drop_back(), ImportD,
- DataConsumer);
- DataConsumer.handleModuleOccurrence(
- ImportD, Mod, (SymbolRoleSet)SymbolRole::Reference, IdLocs.back());
- }
- bool IndexingContext::importedModule(const ImportDecl *ImportD) {
- if (ImportD->isInvalidDecl())
- return true;
- SourceLocation Loc;
- auto IdLocs = ImportD->getIdentifierLocs();
- if (!IdLocs.empty())
- Loc = IdLocs.back();
- else
- Loc = ImportD->getLocation();
- SourceManager &SM = Ctx->getSourceManager();
- FileID FID = SM.getFileID(SM.getFileLoc(Loc));
- if (FID.isInvalid())
- return true;
- bool Invalid = false;
- const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
- if (Invalid || !SEntry.isFile())
- return true;
- if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
- switch (IndexOpts.SystemSymbolFilter) {
- case IndexingOptions::SystemSymbolFilterKind::None:
- return true;
- case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
- case IndexingOptions::SystemSymbolFilterKind::All:
- break;
- }
- }
- const Module *Mod = ImportD->getImportedModule();
- if (!ImportD->isImplicit() && Mod->Parent && !IdLocs.empty()) {
- reportModuleReferences(Mod->Parent, IdLocs.drop_back(), ImportD,
- DataConsumer);
- }
- SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration;
- if (ImportD->isImplicit())
- Roles |= (unsigned)SymbolRole::Implicit;
- return DataConsumer.handleModuleOccurrence(ImportD, Mod, Roles, Loc);
- }
- bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
- TemplateSpecializationKind TKind = TSK_Undeclared;
- if (const ClassTemplateSpecializationDecl *
- SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
- TKind = SD->getSpecializationKind();
- } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- TKind = FD->getTemplateSpecializationKind();
- } else if (auto *VD = dyn_cast<VarDecl>(D)) {
- TKind = VD->getTemplateSpecializationKind();
- } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
- if (RD->getInstantiatedFromMemberClass())
- TKind = RD->getTemplateSpecializationKind();
- } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
- if (ED->getInstantiatedFromMemberEnum())
- TKind = ED->getTemplateSpecializationKind();
- } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D) ||
- isa<EnumConstantDecl>(D)) {
- if (const auto *Parent = dyn_cast<Decl>(D->getDeclContext()))
- return isTemplateImplicitInstantiation(Parent);
- }
- switch (TKind) {
- case TSK_Undeclared:
- // Instantiation maybe not happen yet when we see a SpecializationDecl,
- // e.g. when the type doesn't need to be complete, we still treat it as an
- // instantiation as we'd like to keep the canonicalized result consistent.
- return isa<ClassTemplateSpecializationDecl>(D);
- case TSK_ExplicitSpecialization:
- return false;
- case TSK_ImplicitInstantiation:
- case TSK_ExplicitInstantiationDeclaration:
- case TSK_ExplicitInstantiationDefinition:
- return true;
- }
- llvm_unreachable("invalid TemplateSpecializationKind");
- }
- bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
- if (isa<ObjCInterfaceDecl>(D))
- return false;
- if (isa<ObjCCategoryDecl>(D))
- return false;
- if (isa<ObjCIvarDecl>(D))
- return false;
- if (isa<ObjCMethodDecl>(D))
- return false;
- if (isa<ImportDecl>(D))
- return false;
- return true;
- }
- static const CXXRecordDecl *
- getDeclContextForTemplateInstationPattern(const Decl *D) {
- if (const auto *CTSD =
- dyn_cast<ClassTemplateSpecializationDecl>(D->getDeclContext()))
- return CTSD->getTemplateInstantiationPattern();
- else if (const auto *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext()))
- return RD->getInstantiatedFromMemberClass();
- return nullptr;
- }
- static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
- if (const ClassTemplateSpecializationDecl *
- SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
- const auto *Template = SD->getTemplateInstantiationPattern();
- if (Template)
- return Template;
- // Fallback to primary template if no instantiation is available yet (e.g.
- // the type doesn't need to be complete).
- return SD->getSpecializedTemplate()->getTemplatedDecl();
- } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- return FD->getTemplateInstantiationPattern();
- } else if (auto *VD = dyn_cast<VarDecl>(D)) {
- return VD->getTemplateInstantiationPattern();
- } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
- return RD->getInstantiatedFromMemberClass();
- } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
- return ED->getInstantiatedFromMemberEnum();
- } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) {
- const auto *ND = cast<NamedDecl>(D);
- if (const CXXRecordDecl *Pattern =
- getDeclContextForTemplateInstationPattern(ND)) {
- for (const NamedDecl *BaseND : Pattern->lookup(ND->getDeclName())) {
- if (BaseND->isImplicit())
- continue;
- if (BaseND->getKind() == ND->getKind())
- return BaseND;
- }
- }
- } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
- if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) {
- if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) {
- for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName()))
- return BaseECD;
- }
- }
- }
- return nullptr;
- }
- static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) {
- if (auto VD = dyn_cast<VarDecl>(D))
- return VD->isThisDeclarationADefinition(Ctx);
- if (auto FD = dyn_cast<FunctionDecl>(D))
- return FD->isThisDeclarationADefinition();
- if (auto TD = dyn_cast<TagDecl>(D))
- return TD->isThisDeclarationADefinition();
- if (auto MD = dyn_cast<ObjCMethodDecl>(D))
- return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC);
- if (isa<TypedefNameDecl>(D) ||
- isa<EnumConstantDecl>(D) ||
- isa<FieldDecl>(D) ||
- isa<MSPropertyDecl>(D) ||
- isa<ObjCImplDecl>(D) ||
- isa<ObjCPropertyImplDecl>(D))
- return true;
- return false;
- }
- /// Whether the given NamedDecl should be skipped because it has no name.
- static bool shouldSkipNamelessDecl(const NamedDecl *ND) {
- return (ND->getDeclName().isEmpty() && !isa<TagDecl>(ND) &&
- !isa<ObjCCategoryDecl>(ND)) || isa<CXXDeductionGuideDecl>(ND);
- }
- static const Decl *adjustParent(const Decl *Parent) {
- if (!Parent)
- return nullptr;
- for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
- if (isa<TranslationUnitDecl>(Parent))
- return nullptr;
- if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
- continue;
- if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
- if (NS->isAnonymousNamespace())
- continue;
- } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
- if (RD->isAnonymousStructOrUnion())
- continue;
- } else if (auto ND = dyn_cast<NamedDecl>(Parent)) {
- if (shouldSkipNamelessDecl(ND))
- continue;
- }
- return Parent;
- }
- }
- static const Decl *getCanonicalDecl(const Decl *D) {
- D = D->getCanonicalDecl();
- if (auto TD = dyn_cast<TemplateDecl>(D)) {
- if (auto TTD = TD->getTemplatedDecl()) {
- D = TTD;
- assert(D->isCanonicalDecl());
- }
- }
- return D;
- }
- static bool shouldReportOccurrenceForSystemDeclOnlyMode(
- bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) {
- if (!IsRef)
- return true;
- auto acceptForRelation = [](SymbolRoleSet roles) -> bool {
- bool accept = false;
- applyForEachSymbolRoleInterruptible(roles, [&accept](SymbolRole r) -> bool {
- switch (r) {
- case SymbolRole::RelationChildOf:
- case SymbolRole::RelationBaseOf:
- case SymbolRole::RelationOverrideOf:
- case SymbolRole::RelationExtendedBy:
- case SymbolRole::RelationAccessorOf:
- case SymbolRole::RelationIBTypeOf:
- accept = true;
- return false;
- case SymbolRole::Declaration:
- case SymbolRole::Definition:
- case SymbolRole::Reference:
- case SymbolRole::Read:
- case SymbolRole::Write:
- case SymbolRole::Call:
- case SymbolRole::Dynamic:
- case SymbolRole::AddressOf:
- case SymbolRole::Implicit:
- case SymbolRole::Undefinition:
- case SymbolRole::RelationReceivedBy:
- case SymbolRole::RelationCalledBy:
- case SymbolRole::RelationContainedBy:
- case SymbolRole::RelationSpecializationOf:
- case SymbolRole::NameReference:
- return true;
- }
- llvm_unreachable("Unsupported SymbolRole value!");
- });
- return accept;
- };
- for (auto &Rel : Relations) {
- if (acceptForRelation(Rel.Roles))
- return true;
- }
- return false;
- }
- bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
- bool IsRef, const Decl *Parent,
- SymbolRoleSet Roles,
- ArrayRef<SymbolRelation> Relations,
- const Expr *OrigE,
- const Decl *OrigD,
- const DeclContext *ContainerDC) {
- if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
- return true;
- if (!isa<NamedDecl>(D) || shouldSkipNamelessDecl(cast<NamedDecl>(D)))
- return true;
- SourceManager &SM = Ctx->getSourceManager();
- FileID FID = SM.getFileID(SM.getFileLoc(Loc));
- if (FID.isInvalid())
- return true;
- bool Invalid = false;
- const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
- if (Invalid || !SEntry.isFile())
- return true;
- if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
- switch (IndexOpts.SystemSymbolFilter) {
- case IndexingOptions::SystemSymbolFilterKind::None:
- return true;
- case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
- if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations))
- return true;
- break;
- case IndexingOptions::SystemSymbolFilterKind::All:
- break;
- }
- }
- if (!OrigD)
- OrigD = D;
- if (isTemplateImplicitInstantiation(D)) {
- if (!IsRef)
- return true;
- D = adjustTemplateImplicitInstantiation(D);
- if (!D)
- return true;
- assert(!isTemplateImplicitInstantiation(D));
- }
- if (IsRef)
- Roles |= (unsigned)SymbolRole::Reference;
- else if (isDeclADefinition(OrigD, ContainerDC, *Ctx))
- Roles |= (unsigned)SymbolRole::Definition;
- else
- Roles |= (unsigned)SymbolRole::Declaration;
- D = getCanonicalDecl(D);
- Parent = adjustParent(Parent);
- if (Parent)
- Parent = getCanonicalDecl(Parent);
- SmallVector<SymbolRelation, 6> FinalRelations;
- FinalRelations.reserve(Relations.size()+1);
- auto addRelation = [&](SymbolRelation Rel) {
- auto It = llvm::find_if(FinalRelations, [&](SymbolRelation Elem) -> bool {
- return Elem.RelatedSymbol == Rel.RelatedSymbol;
- });
- if (It != FinalRelations.end()) {
- It->Roles |= Rel.Roles;
- } else {
- FinalRelations.push_back(Rel);
- }
- Roles |= Rel.Roles;
- };
- if (Parent) {
- if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) {
- addRelation(SymbolRelation{
- (unsigned)SymbolRole::RelationContainedBy,
- Parent
- });
- } else {
- addRelation(SymbolRelation{
- (unsigned)SymbolRole::RelationChildOf,
- Parent
- });
- }
- }
- for (auto &Rel : Relations) {
- addRelation(SymbolRelation(Rel.Roles,
- Rel.RelatedSymbol->getCanonicalDecl()));
- }
- IndexDataConsumer::ASTNodeInfo Node{OrigE, OrigD, Parent, ContainerDC};
- return DataConsumer.handleDeclOccurrence(D, Roles, FinalRelations, Loc, Node);
- }
- void IndexingContext::handleMacroDefined(const IdentifierInfo &Name,
- SourceLocation Loc,
- const MacroInfo &MI) {
- if (!shouldIndexMacroOccurrence(/*IsRef=*/false, Loc))
- return;
- SymbolRoleSet Roles = (unsigned)SymbolRole::Definition;
- DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
- }
- void IndexingContext::handleMacroUndefined(const IdentifierInfo &Name,
- SourceLocation Loc,
- const MacroInfo &MI) {
- if (!shouldIndexMacroOccurrence(/*IsRef=*/false, Loc))
- return;
- SymbolRoleSet Roles = (unsigned)SymbolRole::Undefinition;
- DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
- }
- void IndexingContext::handleMacroReference(const IdentifierInfo &Name,
- SourceLocation Loc,
- const MacroInfo &MI) {
- if (!shouldIndexMacroOccurrence(/*IsRef=*/true, Loc))
- return;
- SymbolRoleSet Roles = (unsigned)SymbolRole::Reference;
- DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
- }
- bool IndexingContext::shouldIndexMacroOccurrence(bool IsRef,
- SourceLocation Loc) {
- if (!IndexOpts.IndexMacros)
- return false;
- switch (IndexOpts.SystemSymbolFilter) {
- case IndexingOptions::SystemSymbolFilterKind::None:
- break;
- case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
- if (!IsRef)
- return true;
- break;
- case IndexingOptions::SystemSymbolFilterKind::All:
- return true;
- }
- SourceManager &SM = Ctx->getSourceManager();
- FileID FID = SM.getFileID(SM.getFileLoc(Loc));
- if (FID.isInvalid())
- return false;
- bool Invalid = false;
- const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
- if (Invalid || !SEntry.isFile())
- return false;
- return SEntry.getFile().getFileCharacteristic() == SrcMgr::C_User;
- }
|