xref: /freebsd/contrib/llvm-project/clang/lib/Index/IndexingContext.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
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,
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);
102480093f4SDimitry Andric   DataConsumer.handleModuleOccurrence(
103480093f4SDimitry 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 
147480093f4SDimitry 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:
1725ffd83dbSDimitry Andric       // Instantiation maybe not happen yet when we see a SpecializationDecl,
1735ffd83dbSDimitry Andric       // e.g. when the type doesn't need to be complete, we still treat it as an
1745ffd83dbSDimitry Andric       // instantiation as we'd like to keep the canonicalized result consistent.
1755ffd83dbSDimitry Andric       return isa<ClassTemplateSpecializationDecl>(D);
1760b57cec5SDimitry Andric     case TSK_ExplicitSpecialization:
1770b57cec5SDimitry Andric       return false;
1780b57cec5SDimitry Andric     case TSK_ImplicitInstantiation:
1790b57cec5SDimitry Andric     case TSK_ExplicitInstantiationDeclaration:
1800b57cec5SDimitry Andric     case TSK_ExplicitInstantiationDefinition:
1810b57cec5SDimitry Andric       return true;
1820b57cec5SDimitry Andric   }
1830b57cec5SDimitry Andric   llvm_unreachable("invalid TemplateSpecializationKind");
1840b57cec5SDimitry Andric }
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
1870b57cec5SDimitry Andric   if (isa<ObjCInterfaceDecl>(D))
1880b57cec5SDimitry Andric     return false;
1890b57cec5SDimitry Andric   if (isa<ObjCCategoryDecl>(D))
1900b57cec5SDimitry Andric     return false;
1910b57cec5SDimitry Andric   if (isa<ObjCIvarDecl>(D))
1920b57cec5SDimitry Andric     return false;
1930b57cec5SDimitry Andric   if (isa<ObjCMethodDecl>(D))
1940b57cec5SDimitry Andric     return false;
1950b57cec5SDimitry Andric   if (isa<ImportDecl>(D))
1960b57cec5SDimitry Andric     return false;
1970b57cec5SDimitry Andric   return true;
1980b57cec5SDimitry Andric }
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric static const CXXRecordDecl *
2010b57cec5SDimitry Andric getDeclContextForTemplateInstationPattern(const Decl *D) {
2020b57cec5SDimitry Andric   if (const auto *CTSD =
2030b57cec5SDimitry Andric           dyn_cast<ClassTemplateSpecializationDecl>(D->getDeclContext()))
2040b57cec5SDimitry Andric     return CTSD->getTemplateInstantiationPattern();
2050b57cec5SDimitry Andric   else if (const auto *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext()))
2060b57cec5SDimitry Andric     return RD->getInstantiatedFromMemberClass();
2070b57cec5SDimitry Andric   return nullptr;
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
2110b57cec5SDimitry Andric   if (const ClassTemplateSpecializationDecl *
2120b57cec5SDimitry Andric       SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
2135ffd83dbSDimitry Andric     const auto *Template = SD->getTemplateInstantiationPattern();
2145ffd83dbSDimitry Andric     if (Template)
2155ffd83dbSDimitry Andric       return Template;
2165ffd83dbSDimitry Andric     // Fallback to primary template if no instantiation is available yet (e.g.
2175ffd83dbSDimitry Andric     // the type doesn't need to be complete).
2185ffd83dbSDimitry Andric     return SD->getSpecializedTemplate()->getTemplatedDecl();
2190b57cec5SDimitry Andric   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
2200b57cec5SDimitry Andric     return FD->getTemplateInstantiationPattern();
2210b57cec5SDimitry Andric   } else if (auto *VD = dyn_cast<VarDecl>(D)) {
2220b57cec5SDimitry Andric     return VD->getTemplateInstantiationPattern();
2230b57cec5SDimitry Andric   } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
2240b57cec5SDimitry Andric     return RD->getInstantiatedFromMemberClass();
2250b57cec5SDimitry Andric   } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
2260b57cec5SDimitry Andric     return ED->getInstantiatedFromMemberEnum();
2270b57cec5SDimitry Andric   } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) {
2280b57cec5SDimitry Andric     const auto *ND = cast<NamedDecl>(D);
2290b57cec5SDimitry Andric     if (const CXXRecordDecl *Pattern =
2300b57cec5SDimitry Andric             getDeclContextForTemplateInstationPattern(ND)) {
2310b57cec5SDimitry Andric       for (const NamedDecl *BaseND : Pattern->lookup(ND->getDeclName())) {
2320b57cec5SDimitry Andric         if (BaseND->isImplicit())
2330b57cec5SDimitry Andric           continue;
2340b57cec5SDimitry Andric         if (BaseND->getKind() == ND->getKind())
2350b57cec5SDimitry Andric           return BaseND;
2360b57cec5SDimitry Andric       }
2370b57cec5SDimitry Andric     }
2380b57cec5SDimitry Andric   } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
2390b57cec5SDimitry Andric     if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) {
2400b57cec5SDimitry Andric       if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) {
2410b57cec5SDimitry Andric         for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName()))
2420b57cec5SDimitry Andric           return BaseECD;
2430b57cec5SDimitry Andric       }
2440b57cec5SDimitry Andric     }
2450b57cec5SDimitry Andric   }
2460b57cec5SDimitry Andric   return nullptr;
2470b57cec5SDimitry Andric }
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) {
2500b57cec5SDimitry Andric   if (auto VD = dyn_cast<VarDecl>(D))
2510b57cec5SDimitry Andric     return VD->isThisDeclarationADefinition(Ctx);
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric   if (auto FD = dyn_cast<FunctionDecl>(D))
2540b57cec5SDimitry Andric     return FD->isThisDeclarationADefinition();
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric   if (auto TD = dyn_cast<TagDecl>(D))
2570b57cec5SDimitry Andric     return TD->isThisDeclarationADefinition();
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   if (auto MD = dyn_cast<ObjCMethodDecl>(D))
2600b57cec5SDimitry Andric     return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC);
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric   if (isa<TypedefNameDecl>(D) ||
2630b57cec5SDimitry Andric       isa<EnumConstantDecl>(D) ||
2640b57cec5SDimitry Andric       isa<FieldDecl>(D) ||
2650b57cec5SDimitry Andric       isa<MSPropertyDecl>(D) ||
2660b57cec5SDimitry Andric       isa<ObjCImplDecl>(D) ||
2670b57cec5SDimitry Andric       isa<ObjCPropertyImplDecl>(D))
2680b57cec5SDimitry Andric     return true;
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric   return false;
2710b57cec5SDimitry Andric }
2720b57cec5SDimitry Andric 
2730b57cec5SDimitry Andric /// Whether the given NamedDecl should be skipped because it has no name.
2740b57cec5SDimitry Andric static bool shouldSkipNamelessDecl(const NamedDecl *ND) {
2750b57cec5SDimitry Andric   return (ND->getDeclName().isEmpty() && !isa<TagDecl>(ND) &&
2760b57cec5SDimitry Andric           !isa<ObjCCategoryDecl>(ND)) || isa<CXXDeductionGuideDecl>(ND);
2770b57cec5SDimitry Andric }
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric static const Decl *adjustParent(const Decl *Parent) {
2800b57cec5SDimitry Andric   if (!Parent)
2810b57cec5SDimitry Andric     return nullptr;
2820b57cec5SDimitry Andric   for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
2830b57cec5SDimitry Andric     if (isa<TranslationUnitDecl>(Parent))
2840b57cec5SDimitry Andric       return nullptr;
2850b57cec5SDimitry Andric     if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
2860b57cec5SDimitry Andric       continue;
2870b57cec5SDimitry Andric     if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
2880b57cec5SDimitry Andric       if (NS->isAnonymousNamespace())
2890b57cec5SDimitry Andric         continue;
2900b57cec5SDimitry Andric     } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
2910b57cec5SDimitry Andric       if (RD->isAnonymousStructOrUnion())
2920b57cec5SDimitry Andric         continue;
2930b57cec5SDimitry Andric     } else if (auto ND = dyn_cast<NamedDecl>(Parent)) {
2940b57cec5SDimitry Andric       if (shouldSkipNamelessDecl(ND))
2950b57cec5SDimitry Andric         continue;
2960b57cec5SDimitry Andric     }
2970b57cec5SDimitry Andric     return Parent;
2980b57cec5SDimitry Andric   }
2990b57cec5SDimitry Andric }
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric static const Decl *getCanonicalDecl(const Decl *D) {
3020b57cec5SDimitry Andric   D = D->getCanonicalDecl();
3030b57cec5SDimitry Andric   if (auto TD = dyn_cast<TemplateDecl>(D)) {
3040b57cec5SDimitry Andric     if (auto TTD = TD->getTemplatedDecl()) {
3050b57cec5SDimitry Andric       D = TTD;
3060b57cec5SDimitry Andric       assert(D->isCanonicalDecl());
3070b57cec5SDimitry Andric     }
3080b57cec5SDimitry Andric   }
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric   return D;
3110b57cec5SDimitry Andric }
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric static bool shouldReportOccurrenceForSystemDeclOnlyMode(
3140b57cec5SDimitry Andric     bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) {
3150b57cec5SDimitry Andric   if (!IsRef)
3160b57cec5SDimitry Andric     return true;
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric   auto acceptForRelation = [](SymbolRoleSet roles) -> bool {
3190b57cec5SDimitry Andric     bool accept = false;
3200b57cec5SDimitry Andric     applyForEachSymbolRoleInterruptible(roles, [&accept](SymbolRole r) -> bool {
3210b57cec5SDimitry Andric       switch (r) {
3220b57cec5SDimitry Andric       case SymbolRole::RelationChildOf:
3230b57cec5SDimitry Andric       case SymbolRole::RelationBaseOf:
3240b57cec5SDimitry Andric       case SymbolRole::RelationOverrideOf:
3250b57cec5SDimitry Andric       case SymbolRole::RelationExtendedBy:
3260b57cec5SDimitry Andric       case SymbolRole::RelationAccessorOf:
3270b57cec5SDimitry Andric       case SymbolRole::RelationIBTypeOf:
3280b57cec5SDimitry Andric         accept = true;
3290b57cec5SDimitry Andric         return false;
3300b57cec5SDimitry Andric       case SymbolRole::Declaration:
3310b57cec5SDimitry Andric       case SymbolRole::Definition:
3320b57cec5SDimitry Andric       case SymbolRole::Reference:
3330b57cec5SDimitry Andric       case SymbolRole::Read:
3340b57cec5SDimitry Andric       case SymbolRole::Write:
3350b57cec5SDimitry Andric       case SymbolRole::Call:
3360b57cec5SDimitry Andric       case SymbolRole::Dynamic:
3370b57cec5SDimitry Andric       case SymbolRole::AddressOf:
3380b57cec5SDimitry Andric       case SymbolRole::Implicit:
3390b57cec5SDimitry Andric       case SymbolRole::Undefinition:
3400b57cec5SDimitry Andric       case SymbolRole::RelationReceivedBy:
3410b57cec5SDimitry Andric       case SymbolRole::RelationCalledBy:
3420b57cec5SDimitry Andric       case SymbolRole::RelationContainedBy:
3430b57cec5SDimitry Andric       case SymbolRole::RelationSpecializationOf:
3440b57cec5SDimitry Andric       case SymbolRole::NameReference:
3450b57cec5SDimitry Andric         return true;
3460b57cec5SDimitry Andric       }
3470b57cec5SDimitry Andric       llvm_unreachable("Unsupported SymbolRole value!");
3480b57cec5SDimitry Andric     });
3490b57cec5SDimitry Andric     return accept;
3500b57cec5SDimitry Andric   };
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric   for (auto &Rel : Relations) {
3530b57cec5SDimitry Andric     if (acceptForRelation(Rel.Roles))
3540b57cec5SDimitry Andric       return true;
3550b57cec5SDimitry Andric   }
3560b57cec5SDimitry Andric 
3570b57cec5SDimitry Andric   return false;
3580b57cec5SDimitry Andric }
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
3610b57cec5SDimitry Andric                                            bool IsRef, const Decl *Parent,
3620b57cec5SDimitry Andric                                            SymbolRoleSet Roles,
3630b57cec5SDimitry Andric                                            ArrayRef<SymbolRelation> Relations,
3640b57cec5SDimitry Andric                                            const Expr *OrigE,
3650b57cec5SDimitry Andric                                            const Decl *OrigD,
3660b57cec5SDimitry Andric                                            const DeclContext *ContainerDC) {
3670b57cec5SDimitry Andric   if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
3680b57cec5SDimitry Andric     return true;
3690b57cec5SDimitry Andric   if (!isa<NamedDecl>(D) || shouldSkipNamelessDecl(cast<NamedDecl>(D)))
3700b57cec5SDimitry Andric     return true;
3710b57cec5SDimitry Andric 
3720b57cec5SDimitry Andric   SourceManager &SM = Ctx->getSourceManager();
3730b57cec5SDimitry Andric   FileID FID = SM.getFileID(SM.getFileLoc(Loc));
3740b57cec5SDimitry Andric   if (FID.isInvalid())
3750b57cec5SDimitry Andric     return true;
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric   bool Invalid = false;
3780b57cec5SDimitry Andric   const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
3790b57cec5SDimitry Andric   if (Invalid || !SEntry.isFile())
3800b57cec5SDimitry Andric     return true;
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric   if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
3830b57cec5SDimitry Andric     switch (IndexOpts.SystemSymbolFilter) {
3840b57cec5SDimitry Andric     case IndexingOptions::SystemSymbolFilterKind::None:
3850b57cec5SDimitry Andric       return true;
3860b57cec5SDimitry Andric     case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
3870b57cec5SDimitry Andric       if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations))
3880b57cec5SDimitry Andric         return true;
3890b57cec5SDimitry Andric       break;
3900b57cec5SDimitry Andric     case IndexingOptions::SystemSymbolFilterKind::All:
3910b57cec5SDimitry Andric       break;
3920b57cec5SDimitry Andric     }
3930b57cec5SDimitry Andric   }
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric   if (!OrigD)
3960b57cec5SDimitry Andric     OrigD = D;
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric   if (isTemplateImplicitInstantiation(D)) {
3990b57cec5SDimitry Andric     if (!IsRef)
4000b57cec5SDimitry Andric       return true;
4010b57cec5SDimitry Andric     D = adjustTemplateImplicitInstantiation(D);
4020b57cec5SDimitry Andric     if (!D)
4030b57cec5SDimitry Andric       return true;
4040b57cec5SDimitry Andric     assert(!isTemplateImplicitInstantiation(D));
4050b57cec5SDimitry Andric   }
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric   if (IsRef)
4080b57cec5SDimitry Andric     Roles |= (unsigned)SymbolRole::Reference;
4090b57cec5SDimitry Andric   else if (isDeclADefinition(OrigD, ContainerDC, *Ctx))
4100b57cec5SDimitry Andric     Roles |= (unsigned)SymbolRole::Definition;
4110b57cec5SDimitry Andric   else
4120b57cec5SDimitry Andric     Roles |= (unsigned)SymbolRole::Declaration;
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric   D = getCanonicalDecl(D);
4150b57cec5SDimitry Andric   Parent = adjustParent(Parent);
4160b57cec5SDimitry Andric   if (Parent)
4170b57cec5SDimitry Andric     Parent = getCanonicalDecl(Parent);
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric   SmallVector<SymbolRelation, 6> FinalRelations;
4200b57cec5SDimitry Andric   FinalRelations.reserve(Relations.size()+1);
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric   auto addRelation = [&](SymbolRelation Rel) {
4230b57cec5SDimitry Andric     auto It = llvm::find_if(FinalRelations, [&](SymbolRelation Elem) -> bool {
4240b57cec5SDimitry Andric       return Elem.RelatedSymbol == Rel.RelatedSymbol;
4250b57cec5SDimitry Andric     });
4260b57cec5SDimitry Andric     if (It != FinalRelations.end()) {
4270b57cec5SDimitry Andric       It->Roles |= Rel.Roles;
4280b57cec5SDimitry Andric     } else {
4290b57cec5SDimitry Andric       FinalRelations.push_back(Rel);
4300b57cec5SDimitry Andric     }
4310b57cec5SDimitry Andric     Roles |= Rel.Roles;
4320b57cec5SDimitry Andric   };
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric   if (Parent) {
4350b57cec5SDimitry Andric     if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) {
4360b57cec5SDimitry Andric       addRelation(SymbolRelation{
4370b57cec5SDimitry Andric         (unsigned)SymbolRole::RelationContainedBy,
4380b57cec5SDimitry Andric         Parent
4390b57cec5SDimitry Andric       });
4400b57cec5SDimitry Andric     } else {
4410b57cec5SDimitry Andric       addRelation(SymbolRelation{
4420b57cec5SDimitry Andric         (unsigned)SymbolRole::RelationChildOf,
4430b57cec5SDimitry Andric         Parent
4440b57cec5SDimitry Andric       });
4450b57cec5SDimitry Andric     }
4460b57cec5SDimitry Andric   }
4470b57cec5SDimitry Andric 
4480b57cec5SDimitry Andric   for (auto &Rel : Relations) {
4490b57cec5SDimitry Andric     addRelation(SymbolRelation(Rel.Roles,
4500b57cec5SDimitry Andric                                Rel.RelatedSymbol->getCanonicalDecl()));
4510b57cec5SDimitry Andric   }
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric   IndexDataConsumer::ASTNodeInfo Node{OrigE, OrigD, Parent, ContainerDC};
454480093f4SDimitry Andric   return DataConsumer.handleDeclOccurrence(D, Roles, FinalRelations, Loc, Node);
4550b57cec5SDimitry Andric }
4560b57cec5SDimitry Andric 
4570b57cec5SDimitry Andric void IndexingContext::handleMacroDefined(const IdentifierInfo &Name,
4580b57cec5SDimitry Andric                                          SourceLocation Loc,
4590b57cec5SDimitry Andric                                          const MacroInfo &MI) {
460*fe6060f1SDimitry Andric   if (!shouldIndexMacroOccurrence(/*IsRef=*/false, Loc))
461*fe6060f1SDimitry Andric     return;
4620b57cec5SDimitry Andric   SymbolRoleSet Roles = (unsigned)SymbolRole::Definition;
463480093f4SDimitry Andric   DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
4640b57cec5SDimitry Andric }
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric void IndexingContext::handleMacroUndefined(const IdentifierInfo &Name,
4670b57cec5SDimitry Andric                                            SourceLocation Loc,
4680b57cec5SDimitry Andric                                            const MacroInfo &MI) {
469*fe6060f1SDimitry Andric   if (!shouldIndexMacroOccurrence(/*IsRef=*/false, Loc))
470*fe6060f1SDimitry Andric     return;
4710b57cec5SDimitry Andric   SymbolRoleSet Roles = (unsigned)SymbolRole::Undefinition;
472480093f4SDimitry Andric   DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
4730b57cec5SDimitry Andric }
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric void IndexingContext::handleMacroReference(const IdentifierInfo &Name,
4760b57cec5SDimitry Andric                                            SourceLocation Loc,
4770b57cec5SDimitry Andric                                            const MacroInfo &MI) {
478*fe6060f1SDimitry Andric   if (!shouldIndexMacroOccurrence(/*IsRef=*/true, Loc))
479*fe6060f1SDimitry Andric     return;
4800b57cec5SDimitry Andric   SymbolRoleSet Roles = (unsigned)SymbolRole::Reference;
481480093f4SDimitry Andric   DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
4820b57cec5SDimitry Andric }
483*fe6060f1SDimitry Andric 
484*fe6060f1SDimitry Andric bool IndexingContext::shouldIndexMacroOccurrence(bool IsRef,
485*fe6060f1SDimitry Andric                                                  SourceLocation Loc) {
486*fe6060f1SDimitry Andric   if (!IndexOpts.IndexMacros)
487*fe6060f1SDimitry Andric     return false;
488*fe6060f1SDimitry Andric 
489*fe6060f1SDimitry Andric   switch (IndexOpts.SystemSymbolFilter) {
490*fe6060f1SDimitry Andric   case IndexingOptions::SystemSymbolFilterKind::None:
491*fe6060f1SDimitry Andric     break;
492*fe6060f1SDimitry Andric   case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
493*fe6060f1SDimitry Andric     if (!IsRef)
494*fe6060f1SDimitry Andric       return true;
495*fe6060f1SDimitry Andric     break;
496*fe6060f1SDimitry Andric   case IndexingOptions::SystemSymbolFilterKind::All:
497*fe6060f1SDimitry Andric     return true;
498*fe6060f1SDimitry Andric   }
499*fe6060f1SDimitry Andric 
500*fe6060f1SDimitry Andric   SourceManager &SM = Ctx->getSourceManager();
501*fe6060f1SDimitry Andric   FileID FID = SM.getFileID(SM.getFileLoc(Loc));
502*fe6060f1SDimitry Andric   if (FID.isInvalid())
503*fe6060f1SDimitry Andric     return false;
504*fe6060f1SDimitry Andric 
505*fe6060f1SDimitry Andric   bool Invalid = false;
506*fe6060f1SDimitry Andric   const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
507*fe6060f1SDimitry Andric   if (Invalid || !SEntry.isFile())
508*fe6060f1SDimitry Andric     return false;
509*fe6060f1SDimitry Andric 
510*fe6060f1SDimitry Andric   return SEntry.getFile().getFileCharacteristic() == SrcMgr::C_User;
511*fe6060f1SDimitry Andric }
512