10b57cec5SDimitry Andric //===- IndexingContext.cpp - Indexing context data ------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "IndexingContext.h"
100b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
11480093f4SDimitry Andric #include "clang/AST/Attr.h"
120b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h"
13480093f4SDimitry Andric #include "clang/AST/DeclTemplate.h"
14480093f4SDimitry Andric #include "clang/Basic/SourceLocation.h"
150b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
16480093f4SDimitry Andric #include "clang/Index/IndexDataConsumer.h"
170b57cec5SDimitry Andric
180b57cec5SDimitry Andric using namespace clang;
190b57cec5SDimitry Andric using namespace index;
200b57cec5SDimitry Andric
isGeneratedDecl(const Decl * D)210b57cec5SDimitry Andric static bool isGeneratedDecl(const Decl *D) {
220b57cec5SDimitry Andric if (auto *attr = D->getAttr<ExternalSourceSymbolAttr>()) {
230b57cec5SDimitry Andric return attr->getGeneratedDeclaration();
240b57cec5SDimitry Andric }
250b57cec5SDimitry Andric return false;
260b57cec5SDimitry Andric }
270b57cec5SDimitry Andric
shouldIndex(const Decl * D)280b57cec5SDimitry Andric bool IndexingContext::shouldIndex(const Decl *D) {
290b57cec5SDimitry Andric return !isGeneratedDecl(D);
300b57cec5SDimitry Andric }
310b57cec5SDimitry Andric
getLangOpts() const320b57cec5SDimitry Andric const LangOptions &IndexingContext::getLangOpts() const {
330b57cec5SDimitry Andric return Ctx->getLangOpts();
340b57cec5SDimitry Andric }
350b57cec5SDimitry Andric
shouldIndexFunctionLocalSymbols() const360b57cec5SDimitry Andric bool IndexingContext::shouldIndexFunctionLocalSymbols() const {
370b57cec5SDimitry Andric return IndexOpts.IndexFunctionLocals;
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric
shouldIndexImplicitInstantiation() const400b57cec5SDimitry Andric bool IndexingContext::shouldIndexImplicitInstantiation() const {
410b57cec5SDimitry Andric return IndexOpts.IndexImplicitInstantiation;
420b57cec5SDimitry Andric }
430b57cec5SDimitry Andric
shouldIndexParametersInDeclarations() const440b57cec5SDimitry Andric bool IndexingContext::shouldIndexParametersInDeclarations() const {
450b57cec5SDimitry Andric return IndexOpts.IndexParametersInDeclarations;
460b57cec5SDimitry Andric }
470b57cec5SDimitry Andric
shouldIndexTemplateParameters() const480b57cec5SDimitry Andric bool IndexingContext::shouldIndexTemplateParameters() const {
490b57cec5SDimitry Andric return IndexOpts.IndexTemplateParameters;
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric
handleDecl(const Decl * D,SymbolRoleSet Roles,ArrayRef<SymbolRelation> Relations)520b57cec5SDimitry Andric bool IndexingContext::handleDecl(const Decl *D,
530b57cec5SDimitry Andric SymbolRoleSet Roles,
540b57cec5SDimitry Andric ArrayRef<SymbolRelation> Relations) {
550b57cec5SDimitry Andric return handleDecl(D, D->getLocation(), Roles, Relations);
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric
handleDecl(const Decl * D,SourceLocation Loc,SymbolRoleSet Roles,ArrayRef<SymbolRelation> Relations,const DeclContext * DC)580b57cec5SDimitry Andric bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc,
590b57cec5SDimitry Andric SymbolRoleSet Roles,
600b57cec5SDimitry Andric ArrayRef<SymbolRelation> Relations,
610b57cec5SDimitry Andric const DeclContext *DC) {
620b57cec5SDimitry Andric if (!DC)
630b57cec5SDimitry Andric DC = D->getDeclContext();
640b57cec5SDimitry Andric
650b57cec5SDimitry Andric const Decl *OrigD = D;
660b57cec5SDimitry Andric if (isa<ObjCPropertyImplDecl>(D)) {
670b57cec5SDimitry Andric D = cast<ObjCPropertyImplDecl>(D)->getPropertyDecl();
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC),
700b57cec5SDimitry Andric Roles, Relations,
710b57cec5SDimitry Andric nullptr, OrigD, DC);
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric
handleReference(const NamedDecl * D,SourceLocation Loc,const NamedDecl * Parent,const DeclContext * DC,SymbolRoleSet Roles,ArrayRef<SymbolRelation> Relations,const Expr * RefE)740b57cec5SDimitry Andric bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
750b57cec5SDimitry Andric const NamedDecl *Parent,
760b57cec5SDimitry Andric const DeclContext *DC,
770b57cec5SDimitry Andric SymbolRoleSet Roles,
780b57cec5SDimitry Andric ArrayRef<SymbolRelation> Relations,
79*5f757f3fSDimitry Andric const Expr *RefE) {
800b57cec5SDimitry Andric if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
810b57cec5SDimitry Andric return true;
820b57cec5SDimitry Andric
830b57cec5SDimitry Andric if (!shouldIndexTemplateParameters() &&
840b57cec5SDimitry Andric (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
850b57cec5SDimitry Andric isa<TemplateTemplateParmDecl>(D))) {
860b57cec5SDimitry Andric return true;
870b57cec5SDimitry Andric }
880b57cec5SDimitry Andric return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
89*5f757f3fSDimitry Andric RefE, nullptr, DC);
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric
reportModuleReferences(const Module * Mod,ArrayRef<SourceLocation> IdLocs,const ImportDecl * ImportD,IndexDataConsumer & DataConsumer)920b57cec5SDimitry Andric static void reportModuleReferences(const Module *Mod,
930b57cec5SDimitry Andric ArrayRef<SourceLocation> IdLocs,
940b57cec5SDimitry Andric const ImportDecl *ImportD,
950b57cec5SDimitry Andric IndexDataConsumer &DataConsumer) {
960b57cec5SDimitry Andric if (!Mod)
970b57cec5SDimitry Andric return;
980b57cec5SDimitry Andric reportModuleReferences(Mod->Parent, IdLocs.drop_back(), ImportD,
990b57cec5SDimitry Andric DataConsumer);
100480093f4SDimitry Andric DataConsumer.handleModuleOccurrence(
101480093f4SDimitry Andric ImportD, Mod, (SymbolRoleSet)SymbolRole::Reference, IdLocs.back());
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric
importedModule(const ImportDecl * ImportD)1040b57cec5SDimitry Andric bool IndexingContext::importedModule(const ImportDecl *ImportD) {
1050b57cec5SDimitry Andric if (ImportD->isInvalidDecl())
1060b57cec5SDimitry Andric return true;
1070b57cec5SDimitry Andric
1080b57cec5SDimitry Andric SourceLocation Loc;
1090b57cec5SDimitry Andric auto IdLocs = ImportD->getIdentifierLocs();
1100b57cec5SDimitry Andric if (!IdLocs.empty())
1110b57cec5SDimitry Andric Loc = IdLocs.back();
1120b57cec5SDimitry Andric else
1130b57cec5SDimitry Andric Loc = ImportD->getLocation();
1140b57cec5SDimitry Andric
1150b57cec5SDimitry Andric SourceManager &SM = Ctx->getSourceManager();
1160b57cec5SDimitry Andric FileID FID = SM.getFileID(SM.getFileLoc(Loc));
1170b57cec5SDimitry Andric if (FID.isInvalid())
1180b57cec5SDimitry Andric return true;
1190b57cec5SDimitry Andric
1200b57cec5SDimitry Andric bool Invalid = false;
1210b57cec5SDimitry Andric const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
1220b57cec5SDimitry Andric if (Invalid || !SEntry.isFile())
1230b57cec5SDimitry Andric return true;
1240b57cec5SDimitry Andric
1250b57cec5SDimitry Andric if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
1260b57cec5SDimitry Andric switch (IndexOpts.SystemSymbolFilter) {
1270b57cec5SDimitry Andric case IndexingOptions::SystemSymbolFilterKind::None:
1280b57cec5SDimitry Andric return true;
1290b57cec5SDimitry Andric case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
1300b57cec5SDimitry Andric case IndexingOptions::SystemSymbolFilterKind::All:
1310b57cec5SDimitry Andric break;
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric }
1340b57cec5SDimitry Andric
1350b57cec5SDimitry Andric const Module *Mod = ImportD->getImportedModule();
1360b57cec5SDimitry Andric if (!ImportD->isImplicit() && Mod->Parent && !IdLocs.empty()) {
1370b57cec5SDimitry Andric reportModuleReferences(Mod->Parent, IdLocs.drop_back(), ImportD,
1380b57cec5SDimitry Andric DataConsumer);
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric
1410b57cec5SDimitry Andric SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration;
1420b57cec5SDimitry Andric if (ImportD->isImplicit())
1430b57cec5SDimitry Andric Roles |= (unsigned)SymbolRole::Implicit;
1440b57cec5SDimitry Andric
145480093f4SDimitry Andric return DataConsumer.handleModuleOccurrence(ImportD, Mod, Roles, Loc);
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric
isTemplateImplicitInstantiation(const Decl * D)1480b57cec5SDimitry Andric bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
1490b57cec5SDimitry Andric TemplateSpecializationKind TKind = TSK_Undeclared;
1500b57cec5SDimitry Andric if (const ClassTemplateSpecializationDecl *
1510b57cec5SDimitry Andric SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
1520b57cec5SDimitry Andric TKind = SD->getSpecializationKind();
1530b57cec5SDimitry Andric } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
1540b57cec5SDimitry Andric TKind = FD->getTemplateSpecializationKind();
1550b57cec5SDimitry Andric } else if (auto *VD = dyn_cast<VarDecl>(D)) {
1560b57cec5SDimitry Andric TKind = VD->getTemplateSpecializationKind();
1570b57cec5SDimitry Andric } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
1580b57cec5SDimitry Andric if (RD->getInstantiatedFromMemberClass())
1590b57cec5SDimitry Andric TKind = RD->getTemplateSpecializationKind();
1600b57cec5SDimitry Andric } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
1610b57cec5SDimitry Andric if (ED->getInstantiatedFromMemberEnum())
1620b57cec5SDimitry Andric TKind = ED->getTemplateSpecializationKind();
1630b57cec5SDimitry Andric } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D) ||
1640b57cec5SDimitry Andric isa<EnumConstantDecl>(D)) {
1650b57cec5SDimitry Andric if (const auto *Parent = dyn_cast<Decl>(D->getDeclContext()))
1660b57cec5SDimitry Andric return isTemplateImplicitInstantiation(Parent);
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric switch (TKind) {
1690b57cec5SDimitry Andric case TSK_Undeclared:
1705ffd83dbSDimitry Andric // Instantiation maybe not happen yet when we see a SpecializationDecl,
1715ffd83dbSDimitry Andric // e.g. when the type doesn't need to be complete, we still treat it as an
1725ffd83dbSDimitry Andric // instantiation as we'd like to keep the canonicalized result consistent.
1735ffd83dbSDimitry Andric return isa<ClassTemplateSpecializationDecl>(D);
1740b57cec5SDimitry Andric case TSK_ExplicitSpecialization:
1750b57cec5SDimitry Andric return false;
1760b57cec5SDimitry Andric case TSK_ImplicitInstantiation:
1770b57cec5SDimitry Andric case TSK_ExplicitInstantiationDeclaration:
1780b57cec5SDimitry Andric case TSK_ExplicitInstantiationDefinition:
1790b57cec5SDimitry Andric return true;
1800b57cec5SDimitry Andric }
1810b57cec5SDimitry Andric llvm_unreachable("invalid TemplateSpecializationKind");
1820b57cec5SDimitry Andric }
1830b57cec5SDimitry Andric
shouldIgnoreIfImplicit(const Decl * D)1840b57cec5SDimitry Andric bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
1850b57cec5SDimitry Andric if (isa<ObjCInterfaceDecl>(D))
1860b57cec5SDimitry Andric return false;
1870b57cec5SDimitry Andric if (isa<ObjCCategoryDecl>(D))
1880b57cec5SDimitry Andric return false;
1890b57cec5SDimitry Andric if (isa<ObjCIvarDecl>(D))
1900b57cec5SDimitry Andric return false;
1910b57cec5SDimitry Andric if (isa<ObjCMethodDecl>(D))
1920b57cec5SDimitry Andric return false;
1930b57cec5SDimitry Andric if (isa<ImportDecl>(D))
1940b57cec5SDimitry Andric return false;
1950b57cec5SDimitry Andric return true;
1960b57cec5SDimitry Andric }
1970b57cec5SDimitry Andric
1980b57cec5SDimitry Andric static const CXXRecordDecl *
getDeclContextForTemplateInstationPattern(const Decl * D)1990b57cec5SDimitry Andric getDeclContextForTemplateInstationPattern(const Decl *D) {
2000b57cec5SDimitry Andric if (const auto *CTSD =
2010b57cec5SDimitry Andric dyn_cast<ClassTemplateSpecializationDecl>(D->getDeclContext()))
2020b57cec5SDimitry Andric return CTSD->getTemplateInstantiationPattern();
2030b57cec5SDimitry Andric else if (const auto *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext()))
2040b57cec5SDimitry Andric return RD->getInstantiatedFromMemberClass();
2050b57cec5SDimitry Andric return nullptr;
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric
adjustTemplateImplicitInstantiation(const Decl * D)2080b57cec5SDimitry Andric static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
2090b57cec5SDimitry Andric if (const ClassTemplateSpecializationDecl *
2100b57cec5SDimitry Andric SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
2115ffd83dbSDimitry Andric const auto *Template = SD->getTemplateInstantiationPattern();
2125ffd83dbSDimitry Andric if (Template)
2135ffd83dbSDimitry Andric return Template;
2145ffd83dbSDimitry Andric // Fallback to primary template if no instantiation is available yet (e.g.
2155ffd83dbSDimitry Andric // the type doesn't need to be complete).
2165ffd83dbSDimitry Andric return SD->getSpecializedTemplate()->getTemplatedDecl();
2170b57cec5SDimitry Andric } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
2180b57cec5SDimitry Andric return FD->getTemplateInstantiationPattern();
2190b57cec5SDimitry Andric } else if (auto *VD = dyn_cast<VarDecl>(D)) {
2200b57cec5SDimitry Andric return VD->getTemplateInstantiationPattern();
2210b57cec5SDimitry Andric } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
2220b57cec5SDimitry Andric return RD->getInstantiatedFromMemberClass();
2230b57cec5SDimitry Andric } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
2240b57cec5SDimitry Andric return ED->getInstantiatedFromMemberEnum();
2250b57cec5SDimitry Andric } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) {
2260b57cec5SDimitry Andric const auto *ND = cast<NamedDecl>(D);
2270b57cec5SDimitry Andric if (const CXXRecordDecl *Pattern =
2280b57cec5SDimitry Andric getDeclContextForTemplateInstationPattern(ND)) {
2290b57cec5SDimitry Andric for (const NamedDecl *BaseND : Pattern->lookup(ND->getDeclName())) {
2300b57cec5SDimitry Andric if (BaseND->isImplicit())
2310b57cec5SDimitry Andric continue;
2320b57cec5SDimitry Andric if (BaseND->getKind() == ND->getKind())
2330b57cec5SDimitry Andric return BaseND;
2340b57cec5SDimitry Andric }
2350b57cec5SDimitry Andric }
2360b57cec5SDimitry Andric } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
2370b57cec5SDimitry Andric if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) {
2380b57cec5SDimitry Andric if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) {
2390b57cec5SDimitry Andric for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName()))
2400b57cec5SDimitry Andric return BaseECD;
2410b57cec5SDimitry Andric }
2420b57cec5SDimitry Andric }
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric return nullptr;
2450b57cec5SDimitry Andric }
2460b57cec5SDimitry Andric
isDeclADefinition(const Decl * D,const DeclContext * ContainerDC,ASTContext & Ctx)2470b57cec5SDimitry Andric static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) {
2480b57cec5SDimitry Andric if (auto VD = dyn_cast<VarDecl>(D))
2490b57cec5SDimitry Andric return VD->isThisDeclarationADefinition(Ctx);
2500b57cec5SDimitry Andric
2510b57cec5SDimitry Andric if (auto FD = dyn_cast<FunctionDecl>(D))
2520b57cec5SDimitry Andric return FD->isThisDeclarationADefinition();
2530b57cec5SDimitry Andric
2540b57cec5SDimitry Andric if (auto TD = dyn_cast<TagDecl>(D))
2550b57cec5SDimitry Andric return TD->isThisDeclarationADefinition();
2560b57cec5SDimitry Andric
2570b57cec5SDimitry Andric if (auto MD = dyn_cast<ObjCMethodDecl>(D))
2580b57cec5SDimitry Andric return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC);
2590b57cec5SDimitry Andric
26081ad6265SDimitry Andric if (isa<TypedefNameDecl>(D) || isa<EnumConstantDecl>(D) ||
26181ad6265SDimitry Andric isa<FieldDecl>(D) || isa<MSPropertyDecl>(D) || isa<ObjCImplDecl>(D) ||
26281ad6265SDimitry Andric isa<ObjCPropertyImplDecl>(D) || isa<ConceptDecl>(D))
2630b57cec5SDimitry Andric return true;
2640b57cec5SDimitry Andric
2650b57cec5SDimitry Andric return false;
2660b57cec5SDimitry Andric }
2670b57cec5SDimitry Andric
2680b57cec5SDimitry Andric /// Whether the given NamedDecl should be skipped because it has no name.
shouldSkipNamelessDecl(const NamedDecl * ND)2690b57cec5SDimitry Andric static bool shouldSkipNamelessDecl(const NamedDecl *ND) {
2700b57cec5SDimitry Andric return (ND->getDeclName().isEmpty() && !isa<TagDecl>(ND) &&
2710b57cec5SDimitry Andric !isa<ObjCCategoryDecl>(ND)) || isa<CXXDeductionGuideDecl>(ND);
2720b57cec5SDimitry Andric }
2730b57cec5SDimitry Andric
adjustParent(const Decl * Parent)2740b57cec5SDimitry Andric static const Decl *adjustParent(const Decl *Parent) {
2750b57cec5SDimitry Andric if (!Parent)
2760b57cec5SDimitry Andric return nullptr;
2770b57cec5SDimitry Andric for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
2780b57cec5SDimitry Andric if (isa<TranslationUnitDecl>(Parent))
2790b57cec5SDimitry Andric return nullptr;
2800b57cec5SDimitry Andric if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
2810b57cec5SDimitry Andric continue;
2820b57cec5SDimitry Andric if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
2830b57cec5SDimitry Andric if (NS->isAnonymousNamespace())
2840b57cec5SDimitry Andric continue;
2850b57cec5SDimitry Andric } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
2860b57cec5SDimitry Andric if (RD->isAnonymousStructOrUnion())
2870b57cec5SDimitry Andric continue;
2880b57cec5SDimitry Andric } else if (auto ND = dyn_cast<NamedDecl>(Parent)) {
2890b57cec5SDimitry Andric if (shouldSkipNamelessDecl(ND))
2900b57cec5SDimitry Andric continue;
2910b57cec5SDimitry Andric }
2920b57cec5SDimitry Andric return Parent;
2930b57cec5SDimitry Andric }
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric
getCanonicalDecl(const Decl * D)2960b57cec5SDimitry Andric static const Decl *getCanonicalDecl(const Decl *D) {
2970b57cec5SDimitry Andric D = D->getCanonicalDecl();
2980b57cec5SDimitry Andric if (auto TD = dyn_cast<TemplateDecl>(D)) {
2990b57cec5SDimitry Andric if (auto TTD = TD->getTemplatedDecl()) {
3000b57cec5SDimitry Andric D = TTD;
3010b57cec5SDimitry Andric assert(D->isCanonicalDecl());
3020b57cec5SDimitry Andric }
3030b57cec5SDimitry Andric }
3040b57cec5SDimitry Andric
3050b57cec5SDimitry Andric return D;
3060b57cec5SDimitry Andric }
3070b57cec5SDimitry Andric
shouldReportOccurrenceForSystemDeclOnlyMode(bool IsRef,SymbolRoleSet Roles,ArrayRef<SymbolRelation> Relations)3080b57cec5SDimitry Andric static bool shouldReportOccurrenceForSystemDeclOnlyMode(
3090b57cec5SDimitry Andric bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) {
3100b57cec5SDimitry Andric if (!IsRef)
3110b57cec5SDimitry Andric return true;
3120b57cec5SDimitry Andric
3130b57cec5SDimitry Andric auto acceptForRelation = [](SymbolRoleSet roles) -> bool {
3140b57cec5SDimitry Andric bool accept = false;
3150b57cec5SDimitry Andric applyForEachSymbolRoleInterruptible(roles, [&accept](SymbolRole r) -> bool {
3160b57cec5SDimitry Andric switch (r) {
3170b57cec5SDimitry Andric case SymbolRole::RelationChildOf:
3180b57cec5SDimitry Andric case SymbolRole::RelationBaseOf:
3190b57cec5SDimitry Andric case SymbolRole::RelationOverrideOf:
3200b57cec5SDimitry Andric case SymbolRole::RelationExtendedBy:
3210b57cec5SDimitry Andric case SymbolRole::RelationAccessorOf:
3220b57cec5SDimitry Andric case SymbolRole::RelationIBTypeOf:
3230b57cec5SDimitry Andric accept = true;
3240b57cec5SDimitry Andric return false;
3250b57cec5SDimitry Andric case SymbolRole::Declaration:
3260b57cec5SDimitry Andric case SymbolRole::Definition:
3270b57cec5SDimitry Andric case SymbolRole::Reference:
3280b57cec5SDimitry Andric case SymbolRole::Read:
3290b57cec5SDimitry Andric case SymbolRole::Write:
3300b57cec5SDimitry Andric case SymbolRole::Call:
3310b57cec5SDimitry Andric case SymbolRole::Dynamic:
3320b57cec5SDimitry Andric case SymbolRole::AddressOf:
3330b57cec5SDimitry Andric case SymbolRole::Implicit:
3340b57cec5SDimitry Andric case SymbolRole::Undefinition:
3350b57cec5SDimitry Andric case SymbolRole::RelationReceivedBy:
3360b57cec5SDimitry Andric case SymbolRole::RelationCalledBy:
3370b57cec5SDimitry Andric case SymbolRole::RelationContainedBy:
3380b57cec5SDimitry Andric case SymbolRole::RelationSpecializationOf:
3390b57cec5SDimitry Andric case SymbolRole::NameReference:
3400b57cec5SDimitry Andric return true;
3410b57cec5SDimitry Andric }
3420b57cec5SDimitry Andric llvm_unreachable("Unsupported SymbolRole value!");
3430b57cec5SDimitry Andric });
3440b57cec5SDimitry Andric return accept;
3450b57cec5SDimitry Andric };
3460b57cec5SDimitry Andric
3470b57cec5SDimitry Andric for (auto &Rel : Relations) {
3480b57cec5SDimitry Andric if (acceptForRelation(Rel.Roles))
3490b57cec5SDimitry Andric return true;
3500b57cec5SDimitry Andric }
3510b57cec5SDimitry Andric
3520b57cec5SDimitry Andric return false;
3530b57cec5SDimitry Andric }
3540b57cec5SDimitry Andric
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)3550b57cec5SDimitry Andric bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
3560b57cec5SDimitry Andric bool IsRef, const Decl *Parent,
3570b57cec5SDimitry Andric SymbolRoleSet Roles,
3580b57cec5SDimitry Andric ArrayRef<SymbolRelation> Relations,
3590b57cec5SDimitry Andric const Expr *OrigE,
3600b57cec5SDimitry Andric const Decl *OrigD,
3610b57cec5SDimitry Andric const DeclContext *ContainerDC) {
3620b57cec5SDimitry Andric if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
3630b57cec5SDimitry Andric return true;
3640b57cec5SDimitry Andric if (!isa<NamedDecl>(D) || shouldSkipNamelessDecl(cast<NamedDecl>(D)))
3650b57cec5SDimitry Andric return true;
3660b57cec5SDimitry Andric
3670b57cec5SDimitry Andric SourceManager &SM = Ctx->getSourceManager();
3680b57cec5SDimitry Andric FileID FID = SM.getFileID(SM.getFileLoc(Loc));
3690b57cec5SDimitry Andric if (FID.isInvalid())
3700b57cec5SDimitry Andric return true;
3710b57cec5SDimitry Andric
3720b57cec5SDimitry Andric bool Invalid = false;
3730b57cec5SDimitry Andric const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
3740b57cec5SDimitry Andric if (Invalid || !SEntry.isFile())
3750b57cec5SDimitry Andric return true;
3760b57cec5SDimitry Andric
3770b57cec5SDimitry Andric if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
3780b57cec5SDimitry Andric switch (IndexOpts.SystemSymbolFilter) {
3790b57cec5SDimitry Andric case IndexingOptions::SystemSymbolFilterKind::None:
3800b57cec5SDimitry Andric return true;
3810b57cec5SDimitry Andric case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
3820b57cec5SDimitry Andric if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations))
3830b57cec5SDimitry Andric return true;
3840b57cec5SDimitry Andric break;
3850b57cec5SDimitry Andric case IndexingOptions::SystemSymbolFilterKind::All:
3860b57cec5SDimitry Andric break;
3870b57cec5SDimitry Andric }
3880b57cec5SDimitry Andric }
3890b57cec5SDimitry Andric
3900b57cec5SDimitry Andric if (!OrigD)
3910b57cec5SDimitry Andric OrigD = D;
3920b57cec5SDimitry Andric
3930b57cec5SDimitry Andric if (isTemplateImplicitInstantiation(D)) {
3940b57cec5SDimitry Andric if (!IsRef)
3950b57cec5SDimitry Andric return true;
3960b57cec5SDimitry Andric D = adjustTemplateImplicitInstantiation(D);
3970b57cec5SDimitry Andric if (!D)
3980b57cec5SDimitry Andric return true;
3990b57cec5SDimitry Andric assert(!isTemplateImplicitInstantiation(D));
4000b57cec5SDimitry Andric }
4010b57cec5SDimitry Andric
4020b57cec5SDimitry Andric if (IsRef)
4030b57cec5SDimitry Andric Roles |= (unsigned)SymbolRole::Reference;
4040b57cec5SDimitry Andric else if (isDeclADefinition(OrigD, ContainerDC, *Ctx))
4050b57cec5SDimitry Andric Roles |= (unsigned)SymbolRole::Definition;
4060b57cec5SDimitry Andric else
4070b57cec5SDimitry Andric Roles |= (unsigned)SymbolRole::Declaration;
4080b57cec5SDimitry Andric
4090b57cec5SDimitry Andric D = getCanonicalDecl(D);
4100b57cec5SDimitry Andric Parent = adjustParent(Parent);
4110b57cec5SDimitry Andric if (Parent)
4120b57cec5SDimitry Andric Parent = getCanonicalDecl(Parent);
4130b57cec5SDimitry Andric
4140b57cec5SDimitry Andric SmallVector<SymbolRelation, 6> FinalRelations;
4150b57cec5SDimitry Andric FinalRelations.reserve(Relations.size()+1);
4160b57cec5SDimitry Andric
4170b57cec5SDimitry Andric auto addRelation = [&](SymbolRelation Rel) {
4180b57cec5SDimitry Andric auto It = llvm::find_if(FinalRelations, [&](SymbolRelation Elem) -> bool {
4190b57cec5SDimitry Andric return Elem.RelatedSymbol == Rel.RelatedSymbol;
4200b57cec5SDimitry Andric });
4210b57cec5SDimitry Andric if (It != FinalRelations.end()) {
4220b57cec5SDimitry Andric It->Roles |= Rel.Roles;
4230b57cec5SDimitry Andric } else {
4240b57cec5SDimitry Andric FinalRelations.push_back(Rel);
4250b57cec5SDimitry Andric }
4260b57cec5SDimitry Andric Roles |= Rel.Roles;
4270b57cec5SDimitry Andric };
4280b57cec5SDimitry Andric
4290b57cec5SDimitry Andric if (Parent) {
4300b57cec5SDimitry Andric if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) {
4310b57cec5SDimitry Andric addRelation(SymbolRelation{
4320b57cec5SDimitry Andric (unsigned)SymbolRole::RelationContainedBy,
4330b57cec5SDimitry Andric Parent
4340b57cec5SDimitry Andric });
4350b57cec5SDimitry Andric } else {
4360b57cec5SDimitry Andric addRelation(SymbolRelation{
4370b57cec5SDimitry Andric (unsigned)SymbolRole::RelationChildOf,
4380b57cec5SDimitry Andric Parent
4390b57cec5SDimitry Andric });
4400b57cec5SDimitry Andric }
4410b57cec5SDimitry Andric }
4420b57cec5SDimitry Andric
4430b57cec5SDimitry Andric for (auto &Rel : Relations) {
4440b57cec5SDimitry Andric addRelation(SymbolRelation(Rel.Roles,
4450b57cec5SDimitry Andric Rel.RelatedSymbol->getCanonicalDecl()));
4460b57cec5SDimitry Andric }
4470b57cec5SDimitry Andric
4480b57cec5SDimitry Andric IndexDataConsumer::ASTNodeInfo Node{OrigE, OrigD, Parent, ContainerDC};
449480093f4SDimitry Andric return DataConsumer.handleDeclOccurrence(D, Roles, FinalRelations, Loc, Node);
4500b57cec5SDimitry Andric }
4510b57cec5SDimitry Andric
handleMacroDefined(const IdentifierInfo & Name,SourceLocation Loc,const MacroInfo & MI)4520b57cec5SDimitry Andric void IndexingContext::handleMacroDefined(const IdentifierInfo &Name,
4530b57cec5SDimitry Andric SourceLocation Loc,
4540b57cec5SDimitry Andric const MacroInfo &MI) {
455fe6060f1SDimitry Andric if (!shouldIndexMacroOccurrence(/*IsRef=*/false, Loc))
456fe6060f1SDimitry Andric return;
4570b57cec5SDimitry Andric SymbolRoleSet Roles = (unsigned)SymbolRole::Definition;
458480093f4SDimitry Andric DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
4590b57cec5SDimitry Andric }
4600b57cec5SDimitry Andric
handleMacroUndefined(const IdentifierInfo & Name,SourceLocation Loc,const MacroInfo & MI)4610b57cec5SDimitry Andric void IndexingContext::handleMacroUndefined(const IdentifierInfo &Name,
4620b57cec5SDimitry Andric SourceLocation Loc,
4630b57cec5SDimitry Andric const MacroInfo &MI) {
464fe6060f1SDimitry Andric if (!shouldIndexMacroOccurrence(/*IsRef=*/false, Loc))
465fe6060f1SDimitry Andric return;
4660b57cec5SDimitry Andric SymbolRoleSet Roles = (unsigned)SymbolRole::Undefinition;
467480093f4SDimitry Andric DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
4680b57cec5SDimitry Andric }
4690b57cec5SDimitry Andric
handleMacroReference(const IdentifierInfo & Name,SourceLocation Loc,const MacroInfo & MI)4700b57cec5SDimitry Andric void IndexingContext::handleMacroReference(const IdentifierInfo &Name,
4710b57cec5SDimitry Andric SourceLocation Loc,
4720b57cec5SDimitry Andric const MacroInfo &MI) {
473fe6060f1SDimitry Andric if (!shouldIndexMacroOccurrence(/*IsRef=*/true, Loc))
474fe6060f1SDimitry Andric return;
4750b57cec5SDimitry Andric SymbolRoleSet Roles = (unsigned)SymbolRole::Reference;
476480093f4SDimitry Andric DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
4770b57cec5SDimitry Andric }
478fe6060f1SDimitry Andric
shouldIndexMacroOccurrence(bool IsRef,SourceLocation Loc)479fe6060f1SDimitry Andric bool IndexingContext::shouldIndexMacroOccurrence(bool IsRef,
480fe6060f1SDimitry Andric SourceLocation Loc) {
481fe6060f1SDimitry Andric if (!IndexOpts.IndexMacros)
482fe6060f1SDimitry Andric return false;
483fe6060f1SDimitry Andric
484fe6060f1SDimitry Andric switch (IndexOpts.SystemSymbolFilter) {
485fe6060f1SDimitry Andric case IndexingOptions::SystemSymbolFilterKind::None:
486fe6060f1SDimitry Andric break;
487fe6060f1SDimitry Andric case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
488fe6060f1SDimitry Andric if (!IsRef)
489fe6060f1SDimitry Andric return true;
490fe6060f1SDimitry Andric break;
491fe6060f1SDimitry Andric case IndexingOptions::SystemSymbolFilterKind::All:
492fe6060f1SDimitry Andric return true;
493fe6060f1SDimitry Andric }
494fe6060f1SDimitry Andric
495fe6060f1SDimitry Andric SourceManager &SM = Ctx->getSourceManager();
496fe6060f1SDimitry Andric FileID FID = SM.getFileID(SM.getFileLoc(Loc));
497fe6060f1SDimitry Andric if (FID.isInvalid())
498fe6060f1SDimitry Andric return false;
499fe6060f1SDimitry Andric
500fe6060f1SDimitry Andric bool Invalid = false;
501fe6060f1SDimitry Andric const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
502fe6060f1SDimitry Andric if (Invalid || !SEntry.isFile())
503fe6060f1SDimitry Andric return false;
504fe6060f1SDimitry Andric
505fe6060f1SDimitry Andric return SEntry.getFile().getFileCharacteristic() == SrcMgr::C_User;
506fe6060f1SDimitry Andric }
507