xref: /freebsd/contrib/llvm-project/clang/lib/Index/IndexingContext.cpp (revision 480093f4440d54b30b3025afeac24b48f2ba7a2e)
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"
11*480093f4SDimitry Andric #include "clang/AST/Attr.h"
120b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h"
13*480093f4SDimitry Andric #include "clang/AST/DeclTemplate.h"
14*480093f4SDimitry Andric #include "clang/Basic/SourceLocation.h"
150b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
16*480093f4SDimitry Andric #include "clang/Index/IndexDataConsumer.h"
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric using namespace clang;
190b57cec5SDimitry Andric using namespace index;
200b57cec5SDimitry Andric 
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 
280b57cec5SDimitry Andric bool IndexingContext::shouldIndex(const Decl *D) {
290b57cec5SDimitry Andric   return !isGeneratedDecl(D);
300b57cec5SDimitry Andric }
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric const LangOptions &IndexingContext::getLangOpts() const {
330b57cec5SDimitry Andric   return Ctx->getLangOpts();
340b57cec5SDimitry Andric }
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric bool IndexingContext::shouldIndexFunctionLocalSymbols() const {
370b57cec5SDimitry Andric   return IndexOpts.IndexFunctionLocals;
380b57cec5SDimitry Andric }
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric bool IndexingContext::shouldIndexImplicitInstantiation() const {
410b57cec5SDimitry Andric   return IndexOpts.IndexImplicitInstantiation;
420b57cec5SDimitry Andric }
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric bool IndexingContext::shouldIndexParametersInDeclarations() const {
450b57cec5SDimitry Andric   return IndexOpts.IndexParametersInDeclarations;
460b57cec5SDimitry Andric }
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric bool IndexingContext::shouldIndexTemplateParameters() const {
490b57cec5SDimitry Andric   return IndexOpts.IndexTemplateParameters;
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric 
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 
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 
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,
790b57cec5SDimitry Andric                                       const Expr *RefE,
800b57cec5SDimitry Andric                                       const Decl *RefD) {
810b57cec5SDimitry Andric   if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
820b57cec5SDimitry Andric     return true;
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   if (!shouldIndexTemplateParameters() &&
850b57cec5SDimitry Andric       (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
860b57cec5SDimitry Andric        isa<TemplateTemplateParmDecl>(D))) {
870b57cec5SDimitry Andric     return true;
880b57cec5SDimitry Andric   }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric   return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
910b57cec5SDimitry Andric                               RefE, RefD, DC);
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric static void reportModuleReferences(const Module *Mod,
950b57cec5SDimitry Andric                                    ArrayRef<SourceLocation> IdLocs,
960b57cec5SDimitry Andric                                    const ImportDecl *ImportD,
970b57cec5SDimitry Andric                                    IndexDataConsumer &DataConsumer) {
980b57cec5SDimitry Andric   if (!Mod)
990b57cec5SDimitry Andric     return;
1000b57cec5SDimitry Andric   reportModuleReferences(Mod->Parent, IdLocs.drop_back(), ImportD,
1010b57cec5SDimitry Andric                          DataConsumer);
102*480093f4SDimitry Andric   DataConsumer.handleModuleOccurrence(
103*480093f4SDimitry Andric       ImportD, Mod, (SymbolRoleSet)SymbolRole::Reference, IdLocs.back());
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric bool IndexingContext::importedModule(const ImportDecl *ImportD) {
1070b57cec5SDimitry Andric   if (ImportD->isInvalidDecl())
1080b57cec5SDimitry Andric     return true;
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric   SourceLocation Loc;
1110b57cec5SDimitry Andric   auto IdLocs = ImportD->getIdentifierLocs();
1120b57cec5SDimitry Andric   if (!IdLocs.empty())
1130b57cec5SDimitry Andric     Loc = IdLocs.back();
1140b57cec5SDimitry Andric   else
1150b57cec5SDimitry Andric     Loc = ImportD->getLocation();
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   SourceManager &SM = Ctx->getSourceManager();
1180b57cec5SDimitry Andric   FileID FID = SM.getFileID(SM.getFileLoc(Loc));
1190b57cec5SDimitry Andric   if (FID.isInvalid())
1200b57cec5SDimitry Andric     return true;
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   bool Invalid = false;
1230b57cec5SDimitry Andric   const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
1240b57cec5SDimitry Andric   if (Invalid || !SEntry.isFile())
1250b57cec5SDimitry Andric     return true;
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
1280b57cec5SDimitry Andric     switch (IndexOpts.SystemSymbolFilter) {
1290b57cec5SDimitry Andric     case IndexingOptions::SystemSymbolFilterKind::None:
1300b57cec5SDimitry Andric       return true;
1310b57cec5SDimitry Andric     case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
1320b57cec5SDimitry Andric     case IndexingOptions::SystemSymbolFilterKind::All:
1330b57cec5SDimitry Andric       break;
1340b57cec5SDimitry Andric     }
1350b57cec5SDimitry Andric   }
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   const Module *Mod = ImportD->getImportedModule();
1380b57cec5SDimitry Andric   if (!ImportD->isImplicit() && Mod->Parent && !IdLocs.empty()) {
1390b57cec5SDimitry Andric     reportModuleReferences(Mod->Parent, IdLocs.drop_back(), ImportD,
1400b57cec5SDimitry Andric                            DataConsumer);
1410b57cec5SDimitry Andric   }
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration;
1440b57cec5SDimitry Andric   if (ImportD->isImplicit())
1450b57cec5SDimitry Andric     Roles |= (unsigned)SymbolRole::Implicit;
1460b57cec5SDimitry Andric 
147*480093f4SDimitry Andric   return DataConsumer.handleModuleOccurrence(ImportD, Mod, Roles, Loc);
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
1510b57cec5SDimitry Andric   TemplateSpecializationKind TKind = TSK_Undeclared;
1520b57cec5SDimitry Andric   if (const ClassTemplateSpecializationDecl *
1530b57cec5SDimitry Andric       SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
1540b57cec5SDimitry Andric     TKind = SD->getSpecializationKind();
1550b57cec5SDimitry Andric   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
1560b57cec5SDimitry Andric     TKind = FD->getTemplateSpecializationKind();
1570b57cec5SDimitry Andric   } else if (auto *VD = dyn_cast<VarDecl>(D)) {
1580b57cec5SDimitry Andric     TKind = VD->getTemplateSpecializationKind();
1590b57cec5SDimitry Andric   } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
1600b57cec5SDimitry Andric     if (RD->getInstantiatedFromMemberClass())
1610b57cec5SDimitry Andric       TKind = RD->getTemplateSpecializationKind();
1620b57cec5SDimitry Andric   } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
1630b57cec5SDimitry Andric     if (ED->getInstantiatedFromMemberEnum())
1640b57cec5SDimitry Andric       TKind = ED->getTemplateSpecializationKind();
1650b57cec5SDimitry Andric   } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D) ||
1660b57cec5SDimitry Andric              isa<EnumConstantDecl>(D)) {
1670b57cec5SDimitry Andric     if (const auto *Parent = dyn_cast<Decl>(D->getDeclContext()))
1680b57cec5SDimitry Andric       return isTemplateImplicitInstantiation(Parent);
1690b57cec5SDimitry Andric   }
1700b57cec5SDimitry Andric   switch (TKind) {
1710b57cec5SDimitry Andric     case TSK_Undeclared:
1720b57cec5SDimitry Andric     case TSK_ExplicitSpecialization:
1730b57cec5SDimitry Andric       return false;
1740b57cec5SDimitry Andric     case TSK_ImplicitInstantiation:
1750b57cec5SDimitry Andric     case TSK_ExplicitInstantiationDeclaration:
1760b57cec5SDimitry Andric     case TSK_ExplicitInstantiationDefinition:
1770b57cec5SDimitry Andric       return true;
1780b57cec5SDimitry Andric   }
1790b57cec5SDimitry Andric   llvm_unreachable("invalid TemplateSpecializationKind");
1800b57cec5SDimitry Andric }
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
1830b57cec5SDimitry Andric   if (isa<ObjCInterfaceDecl>(D))
1840b57cec5SDimitry Andric     return false;
1850b57cec5SDimitry Andric   if (isa<ObjCCategoryDecl>(D))
1860b57cec5SDimitry Andric     return false;
1870b57cec5SDimitry Andric   if (isa<ObjCIvarDecl>(D))
1880b57cec5SDimitry Andric     return false;
1890b57cec5SDimitry Andric   if (isa<ObjCMethodDecl>(D))
1900b57cec5SDimitry Andric     return false;
1910b57cec5SDimitry Andric   if (isa<ImportDecl>(D))
1920b57cec5SDimitry Andric     return false;
1930b57cec5SDimitry Andric   return true;
1940b57cec5SDimitry Andric }
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric static const CXXRecordDecl *
1970b57cec5SDimitry Andric getDeclContextForTemplateInstationPattern(const Decl *D) {
1980b57cec5SDimitry Andric   if (const auto *CTSD =
1990b57cec5SDimitry Andric           dyn_cast<ClassTemplateSpecializationDecl>(D->getDeclContext()))
2000b57cec5SDimitry Andric     return CTSD->getTemplateInstantiationPattern();
2010b57cec5SDimitry Andric   else if (const auto *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext()))
2020b57cec5SDimitry Andric     return RD->getInstantiatedFromMemberClass();
2030b57cec5SDimitry Andric   return nullptr;
2040b57cec5SDimitry Andric }
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
2070b57cec5SDimitry Andric   if (const ClassTemplateSpecializationDecl *
2080b57cec5SDimitry Andric       SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
2090b57cec5SDimitry Andric     return SD->getTemplateInstantiationPattern();
2100b57cec5SDimitry Andric   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
2110b57cec5SDimitry Andric     return FD->getTemplateInstantiationPattern();
2120b57cec5SDimitry Andric   } else if (auto *VD = dyn_cast<VarDecl>(D)) {
2130b57cec5SDimitry Andric     return VD->getTemplateInstantiationPattern();
2140b57cec5SDimitry Andric   } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
2150b57cec5SDimitry Andric     return RD->getInstantiatedFromMemberClass();
2160b57cec5SDimitry Andric   } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
2170b57cec5SDimitry Andric     return ED->getInstantiatedFromMemberEnum();
2180b57cec5SDimitry Andric   } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) {
2190b57cec5SDimitry Andric     const auto *ND = cast<NamedDecl>(D);
2200b57cec5SDimitry Andric     if (const CXXRecordDecl *Pattern =
2210b57cec5SDimitry Andric             getDeclContextForTemplateInstationPattern(ND)) {
2220b57cec5SDimitry Andric       for (const NamedDecl *BaseND : Pattern->lookup(ND->getDeclName())) {
2230b57cec5SDimitry Andric         if (BaseND->isImplicit())
2240b57cec5SDimitry Andric           continue;
2250b57cec5SDimitry Andric         if (BaseND->getKind() == ND->getKind())
2260b57cec5SDimitry Andric           return BaseND;
2270b57cec5SDimitry Andric       }
2280b57cec5SDimitry Andric     }
2290b57cec5SDimitry Andric   } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
2300b57cec5SDimitry Andric     if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) {
2310b57cec5SDimitry Andric       if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) {
2320b57cec5SDimitry Andric         for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName()))
2330b57cec5SDimitry Andric           return BaseECD;
2340b57cec5SDimitry Andric       }
2350b57cec5SDimitry Andric     }
2360b57cec5SDimitry Andric   }
2370b57cec5SDimitry Andric   return nullptr;
2380b57cec5SDimitry Andric }
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) {
2410b57cec5SDimitry Andric   if (auto VD = dyn_cast<VarDecl>(D))
2420b57cec5SDimitry Andric     return VD->isThisDeclarationADefinition(Ctx);
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric   if (auto FD = dyn_cast<FunctionDecl>(D))
2450b57cec5SDimitry Andric     return FD->isThisDeclarationADefinition();
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric   if (auto TD = dyn_cast<TagDecl>(D))
2480b57cec5SDimitry Andric     return TD->isThisDeclarationADefinition();
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric   if (auto MD = dyn_cast<ObjCMethodDecl>(D))
2510b57cec5SDimitry Andric     return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC);
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric   if (isa<TypedefNameDecl>(D) ||
2540b57cec5SDimitry Andric       isa<EnumConstantDecl>(D) ||
2550b57cec5SDimitry Andric       isa<FieldDecl>(D) ||
2560b57cec5SDimitry Andric       isa<MSPropertyDecl>(D) ||
2570b57cec5SDimitry Andric       isa<ObjCImplDecl>(D) ||
2580b57cec5SDimitry Andric       isa<ObjCPropertyImplDecl>(D))
2590b57cec5SDimitry Andric     return true;
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   return false;
2620b57cec5SDimitry Andric }
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric /// Whether the given NamedDecl should be skipped because it has no name.
2650b57cec5SDimitry Andric static bool shouldSkipNamelessDecl(const NamedDecl *ND) {
2660b57cec5SDimitry Andric   return (ND->getDeclName().isEmpty() && !isa<TagDecl>(ND) &&
2670b57cec5SDimitry Andric           !isa<ObjCCategoryDecl>(ND)) || isa<CXXDeductionGuideDecl>(ND);
2680b57cec5SDimitry Andric }
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric static const Decl *adjustParent(const Decl *Parent) {
2710b57cec5SDimitry Andric   if (!Parent)
2720b57cec5SDimitry Andric     return nullptr;
2730b57cec5SDimitry Andric   for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
2740b57cec5SDimitry Andric     if (isa<TranslationUnitDecl>(Parent))
2750b57cec5SDimitry Andric       return nullptr;
2760b57cec5SDimitry Andric     if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
2770b57cec5SDimitry Andric       continue;
2780b57cec5SDimitry Andric     if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
2790b57cec5SDimitry Andric       if (NS->isAnonymousNamespace())
2800b57cec5SDimitry Andric         continue;
2810b57cec5SDimitry Andric     } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
2820b57cec5SDimitry Andric       if (RD->isAnonymousStructOrUnion())
2830b57cec5SDimitry Andric         continue;
2840b57cec5SDimitry Andric     } else if (auto ND = dyn_cast<NamedDecl>(Parent)) {
2850b57cec5SDimitry Andric       if (shouldSkipNamelessDecl(ND))
2860b57cec5SDimitry Andric         continue;
2870b57cec5SDimitry Andric     }
2880b57cec5SDimitry Andric     return Parent;
2890b57cec5SDimitry Andric   }
2900b57cec5SDimitry Andric }
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric static const Decl *getCanonicalDecl(const Decl *D) {
2930b57cec5SDimitry Andric   D = D->getCanonicalDecl();
2940b57cec5SDimitry Andric   if (auto TD = dyn_cast<TemplateDecl>(D)) {
2950b57cec5SDimitry Andric     if (auto TTD = TD->getTemplatedDecl()) {
2960b57cec5SDimitry Andric       D = TTD;
2970b57cec5SDimitry Andric       assert(D->isCanonicalDecl());
2980b57cec5SDimitry Andric     }
2990b57cec5SDimitry Andric   }
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric   return D;
3020b57cec5SDimitry Andric }
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric static bool shouldReportOccurrenceForSystemDeclOnlyMode(
3050b57cec5SDimitry Andric     bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) {
3060b57cec5SDimitry Andric   if (!IsRef)
3070b57cec5SDimitry Andric     return true;
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   auto acceptForRelation = [](SymbolRoleSet roles) -> bool {
3100b57cec5SDimitry Andric     bool accept = false;
3110b57cec5SDimitry Andric     applyForEachSymbolRoleInterruptible(roles, [&accept](SymbolRole r) -> bool {
3120b57cec5SDimitry Andric       switch (r) {
3130b57cec5SDimitry Andric       case SymbolRole::RelationChildOf:
3140b57cec5SDimitry Andric       case SymbolRole::RelationBaseOf:
3150b57cec5SDimitry Andric       case SymbolRole::RelationOverrideOf:
3160b57cec5SDimitry Andric       case SymbolRole::RelationExtendedBy:
3170b57cec5SDimitry Andric       case SymbolRole::RelationAccessorOf:
3180b57cec5SDimitry Andric       case SymbolRole::RelationIBTypeOf:
3190b57cec5SDimitry Andric         accept = true;
3200b57cec5SDimitry Andric         return false;
3210b57cec5SDimitry Andric       case SymbolRole::Declaration:
3220b57cec5SDimitry Andric       case SymbolRole::Definition:
3230b57cec5SDimitry Andric       case SymbolRole::Reference:
3240b57cec5SDimitry Andric       case SymbolRole::Read:
3250b57cec5SDimitry Andric       case SymbolRole::Write:
3260b57cec5SDimitry Andric       case SymbolRole::Call:
3270b57cec5SDimitry Andric       case SymbolRole::Dynamic:
3280b57cec5SDimitry Andric       case SymbolRole::AddressOf:
3290b57cec5SDimitry Andric       case SymbolRole::Implicit:
3300b57cec5SDimitry Andric       case SymbolRole::Undefinition:
3310b57cec5SDimitry Andric       case SymbolRole::RelationReceivedBy:
3320b57cec5SDimitry Andric       case SymbolRole::RelationCalledBy:
3330b57cec5SDimitry Andric       case SymbolRole::RelationContainedBy:
3340b57cec5SDimitry Andric       case SymbolRole::RelationSpecializationOf:
3350b57cec5SDimitry Andric       case SymbolRole::NameReference:
3360b57cec5SDimitry Andric         return true;
3370b57cec5SDimitry Andric       }
3380b57cec5SDimitry Andric       llvm_unreachable("Unsupported SymbolRole value!");
3390b57cec5SDimitry Andric     });
3400b57cec5SDimitry Andric     return accept;
3410b57cec5SDimitry Andric   };
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric   for (auto &Rel : Relations) {
3440b57cec5SDimitry Andric     if (acceptForRelation(Rel.Roles))
3450b57cec5SDimitry Andric       return true;
3460b57cec5SDimitry Andric   }
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric   return false;
3490b57cec5SDimitry Andric }
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
3520b57cec5SDimitry Andric                                            bool IsRef, const Decl *Parent,
3530b57cec5SDimitry Andric                                            SymbolRoleSet Roles,
3540b57cec5SDimitry Andric                                            ArrayRef<SymbolRelation> Relations,
3550b57cec5SDimitry Andric                                            const Expr *OrigE,
3560b57cec5SDimitry Andric                                            const Decl *OrigD,
3570b57cec5SDimitry Andric                                            const DeclContext *ContainerDC) {
3580b57cec5SDimitry Andric   if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
3590b57cec5SDimitry Andric     return true;
3600b57cec5SDimitry Andric   if (!isa<NamedDecl>(D) || shouldSkipNamelessDecl(cast<NamedDecl>(D)))
3610b57cec5SDimitry Andric     return true;
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric   SourceManager &SM = Ctx->getSourceManager();
3640b57cec5SDimitry Andric   FileID FID = SM.getFileID(SM.getFileLoc(Loc));
3650b57cec5SDimitry Andric   if (FID.isInvalid())
3660b57cec5SDimitry Andric     return true;
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric   bool Invalid = false;
3690b57cec5SDimitry Andric   const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
3700b57cec5SDimitry Andric   if (Invalid || !SEntry.isFile())
3710b57cec5SDimitry Andric     return true;
3720b57cec5SDimitry Andric 
3730b57cec5SDimitry Andric   if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
3740b57cec5SDimitry Andric     switch (IndexOpts.SystemSymbolFilter) {
3750b57cec5SDimitry Andric     case IndexingOptions::SystemSymbolFilterKind::None:
3760b57cec5SDimitry Andric       return true;
3770b57cec5SDimitry Andric     case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
3780b57cec5SDimitry Andric       if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations))
3790b57cec5SDimitry Andric         return true;
3800b57cec5SDimitry Andric       break;
3810b57cec5SDimitry Andric     case IndexingOptions::SystemSymbolFilterKind::All:
3820b57cec5SDimitry Andric       break;
3830b57cec5SDimitry Andric     }
3840b57cec5SDimitry Andric   }
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric   if (!OrigD)
3870b57cec5SDimitry Andric     OrigD = D;
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric   if (isTemplateImplicitInstantiation(D)) {
3900b57cec5SDimitry Andric     if (!IsRef)
3910b57cec5SDimitry Andric       return true;
3920b57cec5SDimitry Andric     D = adjustTemplateImplicitInstantiation(D);
3930b57cec5SDimitry Andric     if (!D)
3940b57cec5SDimitry Andric       return true;
3950b57cec5SDimitry Andric     assert(!isTemplateImplicitInstantiation(D));
3960b57cec5SDimitry Andric   }
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric   if (IsRef)
3990b57cec5SDimitry Andric     Roles |= (unsigned)SymbolRole::Reference;
4000b57cec5SDimitry Andric   else if (isDeclADefinition(OrigD, ContainerDC, *Ctx))
4010b57cec5SDimitry Andric     Roles |= (unsigned)SymbolRole::Definition;
4020b57cec5SDimitry Andric   else
4030b57cec5SDimitry Andric     Roles |= (unsigned)SymbolRole::Declaration;
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric   D = getCanonicalDecl(D);
4060b57cec5SDimitry Andric   Parent = adjustParent(Parent);
4070b57cec5SDimitry Andric   if (Parent)
4080b57cec5SDimitry Andric     Parent = getCanonicalDecl(Parent);
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric   SmallVector<SymbolRelation, 6> FinalRelations;
4110b57cec5SDimitry Andric   FinalRelations.reserve(Relations.size()+1);
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric   auto addRelation = [&](SymbolRelation Rel) {
4140b57cec5SDimitry Andric     auto It = llvm::find_if(FinalRelations, [&](SymbolRelation Elem) -> bool {
4150b57cec5SDimitry Andric       return Elem.RelatedSymbol == Rel.RelatedSymbol;
4160b57cec5SDimitry Andric     });
4170b57cec5SDimitry Andric     if (It != FinalRelations.end()) {
4180b57cec5SDimitry Andric       It->Roles |= Rel.Roles;
4190b57cec5SDimitry Andric     } else {
4200b57cec5SDimitry Andric       FinalRelations.push_back(Rel);
4210b57cec5SDimitry Andric     }
4220b57cec5SDimitry Andric     Roles |= Rel.Roles;
4230b57cec5SDimitry Andric   };
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric   if (Parent) {
4260b57cec5SDimitry Andric     if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) {
4270b57cec5SDimitry Andric       addRelation(SymbolRelation{
4280b57cec5SDimitry Andric         (unsigned)SymbolRole::RelationContainedBy,
4290b57cec5SDimitry Andric         Parent
4300b57cec5SDimitry Andric       });
4310b57cec5SDimitry Andric     } else {
4320b57cec5SDimitry Andric       addRelation(SymbolRelation{
4330b57cec5SDimitry Andric         (unsigned)SymbolRole::RelationChildOf,
4340b57cec5SDimitry Andric         Parent
4350b57cec5SDimitry Andric       });
4360b57cec5SDimitry Andric     }
4370b57cec5SDimitry Andric   }
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric   for (auto &Rel : Relations) {
4400b57cec5SDimitry Andric     addRelation(SymbolRelation(Rel.Roles,
4410b57cec5SDimitry Andric                                Rel.RelatedSymbol->getCanonicalDecl()));
4420b57cec5SDimitry Andric   }
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric   IndexDataConsumer::ASTNodeInfo Node{OrigE, OrigD, Parent, ContainerDC};
445*480093f4SDimitry Andric   return DataConsumer.handleDeclOccurrence(D, Roles, FinalRelations, Loc, Node);
4460b57cec5SDimitry Andric }
4470b57cec5SDimitry Andric 
4480b57cec5SDimitry Andric void IndexingContext::handleMacroDefined(const IdentifierInfo &Name,
4490b57cec5SDimitry Andric                                          SourceLocation Loc,
4500b57cec5SDimitry Andric                                          const MacroInfo &MI) {
4510b57cec5SDimitry Andric   SymbolRoleSet Roles = (unsigned)SymbolRole::Definition;
452*480093f4SDimitry Andric   DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
4530b57cec5SDimitry Andric }
4540b57cec5SDimitry Andric 
4550b57cec5SDimitry Andric void IndexingContext::handleMacroUndefined(const IdentifierInfo &Name,
4560b57cec5SDimitry Andric                                            SourceLocation Loc,
4570b57cec5SDimitry Andric                                            const MacroInfo &MI) {
4580b57cec5SDimitry Andric   SymbolRoleSet Roles = (unsigned)SymbolRole::Undefinition;
459*480093f4SDimitry Andric   DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
4600b57cec5SDimitry Andric }
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric void IndexingContext::handleMacroReference(const IdentifierInfo &Name,
4630b57cec5SDimitry Andric                                            SourceLocation Loc,
4640b57cec5SDimitry Andric                                            const MacroInfo &MI) {
4650b57cec5SDimitry Andric   SymbolRoleSet Roles = (unsigned)SymbolRole::Reference;
466*480093f4SDimitry Andric   DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
4670b57cec5SDimitry Andric }
468