xref: /llvm-project/clang/lib/Index/IndexingContext.cpp (revision 5ddc371890324ba8aa5c54b42faeb0ed8a552fdb)
1f4fb85b1SArgyrios Kyrtzidis //===- IndexingContext.cpp - Indexing context data ------------------------===//
2f4fb85b1SArgyrios Kyrtzidis //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f4fb85b1SArgyrios Kyrtzidis //
7f4fb85b1SArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
8f4fb85b1SArgyrios Kyrtzidis 
9f4fb85b1SArgyrios Kyrtzidis #include "IndexingContext.h"
10f4fb85b1SArgyrios Kyrtzidis #include "clang/AST/ASTContext.h"
1160573ae6SReid Kleckner #include "clang/AST/Attr.h"
12f4fb85b1SArgyrios Kyrtzidis #include "clang/AST/DeclObjC.h"
1360573ae6SReid Kleckner #include "clang/AST/DeclTemplate.h"
1460573ae6SReid Kleckner #include "clang/Basic/SourceLocation.h"
15f4fb85b1SArgyrios Kyrtzidis #include "clang/Basic/SourceManager.h"
1660573ae6SReid Kleckner #include "clang/Index/IndexDataConsumer.h"
17f4fb85b1SArgyrios Kyrtzidis 
18f4fb85b1SArgyrios Kyrtzidis using namespace clang;
19f4fb85b1SArgyrios Kyrtzidis using namespace index;
20f4fb85b1SArgyrios Kyrtzidis 
isGeneratedDecl(const Decl * D)216e5ca5beSArgyrios Kyrtzidis static bool isGeneratedDecl(const Decl *D) {
226e5ca5beSArgyrios Kyrtzidis   if (auto *attr = D->getAttr<ExternalSourceSymbolAttr>()) {
236e5ca5beSArgyrios Kyrtzidis     return attr->getGeneratedDeclaration();
246e5ca5beSArgyrios Kyrtzidis   }
256e5ca5beSArgyrios Kyrtzidis   return false;
266e5ca5beSArgyrios Kyrtzidis }
276e5ca5beSArgyrios Kyrtzidis 
shouldIndex(const Decl * D)286e5ca5beSArgyrios Kyrtzidis bool IndexingContext::shouldIndex(const Decl *D) {
296e5ca5beSArgyrios Kyrtzidis   return !isGeneratedDecl(D);
306e5ca5beSArgyrios Kyrtzidis }
316e5ca5beSArgyrios Kyrtzidis 
getLangOpts() const32a352ba0cSAlex Lorenz const LangOptions &IndexingContext::getLangOpts() const {
33a352ba0cSAlex Lorenz   return Ctx->getLangOpts();
34a352ba0cSAlex Lorenz }
35a352ba0cSAlex Lorenz 
shouldIndexFunctionLocalSymbols() const36f4fb85b1SArgyrios Kyrtzidis bool IndexingContext::shouldIndexFunctionLocalSymbols() const {
37f4fb85b1SArgyrios Kyrtzidis   return IndexOpts.IndexFunctionLocals;
38f4fb85b1SArgyrios Kyrtzidis }
39f4fb85b1SArgyrios Kyrtzidis 
shouldIndexImplicitInstantiation() const40d50f36edSFangrui Song bool IndexingContext::shouldIndexImplicitInstantiation() const {
41d50f36edSFangrui Song   return IndexOpts.IndexImplicitInstantiation;
42d50f36edSFangrui Song }
43d50f36edSFangrui Song 
shouldIndexParametersInDeclarations() const440468fc0bSKadir Cetinkaya bool IndexingContext::shouldIndexParametersInDeclarations() const {
450468fc0bSKadir Cetinkaya   return IndexOpts.IndexParametersInDeclarations;
460468fc0bSKadir Cetinkaya }
470468fc0bSKadir Cetinkaya 
shouldIndexTemplateParameters() const48b780517cSKadir Cetinkaya bool IndexingContext::shouldIndexTemplateParameters() const {
49b780517cSKadir Cetinkaya   return IndexOpts.IndexTemplateParameters;
50b780517cSKadir Cetinkaya }
51b780517cSKadir Cetinkaya 
handleDecl(const Decl * D,SymbolRoleSet Roles,ArrayRef<SymbolRelation> Relations)52f4fb85b1SArgyrios Kyrtzidis bool IndexingContext::handleDecl(const Decl *D,
53f4fb85b1SArgyrios Kyrtzidis                                  SymbolRoleSet Roles,
54f4fb85b1SArgyrios Kyrtzidis                                  ArrayRef<SymbolRelation> Relations) {
5574790484SArgyrios Kyrtzidis   return handleDecl(D, D->getLocation(), Roles, Relations);
56f4fb85b1SArgyrios Kyrtzidis }
57f4fb85b1SArgyrios Kyrtzidis 
handleDecl(const Decl * D,SourceLocation Loc,SymbolRoleSet Roles,ArrayRef<SymbolRelation> Relations,const DeclContext * DC)58f4fb85b1SArgyrios Kyrtzidis bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc,
59f4fb85b1SArgyrios Kyrtzidis                                  SymbolRoleSet Roles,
60f4fb85b1SArgyrios Kyrtzidis                                  ArrayRef<SymbolRelation> Relations,
61f4fb85b1SArgyrios Kyrtzidis                                  const DeclContext *DC) {
62f4fb85b1SArgyrios Kyrtzidis   if (!DC)
63f4fb85b1SArgyrios Kyrtzidis     DC = D->getDeclContext();
6474790484SArgyrios Kyrtzidis 
6574790484SArgyrios Kyrtzidis   const Decl *OrigD = D;
6674790484SArgyrios Kyrtzidis   if (isa<ObjCPropertyImplDecl>(D)) {
6774790484SArgyrios Kyrtzidis     D = cast<ObjCPropertyImplDecl>(D)->getPropertyDecl();
6874790484SArgyrios Kyrtzidis   }
69f4fb85b1SArgyrios Kyrtzidis   return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC),
70f4fb85b1SArgyrios Kyrtzidis                               Roles, Relations,
7174790484SArgyrios Kyrtzidis                               nullptr, OrigD, DC);
72f4fb85b1SArgyrios Kyrtzidis }
73f4fb85b1SArgyrios Kyrtzidis 
handleReference(const NamedDecl * D,SourceLocation Loc,const NamedDecl * Parent,const DeclContext * DC,SymbolRoleSet Roles,ArrayRef<SymbolRelation> Relations,const Expr * RefE)74f4fb85b1SArgyrios Kyrtzidis bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
75f4fb85b1SArgyrios Kyrtzidis                                       const NamedDecl *Parent,
76f4fb85b1SArgyrios Kyrtzidis                                       const DeclContext *DC,
77f4fb85b1SArgyrios Kyrtzidis                                       SymbolRoleSet Roles,
78f4fb85b1SArgyrios Kyrtzidis                                       ArrayRef<SymbolRelation> Relations,
79*5ddc3718SNathan Ridge                                       const Expr *RefE) {
806d1a15b2SArgyrios Kyrtzidis   if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
81f4fb85b1SArgyrios Kyrtzidis     return true;
82f4fb85b1SArgyrios Kyrtzidis 
83b780517cSKadir Cetinkaya   if (!shouldIndexTemplateParameters() &&
84b780517cSKadir Cetinkaya       (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
85b780517cSKadir Cetinkaya        isa<TemplateTemplateParmDecl>(D))) {
86f4fb85b1SArgyrios Kyrtzidis     return true;
87b780517cSKadir Cetinkaya   }
88f4fb85b1SArgyrios Kyrtzidis   return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
89*5ddc3718SNathan Ridge                               RefE, nullptr, DC);
90f4fb85b1SArgyrios Kyrtzidis }
91f4fb85b1SArgyrios Kyrtzidis 
reportModuleReferences(const Module * Mod,ArrayRef<SourceLocation> IdLocs,const ImportDecl * ImportD,IndexDataConsumer & DataConsumer)9232e5d862SArgyrios Kyrtzidis static void reportModuleReferences(const Module *Mod,
9332e5d862SArgyrios Kyrtzidis                                    ArrayRef<SourceLocation> IdLocs,
9432e5d862SArgyrios Kyrtzidis                                    const ImportDecl *ImportD,
9532e5d862SArgyrios Kyrtzidis                                    IndexDataConsumer &DataConsumer) {
9632e5d862SArgyrios Kyrtzidis   if (!Mod)
9732e5d862SArgyrios Kyrtzidis     return;
9832e5d862SArgyrios Kyrtzidis   reportModuleReferences(Mod->Parent, IdLocs.drop_back(), ImportD,
9932e5d862SArgyrios Kyrtzidis                          DataConsumer);
1003b9715cbSKirill Bobyrev   DataConsumer.handleModuleOccurrence(
1013b9715cbSKirill Bobyrev       ImportD, Mod, (SymbolRoleSet)SymbolRole::Reference, IdLocs.back());
10232e5d862SArgyrios Kyrtzidis }
10332e5d862SArgyrios Kyrtzidis 
importedModule(const ImportDecl * ImportD)104f4fb85b1SArgyrios Kyrtzidis bool IndexingContext::importedModule(const ImportDecl *ImportD) {
10532e5d862SArgyrios Kyrtzidis   if (ImportD->isInvalidDecl())
10632e5d862SArgyrios Kyrtzidis     return true;
10732e5d862SArgyrios Kyrtzidis 
108113387e0SArgyrios Kyrtzidis   SourceLocation Loc;
109113387e0SArgyrios Kyrtzidis   auto IdLocs = ImportD->getIdentifierLocs();
110113387e0SArgyrios Kyrtzidis   if (!IdLocs.empty())
11132e5d862SArgyrios Kyrtzidis     Loc = IdLocs.back();
112113387e0SArgyrios Kyrtzidis   else
113113387e0SArgyrios Kyrtzidis     Loc = ImportD->getLocation();
114f4fb85b1SArgyrios Kyrtzidis 
115cc026ebfSSam McCall   SourceManager &SM = Ctx->getSourceManager();
116cc026ebfSSam McCall   FileID FID = SM.getFileID(SM.getFileLoc(Loc));
117f4fb85b1SArgyrios Kyrtzidis   if (FID.isInvalid())
118f4fb85b1SArgyrios Kyrtzidis     return true;
119f4fb85b1SArgyrios Kyrtzidis 
120f4fb85b1SArgyrios Kyrtzidis   bool Invalid = false;
121f4fb85b1SArgyrios Kyrtzidis   const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
122f4fb85b1SArgyrios Kyrtzidis   if (Invalid || !SEntry.isFile())
123f4fb85b1SArgyrios Kyrtzidis     return true;
124f4fb85b1SArgyrios Kyrtzidis 
125f4fb85b1SArgyrios Kyrtzidis   if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
126f4fb85b1SArgyrios Kyrtzidis     switch (IndexOpts.SystemSymbolFilter) {
127f4fb85b1SArgyrios Kyrtzidis     case IndexingOptions::SystemSymbolFilterKind::None:
128f4fb85b1SArgyrios Kyrtzidis       return true;
1296aed6b4fSBen Langmuir     case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
130f4fb85b1SArgyrios Kyrtzidis     case IndexingOptions::SystemSymbolFilterKind::All:
131f4fb85b1SArgyrios Kyrtzidis       break;
132f4fb85b1SArgyrios Kyrtzidis     }
133f4fb85b1SArgyrios Kyrtzidis   }
134f4fb85b1SArgyrios Kyrtzidis 
13532e5d862SArgyrios Kyrtzidis   const Module *Mod = ImportD->getImportedModule();
13632e5d862SArgyrios Kyrtzidis   if (!ImportD->isImplicit() && Mod->Parent && !IdLocs.empty()) {
13732e5d862SArgyrios Kyrtzidis     reportModuleReferences(Mod->Parent, IdLocs.drop_back(), ImportD,
13832e5d862SArgyrios Kyrtzidis                            DataConsumer);
13932e5d862SArgyrios Kyrtzidis   }
14032e5d862SArgyrios Kyrtzidis 
1416aed6b4fSBen Langmuir   SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration;
142f4fb85b1SArgyrios Kyrtzidis   if (ImportD->isImplicit())
143f4fb85b1SArgyrios Kyrtzidis     Roles |= (unsigned)SymbolRole::Implicit;
144f4fb85b1SArgyrios Kyrtzidis 
1453b9715cbSKirill Bobyrev   return DataConsumer.handleModuleOccurrence(ImportD, Mod, Roles, Loc);
146f4fb85b1SArgyrios Kyrtzidis }
147f4fb85b1SArgyrios Kyrtzidis 
isTemplateImplicitInstantiation(const Decl * D)148f4fb85b1SArgyrios Kyrtzidis bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
149f4fb85b1SArgyrios Kyrtzidis   TemplateSpecializationKind TKind = TSK_Undeclared;
150f4fb85b1SArgyrios Kyrtzidis   if (const ClassTemplateSpecializationDecl *
151f4fb85b1SArgyrios Kyrtzidis       SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
152f4fb85b1SArgyrios Kyrtzidis     TKind = SD->getSpecializationKind();
1539d8ab72aSArgyrios Kyrtzidis   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
154f4fb85b1SArgyrios Kyrtzidis     TKind = FD->getTemplateSpecializationKind();
1559d8ab72aSArgyrios Kyrtzidis   } else if (auto *VD = dyn_cast<VarDecl>(D)) {
1569d8ab72aSArgyrios Kyrtzidis     TKind = VD->getTemplateSpecializationKind();
1572109d436SAlex Lorenz   } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
1582109d436SAlex Lorenz     if (RD->getInstantiatedFromMemberClass())
1592109d436SAlex Lorenz       TKind = RD->getTemplateSpecializationKind();
1609d605206SAlex Lorenz   } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
1619d605206SAlex Lorenz     if (ED->getInstantiatedFromMemberEnum())
1629d605206SAlex Lorenz       TKind = ED->getTemplateSpecializationKind();
1634bbce515SAlex Lorenz   } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D) ||
1644bbce515SAlex Lorenz              isa<EnumConstantDecl>(D)) {
16573e27a60SAlex Lorenz     if (const auto *Parent = dyn_cast<Decl>(D->getDeclContext()))
16673e27a60SAlex Lorenz       return isTemplateImplicitInstantiation(Parent);
167f4fb85b1SArgyrios Kyrtzidis   }
168f4fb85b1SArgyrios Kyrtzidis   switch (TKind) {
169f4fb85b1SArgyrios Kyrtzidis     case TSK_Undeclared:
170bb9e92baSHaojian Wu       // Instantiation maybe not happen yet when we see a SpecializationDecl,
171bb9e92baSHaojian Wu       // e.g. when the type doesn't need to be complete, we still treat it as an
172bb9e92baSHaojian Wu       // instantiation as we'd like to keep the canonicalized result consistent.
173bb9e92baSHaojian Wu       return isa<ClassTemplateSpecializationDecl>(D);
174f4fb85b1SArgyrios Kyrtzidis     case TSK_ExplicitSpecialization:
175f4fb85b1SArgyrios Kyrtzidis       return false;
176f4fb85b1SArgyrios Kyrtzidis     case TSK_ImplicitInstantiation:
177f4fb85b1SArgyrios Kyrtzidis     case TSK_ExplicitInstantiationDeclaration:
178f4fb85b1SArgyrios Kyrtzidis     case TSK_ExplicitInstantiationDefinition:
179f4fb85b1SArgyrios Kyrtzidis       return true;
180f4fb85b1SArgyrios Kyrtzidis   }
1819b0ac334SSaleem Abdulrasool   llvm_unreachable("invalid TemplateSpecializationKind");
182f4fb85b1SArgyrios Kyrtzidis }
183f4fb85b1SArgyrios Kyrtzidis 
shouldIgnoreIfImplicit(const Decl * D)184f4fb85b1SArgyrios Kyrtzidis bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
185f4fb85b1SArgyrios Kyrtzidis   if (isa<ObjCInterfaceDecl>(D))
186f4fb85b1SArgyrios Kyrtzidis     return false;
187f4fb85b1SArgyrios Kyrtzidis   if (isa<ObjCCategoryDecl>(D))
188f4fb85b1SArgyrios Kyrtzidis     return false;
189f4fb85b1SArgyrios Kyrtzidis   if (isa<ObjCIvarDecl>(D))
190f4fb85b1SArgyrios Kyrtzidis     return false;
191f4fb85b1SArgyrios Kyrtzidis   if (isa<ObjCMethodDecl>(D))
192f4fb85b1SArgyrios Kyrtzidis     return false;
193f4fb85b1SArgyrios Kyrtzidis   if (isa<ImportDecl>(D))
194f4fb85b1SArgyrios Kyrtzidis     return false;
195f4fb85b1SArgyrios Kyrtzidis   return true;
196f4fb85b1SArgyrios Kyrtzidis }
197f4fb85b1SArgyrios Kyrtzidis 
19873e27a60SAlex Lorenz static const CXXRecordDecl *
getDeclContextForTemplateInstationPattern(const Decl * D)19973e27a60SAlex Lorenz getDeclContextForTemplateInstationPattern(const Decl *D) {
20073e27a60SAlex Lorenz   if (const auto *CTSD =
20173e27a60SAlex Lorenz           dyn_cast<ClassTemplateSpecializationDecl>(D->getDeclContext()))
20273e27a60SAlex Lorenz     return CTSD->getTemplateInstantiationPattern();
20373e27a60SAlex Lorenz   else if (const auto *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext()))
20473e27a60SAlex Lorenz     return RD->getInstantiatedFromMemberClass();
20573e27a60SAlex Lorenz   return nullptr;
20673e27a60SAlex Lorenz }
20773e27a60SAlex Lorenz 
adjustTemplateImplicitInstantiation(const Decl * D)208f4fb85b1SArgyrios Kyrtzidis static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
209f4fb85b1SArgyrios Kyrtzidis   if (const ClassTemplateSpecializationDecl *
210f4fb85b1SArgyrios Kyrtzidis       SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
211bb9e92baSHaojian Wu     const auto *Template = SD->getTemplateInstantiationPattern();
212bb9e92baSHaojian Wu     if (Template)
213bb9e92baSHaojian Wu       return Template;
214bb9e92baSHaojian Wu     // Fallback to primary template if no instantiation is available yet (e.g.
215bb9e92baSHaojian Wu     // the type doesn't need to be complete).
216bb9e92baSHaojian Wu     return SD->getSpecializedTemplate()->getTemplatedDecl();
2179d8ab72aSArgyrios Kyrtzidis   } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
218f4fb85b1SArgyrios Kyrtzidis     return FD->getTemplateInstantiationPattern();
2199d8ab72aSArgyrios Kyrtzidis   } else if (auto *VD = dyn_cast<VarDecl>(D)) {
2209d8ab72aSArgyrios Kyrtzidis     return VD->getTemplateInstantiationPattern();
2212109d436SAlex Lorenz   } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
2222109d436SAlex Lorenz     return RD->getInstantiatedFromMemberClass();
2239d605206SAlex Lorenz   } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
2249d605206SAlex Lorenz     return ED->getInstantiatedFromMemberEnum();
225fcbae3a3SAlex Lorenz   } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) {
226fcbae3a3SAlex Lorenz     const auto *ND = cast<NamedDecl>(D);
22773e27a60SAlex Lorenz     if (const CXXRecordDecl *Pattern =
228fcbae3a3SAlex Lorenz             getDeclContextForTemplateInstationPattern(ND)) {
229fcbae3a3SAlex Lorenz       for (const NamedDecl *BaseND : Pattern->lookup(ND->getDeclName())) {
230fcbae3a3SAlex Lorenz         if (BaseND->isImplicit())
231048c8a9eSAlex Lorenz           continue;
232fcbae3a3SAlex Lorenz         if (BaseND->getKind() == ND->getKind())
233fcbae3a3SAlex Lorenz           return BaseND;
234048c8a9eSAlex Lorenz       }
235048c8a9eSAlex Lorenz     }
2364bbce515SAlex Lorenz   } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
2374bbce515SAlex Lorenz     if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) {
2384bbce515SAlex Lorenz       if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) {
2394bbce515SAlex Lorenz         for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName()))
2404bbce515SAlex Lorenz           return BaseECD;
2414bbce515SAlex Lorenz       }
2424bbce515SAlex Lorenz     }
243f4fb85b1SArgyrios Kyrtzidis   }
244f4fb85b1SArgyrios Kyrtzidis   return nullptr;
245f4fb85b1SArgyrios Kyrtzidis }
246f4fb85b1SArgyrios Kyrtzidis 
isDeclADefinition(const Decl * D,const DeclContext * ContainerDC,ASTContext & Ctx)24766c49f78SArgyrios Kyrtzidis static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) {
248f4fb85b1SArgyrios Kyrtzidis   if (auto VD = dyn_cast<VarDecl>(D))
249f4fb85b1SArgyrios Kyrtzidis     return VD->isThisDeclarationADefinition(Ctx);
250f4fb85b1SArgyrios Kyrtzidis 
251f4fb85b1SArgyrios Kyrtzidis   if (auto FD = dyn_cast<FunctionDecl>(D))
252f4fb85b1SArgyrios Kyrtzidis     return FD->isThisDeclarationADefinition();
253f4fb85b1SArgyrios Kyrtzidis 
254f4fb85b1SArgyrios Kyrtzidis   if (auto TD = dyn_cast<TagDecl>(D))
255f4fb85b1SArgyrios Kyrtzidis     return TD->isThisDeclarationADefinition();
256f4fb85b1SArgyrios Kyrtzidis 
257f4fb85b1SArgyrios Kyrtzidis   if (auto MD = dyn_cast<ObjCMethodDecl>(D))
25866c49f78SArgyrios Kyrtzidis     return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC);
259f4fb85b1SArgyrios Kyrtzidis 
26075e16fd2SIlya Biryukov   if (isa<TypedefNameDecl>(D) || isa<EnumConstantDecl>(D) ||
26175e16fd2SIlya Biryukov       isa<FieldDecl>(D) || isa<MSPropertyDecl>(D) || isa<ObjCImplDecl>(D) ||
26275e16fd2SIlya Biryukov       isa<ObjCPropertyImplDecl>(D) || isa<ConceptDecl>(D))
263f4fb85b1SArgyrios Kyrtzidis     return true;
264f4fb85b1SArgyrios Kyrtzidis 
265f4fb85b1SArgyrios Kyrtzidis   return false;
266f4fb85b1SArgyrios Kyrtzidis }
267f4fb85b1SArgyrios Kyrtzidis 
268da467ed4SBen Langmuir /// Whether the given NamedDecl should be skipped because it has no name.
shouldSkipNamelessDecl(const NamedDecl * ND)269da467ed4SBen Langmuir static bool shouldSkipNamelessDecl(const NamedDecl *ND) {
27047827627SArgyrios Kyrtzidis   return (ND->getDeclName().isEmpty() && !isa<TagDecl>(ND) &&
27147827627SArgyrios Kyrtzidis           !isa<ObjCCategoryDecl>(ND)) || isa<CXXDeductionGuideDecl>(ND);
272da467ed4SBen Langmuir }
273da467ed4SBen Langmuir 
adjustParent(const Decl * Parent)274f4fb85b1SArgyrios Kyrtzidis static const Decl *adjustParent(const Decl *Parent) {
275f4fb85b1SArgyrios Kyrtzidis   if (!Parent)
276f4fb85b1SArgyrios Kyrtzidis     return nullptr;
277f4fb85b1SArgyrios Kyrtzidis   for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
278f4fb85b1SArgyrios Kyrtzidis     if (isa<TranslationUnitDecl>(Parent))
279f4fb85b1SArgyrios Kyrtzidis       return nullptr;
280f4fb85b1SArgyrios Kyrtzidis     if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
281f4fb85b1SArgyrios Kyrtzidis       continue;
282f4fb85b1SArgyrios Kyrtzidis     if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
283f4fb85b1SArgyrios Kyrtzidis       if (NS->isAnonymousNamespace())
284f4fb85b1SArgyrios Kyrtzidis         continue;
285f4fb85b1SArgyrios Kyrtzidis     } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
286f4fb85b1SArgyrios Kyrtzidis       if (RD->isAnonymousStructOrUnion())
287f4fb85b1SArgyrios Kyrtzidis         continue;
288da467ed4SBen Langmuir     } else if (auto ND = dyn_cast<NamedDecl>(Parent)) {
289da467ed4SBen Langmuir       if (shouldSkipNamelessDecl(ND))
290f4fb85b1SArgyrios Kyrtzidis         continue;
291f4fb85b1SArgyrios Kyrtzidis     }
292f4fb85b1SArgyrios Kyrtzidis     return Parent;
293f4fb85b1SArgyrios Kyrtzidis   }
294f4fb85b1SArgyrios Kyrtzidis }
295f4fb85b1SArgyrios Kyrtzidis 
getCanonicalDecl(const Decl * D)296f4fb85b1SArgyrios Kyrtzidis static const Decl *getCanonicalDecl(const Decl *D) {
297f4fb85b1SArgyrios Kyrtzidis   D = D->getCanonicalDecl();
298f4fb85b1SArgyrios Kyrtzidis   if (auto TD = dyn_cast<TemplateDecl>(D)) {
299e62dd8b5SKrasimir Georgiev     if (auto TTD = TD->getTemplatedDecl()) {
300e62dd8b5SKrasimir Georgiev       D = TTD;
301f4fb85b1SArgyrios Kyrtzidis       assert(D->isCanonicalDecl());
302f4fb85b1SArgyrios Kyrtzidis     }
303e62dd8b5SKrasimir Georgiev   }
304f4fb85b1SArgyrios Kyrtzidis 
305f4fb85b1SArgyrios Kyrtzidis   return D;
306f4fb85b1SArgyrios Kyrtzidis }
307f4fb85b1SArgyrios Kyrtzidis 
shouldReportOccurrenceForSystemDeclOnlyMode(bool IsRef,SymbolRoleSet Roles,ArrayRef<SymbolRelation> Relations)308a9876cafSArgyrios Kyrtzidis static bool shouldReportOccurrenceForSystemDeclOnlyMode(
309a9876cafSArgyrios Kyrtzidis     bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) {
310a9876cafSArgyrios Kyrtzidis   if (!IsRef)
311a9876cafSArgyrios Kyrtzidis     return true;
312a9876cafSArgyrios Kyrtzidis 
313a9876cafSArgyrios Kyrtzidis   auto acceptForRelation = [](SymbolRoleSet roles) -> bool {
314a9876cafSArgyrios Kyrtzidis     bool accept = false;
315a9876cafSArgyrios Kyrtzidis     applyForEachSymbolRoleInterruptible(roles, [&accept](SymbolRole r) -> bool {
316a9876cafSArgyrios Kyrtzidis       switch (r) {
317a9876cafSArgyrios Kyrtzidis       case SymbolRole::RelationChildOf:
318a9876cafSArgyrios Kyrtzidis       case SymbolRole::RelationBaseOf:
319a9876cafSArgyrios Kyrtzidis       case SymbolRole::RelationOverrideOf:
320a9876cafSArgyrios Kyrtzidis       case SymbolRole::RelationExtendedBy:
321a9876cafSArgyrios Kyrtzidis       case SymbolRole::RelationAccessorOf:
322a9876cafSArgyrios Kyrtzidis       case SymbolRole::RelationIBTypeOf:
323a9876cafSArgyrios Kyrtzidis         accept = true;
324a9876cafSArgyrios Kyrtzidis         return false;
325a9876cafSArgyrios Kyrtzidis       case SymbolRole::Declaration:
326a9876cafSArgyrios Kyrtzidis       case SymbolRole::Definition:
327a9876cafSArgyrios Kyrtzidis       case SymbolRole::Reference:
328a9876cafSArgyrios Kyrtzidis       case SymbolRole::Read:
329a9876cafSArgyrios Kyrtzidis       case SymbolRole::Write:
330a9876cafSArgyrios Kyrtzidis       case SymbolRole::Call:
331a9876cafSArgyrios Kyrtzidis       case SymbolRole::Dynamic:
332a9876cafSArgyrios Kyrtzidis       case SymbolRole::AddressOf:
333a9876cafSArgyrios Kyrtzidis       case SymbolRole::Implicit:
3348c97195cSEric Liu       case SymbolRole::Undefinition:
335a9876cafSArgyrios Kyrtzidis       case SymbolRole::RelationReceivedBy:
336a9876cafSArgyrios Kyrtzidis       case SymbolRole::RelationCalledBy:
337a9876cafSArgyrios Kyrtzidis       case SymbolRole::RelationContainedBy:
338f6071c34SAlex Lorenz       case SymbolRole::RelationSpecializationOf:
339e7eb27a9SKadir Cetinkaya       case SymbolRole::NameReference:
340a9876cafSArgyrios Kyrtzidis         return true;
341a9876cafSArgyrios Kyrtzidis       }
342dfbf049eSSimon Pilgrim       llvm_unreachable("Unsupported SymbolRole value!");
343a9876cafSArgyrios Kyrtzidis     });
344a9876cafSArgyrios Kyrtzidis     return accept;
345a9876cafSArgyrios Kyrtzidis   };
346a9876cafSArgyrios Kyrtzidis 
347a9876cafSArgyrios Kyrtzidis   for (auto &Rel : Relations) {
348a9876cafSArgyrios Kyrtzidis     if (acceptForRelation(Rel.Roles))
349a9876cafSArgyrios Kyrtzidis       return true;
350a9876cafSArgyrios Kyrtzidis   }
351a9876cafSArgyrios Kyrtzidis 
352a9876cafSArgyrios Kyrtzidis   return false;
353a9876cafSArgyrios Kyrtzidis }
354a9876cafSArgyrios Kyrtzidis 
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)355f4fb85b1SArgyrios Kyrtzidis bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
356f4fb85b1SArgyrios Kyrtzidis                                            bool IsRef, const Decl *Parent,
357f4fb85b1SArgyrios Kyrtzidis                                            SymbolRoleSet Roles,
358f4fb85b1SArgyrios Kyrtzidis                                            ArrayRef<SymbolRelation> Relations,
359f4fb85b1SArgyrios Kyrtzidis                                            const Expr *OrigE,
360f4fb85b1SArgyrios Kyrtzidis                                            const Decl *OrigD,
361f4fb85b1SArgyrios Kyrtzidis                                            const DeclContext *ContainerDC) {
362f4fb85b1SArgyrios Kyrtzidis   if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
363f4fb85b1SArgyrios Kyrtzidis     return true;
364da467ed4SBen Langmuir   if (!isa<NamedDecl>(D) || shouldSkipNamelessDecl(cast<NamedDecl>(D)))
365f4fb85b1SArgyrios Kyrtzidis     return true;
366f4fb85b1SArgyrios Kyrtzidis 
367f4fb85b1SArgyrios Kyrtzidis   SourceManager &SM = Ctx->getSourceManager();
368cc026ebfSSam McCall   FileID FID = SM.getFileID(SM.getFileLoc(Loc));
369f4fb85b1SArgyrios Kyrtzidis   if (FID.isInvalid())
370f4fb85b1SArgyrios Kyrtzidis     return true;
371f4fb85b1SArgyrios Kyrtzidis 
372f4fb85b1SArgyrios Kyrtzidis   bool Invalid = false;
373f4fb85b1SArgyrios Kyrtzidis   const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
374f4fb85b1SArgyrios Kyrtzidis   if (Invalid || !SEntry.isFile())
375f4fb85b1SArgyrios Kyrtzidis     return true;
376f4fb85b1SArgyrios Kyrtzidis 
377f4fb85b1SArgyrios Kyrtzidis   if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
378f4fb85b1SArgyrios Kyrtzidis     switch (IndexOpts.SystemSymbolFilter) {
379f4fb85b1SArgyrios Kyrtzidis     case IndexingOptions::SystemSymbolFilterKind::None:
380f4fb85b1SArgyrios Kyrtzidis       return true;
381f4fb85b1SArgyrios Kyrtzidis     case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
382a9876cafSArgyrios Kyrtzidis       if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations))
383f4fb85b1SArgyrios Kyrtzidis         return true;
384f4fb85b1SArgyrios Kyrtzidis       break;
385f4fb85b1SArgyrios Kyrtzidis     case IndexingOptions::SystemSymbolFilterKind::All:
386f4fb85b1SArgyrios Kyrtzidis       break;
387f4fb85b1SArgyrios Kyrtzidis     }
388f4fb85b1SArgyrios Kyrtzidis   }
389f4fb85b1SArgyrios Kyrtzidis 
3903e0051bbSEric Liu   if (!OrigD)
3913e0051bbSEric Liu     OrigD = D;
3923e0051bbSEric Liu 
393f4fb85b1SArgyrios Kyrtzidis   if (isTemplateImplicitInstantiation(D)) {
394f4fb85b1SArgyrios Kyrtzidis     if (!IsRef)
395f4fb85b1SArgyrios Kyrtzidis       return true;
396f4fb85b1SArgyrios Kyrtzidis     D = adjustTemplateImplicitInstantiation(D);
397f4fb85b1SArgyrios Kyrtzidis     if (!D)
398f4fb85b1SArgyrios Kyrtzidis       return true;
399f4fb85b1SArgyrios Kyrtzidis     assert(!isTemplateImplicitInstantiation(D));
400f4fb85b1SArgyrios Kyrtzidis   }
401f4fb85b1SArgyrios Kyrtzidis 
402f4fb85b1SArgyrios Kyrtzidis   if (IsRef)
403f4fb85b1SArgyrios Kyrtzidis     Roles |= (unsigned)SymbolRole::Reference;
40474790484SArgyrios Kyrtzidis   else if (isDeclADefinition(OrigD, ContainerDC, *Ctx))
405f4fb85b1SArgyrios Kyrtzidis     Roles |= (unsigned)SymbolRole::Definition;
406f4fb85b1SArgyrios Kyrtzidis   else
407f4fb85b1SArgyrios Kyrtzidis     Roles |= (unsigned)SymbolRole::Declaration;
408f4fb85b1SArgyrios Kyrtzidis 
409f4fb85b1SArgyrios Kyrtzidis   D = getCanonicalDecl(D);
410f4fb85b1SArgyrios Kyrtzidis   Parent = adjustParent(Parent);
411f4fb85b1SArgyrios Kyrtzidis   if (Parent)
412f4fb85b1SArgyrios Kyrtzidis     Parent = getCanonicalDecl(Parent);
413f4fb85b1SArgyrios Kyrtzidis 
414f4fb85b1SArgyrios Kyrtzidis   SmallVector<SymbolRelation, 6> FinalRelations;
415f4fb85b1SArgyrios Kyrtzidis   FinalRelations.reserve(Relations.size()+1);
416f4fb85b1SArgyrios Kyrtzidis 
417f4fb85b1SArgyrios Kyrtzidis   auto addRelation = [&](SymbolRelation Rel) {
41875e74e07SFangrui Song     auto It = llvm::find_if(FinalRelations, [&](SymbolRelation Elem) -> bool {
419f4fb85b1SArgyrios Kyrtzidis       return Elem.RelatedSymbol == Rel.RelatedSymbol;
420f4fb85b1SArgyrios Kyrtzidis     });
421f4fb85b1SArgyrios Kyrtzidis     if (It != FinalRelations.end()) {
422f4fb85b1SArgyrios Kyrtzidis       It->Roles |= Rel.Roles;
423f4fb85b1SArgyrios Kyrtzidis     } else {
424f4fb85b1SArgyrios Kyrtzidis       FinalRelations.push_back(Rel);
425f4fb85b1SArgyrios Kyrtzidis     }
426f4fb85b1SArgyrios Kyrtzidis     Roles |= Rel.Roles;
427f4fb85b1SArgyrios Kyrtzidis   };
428f4fb85b1SArgyrios Kyrtzidis 
429df60aa83SArgyrios Kyrtzidis   if (Parent) {
4306d1a15b2SArgyrios Kyrtzidis     if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) {
431de0f5088SArgyrios Kyrtzidis       addRelation(SymbolRelation{
432de0f5088SArgyrios Kyrtzidis         (unsigned)SymbolRole::RelationContainedBy,
433de0f5088SArgyrios Kyrtzidis         Parent
434de0f5088SArgyrios Kyrtzidis       });
4356d1a15b2SArgyrios Kyrtzidis     } else {
436de0f5088SArgyrios Kyrtzidis       addRelation(SymbolRelation{
437de0f5088SArgyrios Kyrtzidis         (unsigned)SymbolRole::RelationChildOf,
438de0f5088SArgyrios Kyrtzidis         Parent
439de0f5088SArgyrios Kyrtzidis       });
440f4fb85b1SArgyrios Kyrtzidis     }
441df60aa83SArgyrios Kyrtzidis   }
442df60aa83SArgyrios Kyrtzidis 
443f4fb85b1SArgyrios Kyrtzidis   for (auto &Rel : Relations) {
444f4fb85b1SArgyrios Kyrtzidis     addRelation(SymbolRelation(Rel.Roles,
445f4fb85b1SArgyrios Kyrtzidis                                Rel.RelatedSymbol->getCanonicalDecl()));
446f4fb85b1SArgyrios Kyrtzidis   }
447f4fb85b1SArgyrios Kyrtzidis 
448f4fb85b1SArgyrios Kyrtzidis   IndexDataConsumer::ASTNodeInfo Node{OrigE, OrigD, Parent, ContainerDC};
4493b9715cbSKirill Bobyrev   return DataConsumer.handleDeclOccurrence(D, Roles, FinalRelations, Loc, Node);
450f4fb85b1SArgyrios Kyrtzidis }
4518c97195cSEric Liu 
handleMacroDefined(const IdentifierInfo & Name,SourceLocation Loc,const MacroInfo & MI)4528c97195cSEric Liu void IndexingContext::handleMacroDefined(const IdentifierInfo &Name,
4538c97195cSEric Liu                                          SourceLocation Loc,
4548c97195cSEric Liu                                          const MacroInfo &MI) {
45593c87fc0SBen Langmuir   if (!shouldIndexMacroOccurrence(/*IsRef=*/false, Loc))
45693c87fc0SBen Langmuir     return;
4578c97195cSEric Liu   SymbolRoleSet Roles = (unsigned)SymbolRole::Definition;
4583b9715cbSKirill Bobyrev   DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
4598c97195cSEric Liu }
4608c97195cSEric Liu 
handleMacroUndefined(const IdentifierInfo & Name,SourceLocation Loc,const MacroInfo & MI)4618c97195cSEric Liu void IndexingContext::handleMacroUndefined(const IdentifierInfo &Name,
4628c97195cSEric Liu                                            SourceLocation Loc,
4638c97195cSEric Liu                                            const MacroInfo &MI) {
46493c87fc0SBen Langmuir   if (!shouldIndexMacroOccurrence(/*IsRef=*/false, Loc))
46593c87fc0SBen Langmuir     return;
4668c97195cSEric Liu   SymbolRoleSet Roles = (unsigned)SymbolRole::Undefinition;
4673b9715cbSKirill Bobyrev   DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
4688c97195cSEric Liu }
4698c97195cSEric Liu 
handleMacroReference(const IdentifierInfo & Name,SourceLocation Loc,const MacroInfo & MI)4708c97195cSEric Liu void IndexingContext::handleMacroReference(const IdentifierInfo &Name,
4718c97195cSEric Liu                                            SourceLocation Loc,
4728c97195cSEric Liu                                            const MacroInfo &MI) {
47393c87fc0SBen Langmuir   if (!shouldIndexMacroOccurrence(/*IsRef=*/true, Loc))
47493c87fc0SBen Langmuir     return;
4758c97195cSEric Liu   SymbolRoleSet Roles = (unsigned)SymbolRole::Reference;
4763b9715cbSKirill Bobyrev   DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
4778c97195cSEric Liu }
47893c87fc0SBen Langmuir 
shouldIndexMacroOccurrence(bool IsRef,SourceLocation Loc)47993c87fc0SBen Langmuir bool IndexingContext::shouldIndexMacroOccurrence(bool IsRef,
48093c87fc0SBen Langmuir                                                  SourceLocation Loc) {
48193c87fc0SBen Langmuir   if (!IndexOpts.IndexMacros)
48293c87fc0SBen Langmuir     return false;
48393c87fc0SBen Langmuir 
48493c87fc0SBen Langmuir   switch (IndexOpts.SystemSymbolFilter) {
48593c87fc0SBen Langmuir   case IndexingOptions::SystemSymbolFilterKind::None:
48693c87fc0SBen Langmuir     break;
48793c87fc0SBen Langmuir   case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
48893c87fc0SBen Langmuir     if (!IsRef)
48993c87fc0SBen Langmuir       return true;
49093c87fc0SBen Langmuir     break;
49193c87fc0SBen Langmuir   case IndexingOptions::SystemSymbolFilterKind::All:
49293c87fc0SBen Langmuir     return true;
49393c87fc0SBen Langmuir   }
49493c87fc0SBen Langmuir 
49593c87fc0SBen Langmuir   SourceManager &SM = Ctx->getSourceManager();
49693c87fc0SBen Langmuir   FileID FID = SM.getFileID(SM.getFileLoc(Loc));
49793c87fc0SBen Langmuir   if (FID.isInvalid())
49893c87fc0SBen Langmuir     return false;
49993c87fc0SBen Langmuir 
50093c87fc0SBen Langmuir   bool Invalid = false;
50193c87fc0SBen Langmuir   const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
50293c87fc0SBen Langmuir   if (Invalid || !SEntry.isFile())
50393c87fc0SBen Langmuir     return false;
50493c87fc0SBen Langmuir 
50593c87fc0SBen Langmuir   return SEntry.getFile().getFileCharacteristic() == SrcMgr::C_User;
50693c87fc0SBen Langmuir }
507