1e5dd7070Spatrick //===- IndexingContext.cpp - Indexing context data ------------------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick
9e5dd7070Spatrick #include "IndexingContext.h"
10e5dd7070Spatrick #include "clang/AST/ASTContext.h"
11e5dd7070Spatrick #include "clang/AST/Attr.h"
12e5dd7070Spatrick #include "clang/AST/DeclObjC.h"
13e5dd7070Spatrick #include "clang/AST/DeclTemplate.h"
14e5dd7070Spatrick #include "clang/Basic/SourceLocation.h"
15e5dd7070Spatrick #include "clang/Basic/SourceManager.h"
16e5dd7070Spatrick #include "clang/Index/IndexDataConsumer.h"
17e5dd7070Spatrick
18e5dd7070Spatrick using namespace clang;
19e5dd7070Spatrick using namespace index;
20e5dd7070Spatrick
isGeneratedDecl(const Decl * D)21e5dd7070Spatrick static bool isGeneratedDecl(const Decl *D) {
22e5dd7070Spatrick if (auto *attr = D->getAttr<ExternalSourceSymbolAttr>()) {
23e5dd7070Spatrick return attr->getGeneratedDeclaration();
24e5dd7070Spatrick }
25e5dd7070Spatrick return false;
26e5dd7070Spatrick }
27e5dd7070Spatrick
shouldIndex(const Decl * D)28e5dd7070Spatrick bool IndexingContext::shouldIndex(const Decl *D) {
29e5dd7070Spatrick return !isGeneratedDecl(D);
30e5dd7070Spatrick }
31e5dd7070Spatrick
getLangOpts() const32e5dd7070Spatrick const LangOptions &IndexingContext::getLangOpts() const {
33e5dd7070Spatrick return Ctx->getLangOpts();
34e5dd7070Spatrick }
35e5dd7070Spatrick
shouldIndexFunctionLocalSymbols() const36e5dd7070Spatrick bool IndexingContext::shouldIndexFunctionLocalSymbols() const {
37e5dd7070Spatrick return IndexOpts.IndexFunctionLocals;
38e5dd7070Spatrick }
39e5dd7070Spatrick
shouldIndexImplicitInstantiation() const40e5dd7070Spatrick bool IndexingContext::shouldIndexImplicitInstantiation() const {
41e5dd7070Spatrick return IndexOpts.IndexImplicitInstantiation;
42e5dd7070Spatrick }
43e5dd7070Spatrick
shouldIndexParametersInDeclarations() const44e5dd7070Spatrick bool IndexingContext::shouldIndexParametersInDeclarations() const {
45e5dd7070Spatrick return IndexOpts.IndexParametersInDeclarations;
46e5dd7070Spatrick }
47e5dd7070Spatrick
shouldIndexTemplateParameters() const48e5dd7070Spatrick bool IndexingContext::shouldIndexTemplateParameters() const {
49e5dd7070Spatrick return IndexOpts.IndexTemplateParameters;
50e5dd7070Spatrick }
51e5dd7070Spatrick
handleDecl(const Decl * D,SymbolRoleSet Roles,ArrayRef<SymbolRelation> Relations)52e5dd7070Spatrick bool IndexingContext::handleDecl(const Decl *D,
53e5dd7070Spatrick SymbolRoleSet Roles,
54e5dd7070Spatrick ArrayRef<SymbolRelation> Relations) {
55e5dd7070Spatrick return handleDecl(D, D->getLocation(), Roles, Relations);
56e5dd7070Spatrick }
57e5dd7070Spatrick
handleDecl(const Decl * D,SourceLocation Loc,SymbolRoleSet Roles,ArrayRef<SymbolRelation> Relations,const DeclContext * DC)58e5dd7070Spatrick bool IndexingContext::handleDecl(const Decl *D, SourceLocation Loc,
59e5dd7070Spatrick SymbolRoleSet Roles,
60e5dd7070Spatrick ArrayRef<SymbolRelation> Relations,
61e5dd7070Spatrick const DeclContext *DC) {
62e5dd7070Spatrick if (!DC)
63e5dd7070Spatrick DC = D->getDeclContext();
64e5dd7070Spatrick
65e5dd7070Spatrick const Decl *OrigD = D;
66e5dd7070Spatrick if (isa<ObjCPropertyImplDecl>(D)) {
67e5dd7070Spatrick D = cast<ObjCPropertyImplDecl>(D)->getPropertyDecl();
68e5dd7070Spatrick }
69e5dd7070Spatrick return handleDeclOccurrence(D, Loc, /*IsRef=*/false, cast<Decl>(DC),
70e5dd7070Spatrick Roles, Relations,
71e5dd7070Spatrick nullptr, OrigD, DC);
72e5dd7070Spatrick }
73e5dd7070Spatrick
handleReference(const NamedDecl * D,SourceLocation Loc,const NamedDecl * Parent,const DeclContext * DC,SymbolRoleSet Roles,ArrayRef<SymbolRelation> Relations,const Expr * RefE,const Decl * RefD)74e5dd7070Spatrick bool IndexingContext::handleReference(const NamedDecl *D, SourceLocation Loc,
75e5dd7070Spatrick const NamedDecl *Parent,
76e5dd7070Spatrick const DeclContext *DC,
77e5dd7070Spatrick SymbolRoleSet Roles,
78e5dd7070Spatrick ArrayRef<SymbolRelation> Relations,
79e5dd7070Spatrick const Expr *RefE,
80e5dd7070Spatrick const Decl *RefD) {
81e5dd7070Spatrick if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
82e5dd7070Spatrick return true;
83e5dd7070Spatrick
84e5dd7070Spatrick if (!shouldIndexTemplateParameters() &&
85e5dd7070Spatrick (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
86e5dd7070Spatrick isa<TemplateTemplateParmDecl>(D))) {
87e5dd7070Spatrick return true;
88e5dd7070Spatrick }
89e5dd7070Spatrick return handleDeclOccurrence(D, Loc, /*IsRef=*/true, Parent, Roles, Relations,
90e5dd7070Spatrick RefE, RefD, DC);
91e5dd7070Spatrick }
92e5dd7070Spatrick
reportModuleReferences(const Module * Mod,ArrayRef<SourceLocation> IdLocs,const ImportDecl * ImportD,IndexDataConsumer & DataConsumer)93e5dd7070Spatrick static void reportModuleReferences(const Module *Mod,
94e5dd7070Spatrick ArrayRef<SourceLocation> IdLocs,
95e5dd7070Spatrick const ImportDecl *ImportD,
96e5dd7070Spatrick IndexDataConsumer &DataConsumer) {
97e5dd7070Spatrick if (!Mod)
98e5dd7070Spatrick return;
99e5dd7070Spatrick reportModuleReferences(Mod->Parent, IdLocs.drop_back(), ImportD,
100e5dd7070Spatrick DataConsumer);
101e5dd7070Spatrick DataConsumer.handleModuleOccurrence(
102e5dd7070Spatrick ImportD, Mod, (SymbolRoleSet)SymbolRole::Reference, IdLocs.back());
103e5dd7070Spatrick }
104e5dd7070Spatrick
importedModule(const ImportDecl * ImportD)105e5dd7070Spatrick bool IndexingContext::importedModule(const ImportDecl *ImportD) {
106e5dd7070Spatrick if (ImportD->isInvalidDecl())
107e5dd7070Spatrick return true;
108e5dd7070Spatrick
109e5dd7070Spatrick SourceLocation Loc;
110e5dd7070Spatrick auto IdLocs = ImportD->getIdentifierLocs();
111e5dd7070Spatrick if (!IdLocs.empty())
112e5dd7070Spatrick Loc = IdLocs.back();
113e5dd7070Spatrick else
114e5dd7070Spatrick Loc = ImportD->getLocation();
115e5dd7070Spatrick
116e5dd7070Spatrick SourceManager &SM = Ctx->getSourceManager();
117e5dd7070Spatrick FileID FID = SM.getFileID(SM.getFileLoc(Loc));
118e5dd7070Spatrick if (FID.isInvalid())
119e5dd7070Spatrick return true;
120e5dd7070Spatrick
121e5dd7070Spatrick bool Invalid = false;
122e5dd7070Spatrick const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
123e5dd7070Spatrick if (Invalid || !SEntry.isFile())
124e5dd7070Spatrick return true;
125e5dd7070Spatrick
126e5dd7070Spatrick if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
127e5dd7070Spatrick switch (IndexOpts.SystemSymbolFilter) {
128e5dd7070Spatrick case IndexingOptions::SystemSymbolFilterKind::None:
129e5dd7070Spatrick return true;
130e5dd7070Spatrick case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
131e5dd7070Spatrick case IndexingOptions::SystemSymbolFilterKind::All:
132e5dd7070Spatrick break;
133e5dd7070Spatrick }
134e5dd7070Spatrick }
135e5dd7070Spatrick
136e5dd7070Spatrick const Module *Mod = ImportD->getImportedModule();
137e5dd7070Spatrick if (!ImportD->isImplicit() && Mod->Parent && !IdLocs.empty()) {
138e5dd7070Spatrick reportModuleReferences(Mod->Parent, IdLocs.drop_back(), ImportD,
139e5dd7070Spatrick DataConsumer);
140e5dd7070Spatrick }
141e5dd7070Spatrick
142e5dd7070Spatrick SymbolRoleSet Roles = (unsigned)SymbolRole::Declaration;
143e5dd7070Spatrick if (ImportD->isImplicit())
144e5dd7070Spatrick Roles |= (unsigned)SymbolRole::Implicit;
145e5dd7070Spatrick
146e5dd7070Spatrick return DataConsumer.handleModuleOccurrence(ImportD, Mod, Roles, Loc);
147e5dd7070Spatrick }
148e5dd7070Spatrick
isTemplateImplicitInstantiation(const Decl * D)149e5dd7070Spatrick bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
150e5dd7070Spatrick TemplateSpecializationKind TKind = TSK_Undeclared;
151e5dd7070Spatrick if (const ClassTemplateSpecializationDecl *
152e5dd7070Spatrick SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
153e5dd7070Spatrick TKind = SD->getSpecializationKind();
154e5dd7070Spatrick } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
155e5dd7070Spatrick TKind = FD->getTemplateSpecializationKind();
156e5dd7070Spatrick } else if (auto *VD = dyn_cast<VarDecl>(D)) {
157e5dd7070Spatrick TKind = VD->getTemplateSpecializationKind();
158e5dd7070Spatrick } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
159e5dd7070Spatrick if (RD->getInstantiatedFromMemberClass())
160e5dd7070Spatrick TKind = RD->getTemplateSpecializationKind();
161e5dd7070Spatrick } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
162e5dd7070Spatrick if (ED->getInstantiatedFromMemberEnum())
163e5dd7070Spatrick TKind = ED->getTemplateSpecializationKind();
164e5dd7070Spatrick } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D) ||
165e5dd7070Spatrick isa<EnumConstantDecl>(D)) {
166e5dd7070Spatrick if (const auto *Parent = dyn_cast<Decl>(D->getDeclContext()))
167e5dd7070Spatrick return isTemplateImplicitInstantiation(Parent);
168e5dd7070Spatrick }
169e5dd7070Spatrick switch (TKind) {
170e5dd7070Spatrick case TSK_Undeclared:
171ec727ea7Spatrick // Instantiation maybe not happen yet when we see a SpecializationDecl,
172ec727ea7Spatrick // e.g. when the type doesn't need to be complete, we still treat it as an
173ec727ea7Spatrick // instantiation as we'd like to keep the canonicalized result consistent.
174ec727ea7Spatrick return isa<ClassTemplateSpecializationDecl>(D);
175e5dd7070Spatrick case TSK_ExplicitSpecialization:
176e5dd7070Spatrick return false;
177e5dd7070Spatrick case TSK_ImplicitInstantiation:
178e5dd7070Spatrick case TSK_ExplicitInstantiationDeclaration:
179e5dd7070Spatrick case TSK_ExplicitInstantiationDefinition:
180e5dd7070Spatrick return true;
181e5dd7070Spatrick }
182e5dd7070Spatrick llvm_unreachable("invalid TemplateSpecializationKind");
183e5dd7070Spatrick }
184e5dd7070Spatrick
shouldIgnoreIfImplicit(const Decl * D)185e5dd7070Spatrick bool IndexingContext::shouldIgnoreIfImplicit(const Decl *D) {
186e5dd7070Spatrick if (isa<ObjCInterfaceDecl>(D))
187e5dd7070Spatrick return false;
188e5dd7070Spatrick if (isa<ObjCCategoryDecl>(D))
189e5dd7070Spatrick return false;
190e5dd7070Spatrick if (isa<ObjCIvarDecl>(D))
191e5dd7070Spatrick return false;
192e5dd7070Spatrick if (isa<ObjCMethodDecl>(D))
193e5dd7070Spatrick return false;
194e5dd7070Spatrick if (isa<ImportDecl>(D))
195e5dd7070Spatrick return false;
196e5dd7070Spatrick return true;
197e5dd7070Spatrick }
198e5dd7070Spatrick
199e5dd7070Spatrick static const CXXRecordDecl *
getDeclContextForTemplateInstationPattern(const Decl * D)200e5dd7070Spatrick getDeclContextForTemplateInstationPattern(const Decl *D) {
201e5dd7070Spatrick if (const auto *CTSD =
202e5dd7070Spatrick dyn_cast<ClassTemplateSpecializationDecl>(D->getDeclContext()))
203e5dd7070Spatrick return CTSD->getTemplateInstantiationPattern();
204e5dd7070Spatrick else if (const auto *RD = dyn_cast<CXXRecordDecl>(D->getDeclContext()))
205e5dd7070Spatrick return RD->getInstantiatedFromMemberClass();
206e5dd7070Spatrick return nullptr;
207e5dd7070Spatrick }
208e5dd7070Spatrick
adjustTemplateImplicitInstantiation(const Decl * D)209e5dd7070Spatrick static const Decl *adjustTemplateImplicitInstantiation(const Decl *D) {
210e5dd7070Spatrick if (const ClassTemplateSpecializationDecl *
211e5dd7070Spatrick SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
212ec727ea7Spatrick const auto *Template = SD->getTemplateInstantiationPattern();
213ec727ea7Spatrick if (Template)
214ec727ea7Spatrick return Template;
215ec727ea7Spatrick // Fallback to primary template if no instantiation is available yet (e.g.
216ec727ea7Spatrick // the type doesn't need to be complete).
217ec727ea7Spatrick return SD->getSpecializedTemplate()->getTemplatedDecl();
218e5dd7070Spatrick } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
219e5dd7070Spatrick return FD->getTemplateInstantiationPattern();
220e5dd7070Spatrick } else if (auto *VD = dyn_cast<VarDecl>(D)) {
221e5dd7070Spatrick return VD->getTemplateInstantiationPattern();
222e5dd7070Spatrick } else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) {
223e5dd7070Spatrick return RD->getInstantiatedFromMemberClass();
224e5dd7070Spatrick } else if (const auto *ED = dyn_cast<EnumDecl>(D)) {
225e5dd7070Spatrick return ED->getInstantiatedFromMemberEnum();
226e5dd7070Spatrick } else if (isa<FieldDecl>(D) || isa<TypedefNameDecl>(D)) {
227e5dd7070Spatrick const auto *ND = cast<NamedDecl>(D);
228e5dd7070Spatrick if (const CXXRecordDecl *Pattern =
229e5dd7070Spatrick getDeclContextForTemplateInstationPattern(ND)) {
230e5dd7070Spatrick for (const NamedDecl *BaseND : Pattern->lookup(ND->getDeclName())) {
231e5dd7070Spatrick if (BaseND->isImplicit())
232e5dd7070Spatrick continue;
233e5dd7070Spatrick if (BaseND->getKind() == ND->getKind())
234e5dd7070Spatrick return BaseND;
235e5dd7070Spatrick }
236e5dd7070Spatrick }
237e5dd7070Spatrick } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
238e5dd7070Spatrick if (const auto *ED = dyn_cast<EnumDecl>(ECD->getDeclContext())) {
239e5dd7070Spatrick if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) {
240e5dd7070Spatrick for (const NamedDecl *BaseECD : Pattern->lookup(ECD->getDeclName()))
241e5dd7070Spatrick return BaseECD;
242e5dd7070Spatrick }
243e5dd7070Spatrick }
244e5dd7070Spatrick }
245e5dd7070Spatrick return nullptr;
246e5dd7070Spatrick }
247e5dd7070Spatrick
isDeclADefinition(const Decl * D,const DeclContext * ContainerDC,ASTContext & Ctx)248e5dd7070Spatrick static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) {
249e5dd7070Spatrick if (auto VD = dyn_cast<VarDecl>(D))
250e5dd7070Spatrick return VD->isThisDeclarationADefinition(Ctx);
251e5dd7070Spatrick
252e5dd7070Spatrick if (auto FD = dyn_cast<FunctionDecl>(D))
253e5dd7070Spatrick return FD->isThisDeclarationADefinition();
254e5dd7070Spatrick
255e5dd7070Spatrick if (auto TD = dyn_cast<TagDecl>(D))
256e5dd7070Spatrick return TD->isThisDeclarationADefinition();
257e5dd7070Spatrick
258e5dd7070Spatrick if (auto MD = dyn_cast<ObjCMethodDecl>(D))
259e5dd7070Spatrick return MD->isThisDeclarationADefinition() || isa<ObjCImplDecl>(ContainerDC);
260e5dd7070Spatrick
261*12c85518Srobert if (isa<TypedefNameDecl>(D) || isa<EnumConstantDecl>(D) ||
262*12c85518Srobert isa<FieldDecl>(D) || isa<MSPropertyDecl>(D) || isa<ObjCImplDecl>(D) ||
263*12c85518Srobert isa<ObjCPropertyImplDecl>(D) || isa<ConceptDecl>(D))
264e5dd7070Spatrick return true;
265e5dd7070Spatrick
266e5dd7070Spatrick return false;
267e5dd7070Spatrick }
268e5dd7070Spatrick
269e5dd7070Spatrick /// Whether the given NamedDecl should be skipped because it has no name.
shouldSkipNamelessDecl(const NamedDecl * ND)270e5dd7070Spatrick static bool shouldSkipNamelessDecl(const NamedDecl *ND) {
271e5dd7070Spatrick return (ND->getDeclName().isEmpty() && !isa<TagDecl>(ND) &&
272e5dd7070Spatrick !isa<ObjCCategoryDecl>(ND)) || isa<CXXDeductionGuideDecl>(ND);
273e5dd7070Spatrick }
274e5dd7070Spatrick
adjustParent(const Decl * Parent)275e5dd7070Spatrick static const Decl *adjustParent(const Decl *Parent) {
276e5dd7070Spatrick if (!Parent)
277e5dd7070Spatrick return nullptr;
278e5dd7070Spatrick for (;; Parent = cast<Decl>(Parent->getDeclContext())) {
279e5dd7070Spatrick if (isa<TranslationUnitDecl>(Parent))
280e5dd7070Spatrick return nullptr;
281e5dd7070Spatrick if (isa<LinkageSpecDecl>(Parent) || isa<BlockDecl>(Parent))
282e5dd7070Spatrick continue;
283e5dd7070Spatrick if (auto NS = dyn_cast<NamespaceDecl>(Parent)) {
284e5dd7070Spatrick if (NS->isAnonymousNamespace())
285e5dd7070Spatrick continue;
286e5dd7070Spatrick } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
287e5dd7070Spatrick if (RD->isAnonymousStructOrUnion())
288e5dd7070Spatrick continue;
289e5dd7070Spatrick } else if (auto ND = dyn_cast<NamedDecl>(Parent)) {
290e5dd7070Spatrick if (shouldSkipNamelessDecl(ND))
291e5dd7070Spatrick continue;
292e5dd7070Spatrick }
293e5dd7070Spatrick return Parent;
294e5dd7070Spatrick }
295e5dd7070Spatrick }
296e5dd7070Spatrick
getCanonicalDecl(const Decl * D)297e5dd7070Spatrick static const Decl *getCanonicalDecl(const Decl *D) {
298e5dd7070Spatrick D = D->getCanonicalDecl();
299e5dd7070Spatrick if (auto TD = dyn_cast<TemplateDecl>(D)) {
300e5dd7070Spatrick if (auto TTD = TD->getTemplatedDecl()) {
301e5dd7070Spatrick D = TTD;
302e5dd7070Spatrick assert(D->isCanonicalDecl());
303e5dd7070Spatrick }
304e5dd7070Spatrick }
305e5dd7070Spatrick
306e5dd7070Spatrick return D;
307e5dd7070Spatrick }
308e5dd7070Spatrick
shouldReportOccurrenceForSystemDeclOnlyMode(bool IsRef,SymbolRoleSet Roles,ArrayRef<SymbolRelation> Relations)309e5dd7070Spatrick static bool shouldReportOccurrenceForSystemDeclOnlyMode(
310e5dd7070Spatrick bool IsRef, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations) {
311e5dd7070Spatrick if (!IsRef)
312e5dd7070Spatrick return true;
313e5dd7070Spatrick
314e5dd7070Spatrick auto acceptForRelation = [](SymbolRoleSet roles) -> bool {
315e5dd7070Spatrick bool accept = false;
316e5dd7070Spatrick applyForEachSymbolRoleInterruptible(roles, [&accept](SymbolRole r) -> bool {
317e5dd7070Spatrick switch (r) {
318e5dd7070Spatrick case SymbolRole::RelationChildOf:
319e5dd7070Spatrick case SymbolRole::RelationBaseOf:
320e5dd7070Spatrick case SymbolRole::RelationOverrideOf:
321e5dd7070Spatrick case SymbolRole::RelationExtendedBy:
322e5dd7070Spatrick case SymbolRole::RelationAccessorOf:
323e5dd7070Spatrick case SymbolRole::RelationIBTypeOf:
324e5dd7070Spatrick accept = true;
325e5dd7070Spatrick return false;
326e5dd7070Spatrick case SymbolRole::Declaration:
327e5dd7070Spatrick case SymbolRole::Definition:
328e5dd7070Spatrick case SymbolRole::Reference:
329e5dd7070Spatrick case SymbolRole::Read:
330e5dd7070Spatrick case SymbolRole::Write:
331e5dd7070Spatrick case SymbolRole::Call:
332e5dd7070Spatrick case SymbolRole::Dynamic:
333e5dd7070Spatrick case SymbolRole::AddressOf:
334e5dd7070Spatrick case SymbolRole::Implicit:
335e5dd7070Spatrick case SymbolRole::Undefinition:
336e5dd7070Spatrick case SymbolRole::RelationReceivedBy:
337e5dd7070Spatrick case SymbolRole::RelationCalledBy:
338e5dd7070Spatrick case SymbolRole::RelationContainedBy:
339e5dd7070Spatrick case SymbolRole::RelationSpecializationOf:
340e5dd7070Spatrick case SymbolRole::NameReference:
341e5dd7070Spatrick return true;
342e5dd7070Spatrick }
343e5dd7070Spatrick llvm_unreachable("Unsupported SymbolRole value!");
344e5dd7070Spatrick });
345e5dd7070Spatrick return accept;
346e5dd7070Spatrick };
347e5dd7070Spatrick
348e5dd7070Spatrick for (auto &Rel : Relations) {
349e5dd7070Spatrick if (acceptForRelation(Rel.Roles))
350e5dd7070Spatrick return true;
351e5dd7070Spatrick }
352e5dd7070Spatrick
353e5dd7070Spatrick return false;
354e5dd7070Spatrick }
355e5dd7070Spatrick
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)356e5dd7070Spatrick bool IndexingContext::handleDeclOccurrence(const Decl *D, SourceLocation Loc,
357e5dd7070Spatrick bool IsRef, const Decl *Parent,
358e5dd7070Spatrick SymbolRoleSet Roles,
359e5dd7070Spatrick ArrayRef<SymbolRelation> Relations,
360e5dd7070Spatrick const Expr *OrigE,
361e5dd7070Spatrick const Decl *OrigD,
362e5dd7070Spatrick const DeclContext *ContainerDC) {
363e5dd7070Spatrick if (D->isImplicit() && !isa<ObjCMethodDecl>(D))
364e5dd7070Spatrick return true;
365e5dd7070Spatrick if (!isa<NamedDecl>(D) || shouldSkipNamelessDecl(cast<NamedDecl>(D)))
366e5dd7070Spatrick return true;
367e5dd7070Spatrick
368e5dd7070Spatrick SourceManager &SM = Ctx->getSourceManager();
369e5dd7070Spatrick FileID FID = SM.getFileID(SM.getFileLoc(Loc));
370e5dd7070Spatrick if (FID.isInvalid())
371e5dd7070Spatrick return true;
372e5dd7070Spatrick
373e5dd7070Spatrick bool Invalid = false;
374e5dd7070Spatrick const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
375e5dd7070Spatrick if (Invalid || !SEntry.isFile())
376e5dd7070Spatrick return true;
377e5dd7070Spatrick
378e5dd7070Spatrick if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) {
379e5dd7070Spatrick switch (IndexOpts.SystemSymbolFilter) {
380e5dd7070Spatrick case IndexingOptions::SystemSymbolFilterKind::None:
381e5dd7070Spatrick return true;
382e5dd7070Spatrick case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
383e5dd7070Spatrick if (!shouldReportOccurrenceForSystemDeclOnlyMode(IsRef, Roles, Relations))
384e5dd7070Spatrick return true;
385e5dd7070Spatrick break;
386e5dd7070Spatrick case IndexingOptions::SystemSymbolFilterKind::All:
387e5dd7070Spatrick break;
388e5dd7070Spatrick }
389e5dd7070Spatrick }
390e5dd7070Spatrick
391e5dd7070Spatrick if (!OrigD)
392e5dd7070Spatrick OrigD = D;
393e5dd7070Spatrick
394e5dd7070Spatrick if (isTemplateImplicitInstantiation(D)) {
395e5dd7070Spatrick if (!IsRef)
396e5dd7070Spatrick return true;
397e5dd7070Spatrick D = adjustTemplateImplicitInstantiation(D);
398e5dd7070Spatrick if (!D)
399e5dd7070Spatrick return true;
400e5dd7070Spatrick assert(!isTemplateImplicitInstantiation(D));
401e5dd7070Spatrick }
402e5dd7070Spatrick
403e5dd7070Spatrick if (IsRef)
404e5dd7070Spatrick Roles |= (unsigned)SymbolRole::Reference;
405e5dd7070Spatrick else if (isDeclADefinition(OrigD, ContainerDC, *Ctx))
406e5dd7070Spatrick Roles |= (unsigned)SymbolRole::Definition;
407e5dd7070Spatrick else
408e5dd7070Spatrick Roles |= (unsigned)SymbolRole::Declaration;
409e5dd7070Spatrick
410e5dd7070Spatrick D = getCanonicalDecl(D);
411e5dd7070Spatrick Parent = adjustParent(Parent);
412e5dd7070Spatrick if (Parent)
413e5dd7070Spatrick Parent = getCanonicalDecl(Parent);
414e5dd7070Spatrick
415e5dd7070Spatrick SmallVector<SymbolRelation, 6> FinalRelations;
416e5dd7070Spatrick FinalRelations.reserve(Relations.size()+1);
417e5dd7070Spatrick
418e5dd7070Spatrick auto addRelation = [&](SymbolRelation Rel) {
419e5dd7070Spatrick auto It = llvm::find_if(FinalRelations, [&](SymbolRelation Elem) -> bool {
420e5dd7070Spatrick return Elem.RelatedSymbol == Rel.RelatedSymbol;
421e5dd7070Spatrick });
422e5dd7070Spatrick if (It != FinalRelations.end()) {
423e5dd7070Spatrick It->Roles |= Rel.Roles;
424e5dd7070Spatrick } else {
425e5dd7070Spatrick FinalRelations.push_back(Rel);
426e5dd7070Spatrick }
427e5dd7070Spatrick Roles |= Rel.Roles;
428e5dd7070Spatrick };
429e5dd7070Spatrick
430e5dd7070Spatrick if (Parent) {
431e5dd7070Spatrick if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) {
432e5dd7070Spatrick addRelation(SymbolRelation{
433e5dd7070Spatrick (unsigned)SymbolRole::RelationContainedBy,
434e5dd7070Spatrick Parent
435e5dd7070Spatrick });
436e5dd7070Spatrick } else {
437e5dd7070Spatrick addRelation(SymbolRelation{
438e5dd7070Spatrick (unsigned)SymbolRole::RelationChildOf,
439e5dd7070Spatrick Parent
440e5dd7070Spatrick });
441e5dd7070Spatrick }
442e5dd7070Spatrick }
443e5dd7070Spatrick
444e5dd7070Spatrick for (auto &Rel : Relations) {
445e5dd7070Spatrick addRelation(SymbolRelation(Rel.Roles,
446e5dd7070Spatrick Rel.RelatedSymbol->getCanonicalDecl()));
447e5dd7070Spatrick }
448e5dd7070Spatrick
449e5dd7070Spatrick IndexDataConsumer::ASTNodeInfo Node{OrigE, OrigD, Parent, ContainerDC};
450e5dd7070Spatrick return DataConsumer.handleDeclOccurrence(D, Roles, FinalRelations, Loc, Node);
451e5dd7070Spatrick }
452e5dd7070Spatrick
handleMacroDefined(const IdentifierInfo & Name,SourceLocation Loc,const MacroInfo & MI)453e5dd7070Spatrick void IndexingContext::handleMacroDefined(const IdentifierInfo &Name,
454e5dd7070Spatrick SourceLocation Loc,
455e5dd7070Spatrick const MacroInfo &MI) {
456a9ac8606Spatrick if (!shouldIndexMacroOccurrence(/*IsRef=*/false, Loc))
457a9ac8606Spatrick return;
458e5dd7070Spatrick SymbolRoleSet Roles = (unsigned)SymbolRole::Definition;
459e5dd7070Spatrick DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
460e5dd7070Spatrick }
461e5dd7070Spatrick
handleMacroUndefined(const IdentifierInfo & Name,SourceLocation Loc,const MacroInfo & MI)462e5dd7070Spatrick void IndexingContext::handleMacroUndefined(const IdentifierInfo &Name,
463e5dd7070Spatrick SourceLocation Loc,
464e5dd7070Spatrick const MacroInfo &MI) {
465a9ac8606Spatrick if (!shouldIndexMacroOccurrence(/*IsRef=*/false, Loc))
466a9ac8606Spatrick return;
467e5dd7070Spatrick SymbolRoleSet Roles = (unsigned)SymbolRole::Undefinition;
468e5dd7070Spatrick DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
469e5dd7070Spatrick }
470e5dd7070Spatrick
handleMacroReference(const IdentifierInfo & Name,SourceLocation Loc,const MacroInfo & MI)471e5dd7070Spatrick void IndexingContext::handleMacroReference(const IdentifierInfo &Name,
472e5dd7070Spatrick SourceLocation Loc,
473e5dd7070Spatrick const MacroInfo &MI) {
474a9ac8606Spatrick if (!shouldIndexMacroOccurrence(/*IsRef=*/true, Loc))
475a9ac8606Spatrick return;
476e5dd7070Spatrick SymbolRoleSet Roles = (unsigned)SymbolRole::Reference;
477e5dd7070Spatrick DataConsumer.handleMacroOccurrence(&Name, &MI, Roles, Loc);
478e5dd7070Spatrick }
479a9ac8606Spatrick
shouldIndexMacroOccurrence(bool IsRef,SourceLocation Loc)480a9ac8606Spatrick bool IndexingContext::shouldIndexMacroOccurrence(bool IsRef,
481a9ac8606Spatrick SourceLocation Loc) {
482a9ac8606Spatrick if (!IndexOpts.IndexMacros)
483a9ac8606Spatrick return false;
484a9ac8606Spatrick
485a9ac8606Spatrick switch (IndexOpts.SystemSymbolFilter) {
486a9ac8606Spatrick case IndexingOptions::SystemSymbolFilterKind::None:
487a9ac8606Spatrick break;
488a9ac8606Spatrick case IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly:
489a9ac8606Spatrick if (!IsRef)
490a9ac8606Spatrick return true;
491a9ac8606Spatrick break;
492a9ac8606Spatrick case IndexingOptions::SystemSymbolFilterKind::All:
493a9ac8606Spatrick return true;
494a9ac8606Spatrick }
495a9ac8606Spatrick
496a9ac8606Spatrick SourceManager &SM = Ctx->getSourceManager();
497a9ac8606Spatrick FileID FID = SM.getFileID(SM.getFileLoc(Loc));
498a9ac8606Spatrick if (FID.isInvalid())
499a9ac8606Spatrick return false;
500a9ac8606Spatrick
501a9ac8606Spatrick bool Invalid = false;
502a9ac8606Spatrick const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid);
503a9ac8606Spatrick if (Invalid || !SEntry.isFile())
504a9ac8606Spatrick return false;
505a9ac8606Spatrick
506a9ac8606Spatrick return SEntry.getFile().getFileCharacteristic() == SrcMgr::C_User;
507a9ac8606Spatrick }
508