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