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