xref: /freebsd/contrib/llvm-project/clang/lib/Index/IndexingContext.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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 
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,
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 
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 
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 
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 
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 *
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 
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 
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.
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 
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 
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 
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 
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 
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 
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 
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 
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