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