1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | #include "IndexingContext.h" |
10 | #include "clang/Index/IndexDataConsumer.h" |
11 | #include "clang/AST/DeclVisitor.h" |
12 | |
13 | using namespace clang; |
14 | using namespace index; |
15 | |
16 | #define TRY_DECL(D,CALL_EXPR) \ |
17 | do { \ |
18 | if (!IndexCtx.shouldIndex(D)) return true; \ |
19 | if (!CALL_EXPR) \ |
20 | return false; \ |
21 | } while (0) |
22 | |
23 | #define TRY_TO(CALL_EXPR) \ |
24 | do { \ |
25 | if (!CALL_EXPR) \ |
26 | return false; \ |
27 | } while (0) |
28 | |
29 | namespace { |
30 | |
31 | class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> { |
32 | IndexingContext &IndexCtx; |
33 | |
34 | public: |
35 | explicit IndexingDeclVisitor(IndexingContext &indexCtx) |
36 | : IndexCtx(indexCtx) { } |
37 | |
38 | bool Handled = true; |
39 | |
40 | bool VisitDecl(const Decl *D) { |
41 | Handled = false; |
42 | return true; |
43 | } |
44 | |
45 | |
46 | |
47 | static bool hasUserDefined(const ObjCMethodDecl *D, |
48 | const ObjCImplDecl *Container) { |
49 | const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(), |
50 | D->isInstanceMethod()); |
51 | return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition(); |
52 | } |
53 | |
54 | void handleTemplateArgumentLoc(const TemplateArgumentLoc &TALoc, |
55 | const NamedDecl *Parent, |
56 | const DeclContext *DC) { |
57 | const TemplateArgumentLocInfo &LocInfo = TALoc.getLocInfo(); |
58 | switch (TALoc.getArgument().getKind()) { |
59 | case TemplateArgument::Expression: |
60 | IndexCtx.indexBody(LocInfo.getAsExpr(), Parent, DC); |
61 | break; |
62 | case TemplateArgument::Type: |
63 | IndexCtx.indexTypeSourceInfo(LocInfo.getAsTypeSourceInfo(), Parent, DC); |
64 | break; |
65 | case TemplateArgument::Template: |
66 | case TemplateArgument::TemplateExpansion: |
67 | IndexCtx.indexNestedNameSpecifierLoc(TALoc.getTemplateQualifierLoc(), |
68 | Parent, DC); |
69 | if (const TemplateDecl *TD = TALoc.getArgument() |
70 | .getAsTemplateOrTemplatePattern() |
71 | .getAsTemplateDecl()) { |
72 | if (const NamedDecl *TTD = TD->getTemplatedDecl()) |
73 | IndexCtx.handleReference(TTD, TALoc.getTemplateNameLoc(), Parent, DC); |
74 | } |
75 | break; |
76 | default: |
77 | break; |
78 | } |
79 | } |
80 | |
81 | void handleDeclarator(const DeclaratorDecl *D, |
82 | const NamedDecl *Parent = nullptr, |
83 | bool isIBType = false) { |
84 | if (!Parent) Parent = D; |
85 | |
86 | IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent, |
87 | Parent->getLexicalDeclContext(), |
88 | , isIBType); |
89 | IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent); |
90 | if (IndexCtx.shouldIndexFunctionLocalSymbols()) { |
91 | if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) { |
92 | auto *DC = Parm->getDeclContext(); |
93 | if (auto *FD = dyn_cast<FunctionDecl>(DC)) { |
94 | if (IndexCtx.shouldIndexParametersInDeclarations() || |
95 | FD->isThisDeclarationADefinition()) |
96 | IndexCtx.handleDecl(Parm); |
97 | } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) { |
98 | if (MD->isThisDeclarationADefinition()) |
99 | IndexCtx.handleDecl(Parm); |
100 | } else { |
101 | IndexCtx.handleDecl(Parm); |
102 | } |
103 | } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { |
104 | if (IndexCtx.shouldIndexParametersInDeclarations() || |
105 | FD->isThisDeclarationADefinition()) { |
106 | for (auto PI : FD->parameters()) { |
107 | IndexCtx.handleDecl(PI); |
108 | } |
109 | } |
110 | } |
111 | } else { |
112 | |
113 | if (const auto *FD = dyn_cast<FunctionDecl>(D)) { |
114 | if (FD->isThisDeclarationADefinition()) { |
115 | for (const auto *PV : FD->parameters()) { |
116 | if (PV->hasDefaultArg() && !PV->hasUninstantiatedDefaultArg() && |
117 | !PV->hasUnparsedDefaultArg()) |
118 | IndexCtx.indexBody(PV->getDefaultArg(), D); |
119 | } |
120 | } |
121 | } |
122 | } |
123 | } |
124 | |
125 | bool handleObjCMethod(const ObjCMethodDecl *D, |
126 | const ObjCPropertyDecl *AssociatedProp = nullptr) { |
127 | SmallVector<SymbolRelation, 4> Relations; |
128 | SmallVector<const ObjCMethodDecl*, 4> Overriden; |
129 | |
130 | D->getOverriddenMethods(Overriden); |
131 | for(auto overridden: Overriden) { |
132 | Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf, |
133 | overridden); |
134 | } |
135 | if (AssociatedProp) |
136 | Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf, |
137 | AssociatedProp); |
138 | |
139 | |
140 | |
141 | SourceLocation MethodLoc = D->getSelectorStartLoc(); |
142 | if (MethodLoc.isInvalid()) |
143 | MethodLoc = D->getLocation(); |
144 | |
145 | SourceLocation AttrLoc; |
146 | |
147 | |
148 | if (AssociatedProp) { |
149 | bool isGetter = !D->param_size(); |
150 | AttrLoc = isGetter ? |
151 | AssociatedProp->getGetterNameLoc(): |
152 | AssociatedProp->getSetterNameLoc(); |
153 | } |
154 | |
155 | SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic; |
156 | if (D->isImplicit()) { |
157 | if (AttrLoc.isValid()) { |
158 | MethodLoc = AttrLoc; |
159 | } else { |
160 | Roles |= (SymbolRoleSet)SymbolRole::Implicit; |
161 | } |
162 | } else if (AttrLoc.isValid()) { |
163 | IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()), |
164 | D->getDeclContext(), 0); |
165 | } |
166 | |
167 | TRY_DECL(D, IndexCtx.handleDecl(D, MethodLoc, Roles, Relations)); |
168 | IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D); |
169 | bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>(); |
170 | for (const auto *I : D->parameters()) { |
171 | handleDeclarator(I, D, hasIBActionAndFirst); |
172 | hasIBActionAndFirst = false; |
173 | } |
174 | |
175 | if (D->isThisDeclarationADefinition()) { |
176 | const Stmt *Body = D->getBody(); |
177 | if (Body) { |
178 | IndexCtx.indexBody(Body, D, D); |
179 | } |
180 | } |
181 | return true; |
182 | } |
183 | |
184 | |
185 | |
186 | |
187 | |
188 | |
189 | |
190 | void |
191 | gatherTemplatePseudoOverrides(const NamedDecl *D, |
192 | SmallVectorImpl<SymbolRelation> &Relations) { |
193 | if (!IndexCtx.getLangOpts().CPlusPlus) |
194 | return; |
195 | const auto *CTSD = |
196 | dyn_cast<ClassTemplateSpecializationDecl>(D->getLexicalDeclContext()); |
197 | if (!CTSD) |
198 | return; |
199 | llvm::PointerUnion<ClassTemplateDecl *, |
200 | ClassTemplatePartialSpecializationDecl *> |
201 | Template = CTSD->getSpecializedTemplateOrPartial(); |
202 | if (const auto *CTD = Template.dyn_cast<ClassTemplateDecl *>()) { |
203 | const CXXRecordDecl *Pattern = CTD->getTemplatedDecl(); |
204 | bool TypeOverride = isa<TypeDecl>(D); |
205 | for (const NamedDecl *ND : Pattern->lookup(D->getDeclName())) { |
206 | if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND)) |
207 | ND = CTD->getTemplatedDecl(); |
208 | if (ND->isImplicit()) |
209 | continue; |
210 | |
211 | if (!TypeOverride) { |
212 | if (ND->getKind() != D->getKind()) |
213 | continue; |
214 | } else if (!isa<TypeDecl>(ND)) |
215 | continue; |
216 | if (const auto *FD = dyn_cast<FunctionDecl>(ND)) { |
217 | const auto *DFD = cast<FunctionDecl>(D); |
218 | |
219 | if (FD->getStorageClass() != DFD->getStorageClass() || |
220 | FD->getNumParams() != DFD->getNumParams()) |
221 | continue; |
222 | } |
223 | Relations.emplace_back( |
224 | SymbolRoleSet(SymbolRole::RelationSpecializationOf), ND); |
225 | } |
226 | } |
227 | } |
228 | |
229 | bool VisitFunctionDecl(const FunctionDecl *D) { |
230 | SymbolRoleSet Roles{}; |
231 | SmallVector<SymbolRelation, 4> Relations; |
232 | if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) { |
233 | if (CXXMD->isVirtual()) |
234 | Roles |= (unsigned)SymbolRole::Dynamic; |
235 | for (const CXXMethodDecl *O : CXXMD->overridden_methods()) { |
236 | Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, O); |
237 | } |
238 | } |
239 | gatherTemplatePseudoOverrides(D, Relations); |
240 | if (const auto *Base = D->getPrimaryTemplate()) |
241 | Relations.push_back( |
242 | SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf), |
243 | Base->getTemplatedDecl())); |
244 | |
245 | TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations)); |
246 | handleDeclarator(D); |
247 | |
248 | if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { |
249 | IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(), |
250 | Ctor->getParent(), Ctor->getDeclContext(), |
251 | (unsigned)SymbolRole::NameReference); |
252 | |
253 | |
254 | for (const auto *Init : Ctor->inits()) { |
255 | if (Init->isWritten()) { |
256 | IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D); |
257 | if (const FieldDecl *Member = Init->getAnyMember()) |
258 | IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D, |
259 | (unsigned)SymbolRole::Write); |
260 | IndexCtx.indexBody(Init->getInit(), D, D); |
261 | } |
262 | } |
263 | } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) { |
264 | if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) { |
265 | IndexCtx.handleReference(Dtor->getParent(), |
266 | TypeNameInfo->getTypeLoc().getBeginLoc(), |
267 | Dtor->getParent(), Dtor->getDeclContext(), |
268 | (unsigned)SymbolRole::NameReference); |
269 | } |
270 | } else if (const auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) { |
271 | IndexCtx.handleReference(Guide->getDeducedTemplate()->getTemplatedDecl(), |
272 | Guide->getLocation(), Guide, |
273 | Guide->getDeclContext()); |
274 | } |
275 | |
276 | if (const ASTTemplateArgumentListInfo *TemplateArgInfo = |
277 | D->getTemplateSpecializationArgsAsWritten()) { |
278 | for (const auto &Arg : TemplateArgInfo->arguments()) |
279 | handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext()); |
280 | } |
281 | |
282 | if (D->isThisDeclarationADefinition()) { |
283 | const Stmt *Body = D->getBody(); |
284 | if (Body) { |
285 | IndexCtx.indexBody(Body, D, D); |
286 | } |
287 | } |
288 | return true; |
289 | } |
290 | |
291 | bool VisitVarDecl(const VarDecl *D) { |
292 | SmallVector<SymbolRelation, 4> Relations; |
293 | gatherTemplatePseudoOverrides(D, Relations); |
294 | TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); |
295 | handleDeclarator(D); |
296 | IndexCtx.indexBody(D->getInit(), D); |
297 | return true; |
298 | } |
299 | |
300 | bool VisitDecompositionDecl(const DecompositionDecl *D) { |
301 | for (const auto *Binding : D->bindings()) |
302 | TRY_DECL(Binding, IndexCtx.handleDecl(Binding)); |
303 | return Base::VisitDecompositionDecl(D); |
304 | } |
305 | |
306 | bool VisitFieldDecl(const FieldDecl *D) { |
307 | SmallVector<SymbolRelation, 4> Relations; |
308 | gatherTemplatePseudoOverrides(D, Relations); |
309 | TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); |
310 | handleDeclarator(D); |
311 | if (D->isBitField()) |
312 | IndexCtx.indexBody(D->getBitWidth(), D); |
313 | else if (D->hasInClassInitializer()) |
314 | IndexCtx.indexBody(D->getInClassInitializer(), D); |
315 | return true; |
316 | } |
317 | |
318 | bool VisitObjCIvarDecl(const ObjCIvarDecl *D) { |
319 | if (D->getSynthesize()) { |
320 | |
321 | return true; |
322 | } |
323 | TRY_DECL(D, IndexCtx.handleDecl(D)); |
324 | handleDeclarator(D); |
325 | return true; |
326 | } |
327 | |
328 | bool VisitMSPropertyDecl(const MSPropertyDecl *D) { |
329 | TRY_DECL(D, IndexCtx.handleDecl(D)); |
330 | handleDeclarator(D); |
331 | return true; |
332 | } |
333 | |
334 | bool VisitEnumConstantDecl(const EnumConstantDecl *D) { |
335 | TRY_DECL(D, IndexCtx.handleDecl(D)); |
336 | IndexCtx.indexBody(D->getInitExpr(), D); |
337 | return true; |
338 | } |
339 | |
340 | bool VisitTypedefNameDecl(const TypedefNameDecl *D) { |
341 | if (!D->isTransparentTag()) { |
342 | SmallVector<SymbolRelation, 4> Relations; |
343 | gatherTemplatePseudoOverrides(D, Relations); |
344 | TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); |
345 | IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); |
346 | } |
347 | return true; |
348 | } |
349 | |
350 | bool VisitTagDecl(const TagDecl *D) { |
351 | |
352 | if (D->isFreeStanding()) { |
353 | if (D->isThisDeclarationADefinition()) { |
354 | SmallVector<SymbolRelation, 4> Relations; |
355 | gatherTemplatePseudoOverrides(D, Relations); |
356 | IndexCtx.indexTagDecl(D, Relations); |
357 | } else { |
358 | SmallVector<SymbolRelation, 1> Relations; |
359 | gatherTemplatePseudoOverrides(D, Relations); |
360 | return IndexCtx.handleDecl(D, D->getLocation(), SymbolRoleSet(), |
361 | Relations, D->getLexicalDeclContext()); |
362 | } |
363 | } |
364 | return true; |
365 | } |
366 | |
367 | bool handleReferencedProtocols(const ObjCProtocolList &ProtList, |
368 | const ObjCContainerDecl *ContD, |
369 | SourceLocation SuperLoc) { |
370 | ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin(); |
371 | for (ObjCInterfaceDecl::protocol_iterator |
372 | I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) { |
373 | SourceLocation Loc = *LI; |
374 | ObjCProtocolDecl *PD = *I; |
375 | SymbolRoleSet roles{}; |
376 | if (Loc == SuperLoc) |
377 | roles |= (SymbolRoleSet)SymbolRole::Implicit; |
378 | TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles, |
379 | SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD})); |
380 | } |
381 | return true; |
382 | } |
383 | |
384 | bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { |
385 | if (D->isThisDeclarationADefinition()) { |
386 | TRY_DECL(D, IndexCtx.handleDecl(D)); |
387 | SourceLocation SuperLoc = D->getSuperClassLoc(); |
388 | if (auto *SuperD = D->getSuperClass()) { |
389 | bool hasSuperTypedef = false; |
390 | if (auto *TInfo = D->getSuperClassTInfo()) { |
391 | if (auto *TT = TInfo->getType()->getAs<TypedefType>()) { |
392 | if (auto *TD = TT->getDecl()) { |
393 | hasSuperTypedef = true; |
394 | TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D, |
395 | SymbolRoleSet())); |
396 | } |
397 | } |
398 | } |
399 | SymbolRoleSet superRoles{}; |
400 | if (hasSuperTypedef) |
401 | superRoles |= (SymbolRoleSet)SymbolRole::Implicit; |
402 | TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles, |
403 | SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D})); |
404 | } |
405 | TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, |
406 | SuperLoc)); |
407 | TRY_TO(IndexCtx.indexDeclContext(D)); |
408 | } else { |
409 | return IndexCtx.handleReference(D, D->getLocation(), nullptr, |
410 | D->getDeclContext(), SymbolRoleSet()); |
411 | } |
412 | return true; |
413 | } |
414 | |
415 | bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { |
416 | if (D->isThisDeclarationADefinition()) { |
417 | TRY_DECL(D, IndexCtx.handleDecl(D)); |
418 | TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, |
419 | SourceLocation())); |
420 | TRY_TO(IndexCtx.indexDeclContext(D)); |
421 | } else { |
422 | return IndexCtx.handleReference(D, D->getLocation(), nullptr, |
423 | D->getDeclContext(), SymbolRoleSet()); |
424 | } |
425 | return true; |
426 | } |
427 | |
428 | bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { |
429 | const ObjCInterfaceDecl *Class = D->getClassInterface(); |
430 | if (!Class) |
431 | return true; |
432 | |
433 | if (Class->isImplicitInterfaceDecl()) |
434 | IndexCtx.handleDecl(Class); |
435 | |
436 | TRY_DECL(D, IndexCtx.handleDecl(D)); |
437 | |
438 | |
439 | |
440 | |
441 | for (const auto *I : D->property_impls()) { |
442 | if (I->getLocation().isInvalid()) |
443 | IndexCtx.indexDecl(I); |
444 | } |
445 | for (const auto *I : D->decls()) { |
446 | if (!isa<ObjCPropertyImplDecl>(I) || |
447 | cast<ObjCPropertyImplDecl>(I)->getLocation().isValid()) |
448 | IndexCtx.indexDecl(I); |
449 | } |
450 | |
451 | return true; |
452 | } |
453 | |
454 | bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { |
455 | if (!IndexCtx.shouldIndex(D)) |
456 | return true; |
457 | const ObjCInterfaceDecl *C = D->getClassInterface(); |
458 | if (!C) |
459 | return true; |
460 | TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(), |
461 | SymbolRelation{ |
462 | (unsigned)SymbolRole::RelationExtendedBy, D |
463 | })); |
464 | SourceLocation CategoryLoc = D->getCategoryNameLoc(); |
465 | if (!CategoryLoc.isValid()) |
466 | CategoryLoc = D->getLocation(); |
467 | TRY_TO(IndexCtx.handleDecl(D, CategoryLoc)); |
468 | TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, |
469 | SourceLocation())); |
470 | TRY_TO(IndexCtx.indexDeclContext(D)); |
471 | return true; |
472 | } |
473 | |
474 | bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { |
475 | const ObjCCategoryDecl *Cat = D->getCategoryDecl(); |
476 | if (!Cat) |
477 | return true; |
478 | const ObjCInterfaceDecl *C = D->getClassInterface(); |
479 | if (C) |
480 | TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, |
481 | SymbolRoleSet())); |
482 | SourceLocation CategoryLoc = D->getCategoryNameLoc(); |
483 | if (!CategoryLoc.isValid()) |
484 | CategoryLoc = D->getLocation(); |
485 | TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc)); |
486 | IndexCtx.indexDeclContext(D); |
487 | return true; |
488 | } |
489 | |
490 | bool VisitObjCMethodDecl(const ObjCMethodDecl *D) { |
491 | |
492 | |
493 | if (D->isPropertyAccessor()) |
494 | return true; |
495 | |
496 | handleObjCMethod(D); |
497 | return true; |
498 | } |
499 | |
500 | bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { |
501 | if (ObjCMethodDecl *MD = D->getGetterMethodDecl()) |
502 | if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) |
503 | handleObjCMethod(MD, D); |
504 | if (ObjCMethodDecl *MD = D->getSetterMethodDecl()) |
505 | if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) |
506 | handleObjCMethod(MD, D); |
507 | TRY_DECL(D, IndexCtx.handleDecl(D)); |
508 | if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>()) |
509 | IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D, |
510 | D->getLexicalDeclContext(), false, true); |
511 | IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); |
512 | return true; |
513 | } |
514 | |
515 | bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { |
516 | ObjCPropertyDecl *PD = D->getPropertyDecl(); |
517 | auto *Container = cast<ObjCImplDecl>(D->getDeclContext()); |
518 | SourceLocation Loc = D->getLocation(); |
519 | SymbolRoleSet Roles = 0; |
520 | SmallVector<SymbolRelation, 1> Relations; |
521 | |
522 | if (ObjCIvarDecl *ID = D->getPropertyIvarDecl()) |
523 | Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID}); |
524 | if (Loc.isInvalid()) { |
525 | Loc = Container->getLocation(); |
526 | Roles |= (SymbolRoleSet)SymbolRole::Implicit; |
527 | } |
528 | TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations)); |
529 | |
530 | if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) |
531 | return true; |
532 | |
533 | getPropertyImplementation() == ObjCPropertyImplDecl..Synthesize", "/home/seafit/code_projects/clang_source/clang/lib/Index/IndexDecl.cpp", 533, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); |
534 | SymbolRoleSet AccessorMethodRoles = |
535 | SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit); |
536 | if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) { |
537 | if (MD->isPropertyAccessor() && |
538 | !hasUserDefined(MD, Container)) |
539 | IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container); |
540 | } |
541 | if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) { |
542 | if (MD->isPropertyAccessor() && |
543 | !hasUserDefined(MD, Container)) |
544 | IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container); |
545 | } |
546 | if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) { |
547 | if (IvarD->getSynthesize()) { |
548 | |
549 | |
550 | |
551 | |
552 | |
553 | |
554 | SymbolRoleSet IvarRoles = 0; |
555 | SourceLocation IvarLoc = D->getPropertyIvarDeclLoc(); |
556 | if (D->getLocation().isInvalid()) { |
557 | IvarLoc = Container->getLocation(); |
558 | IvarRoles = (SymbolRoleSet)SymbolRole::Implicit; |
559 | } else if (D->getLocation() == IvarLoc) { |
560 | IvarRoles = (SymbolRoleSet)SymbolRole::Implicit; |
561 | } |
562 | TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles)); |
563 | } else { |
564 | IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr, |
565 | D->getDeclContext(), SymbolRoleSet()); |
566 | } |
567 | } |
568 | return true; |
569 | } |
570 | |
571 | bool VisitNamespaceDecl(const NamespaceDecl *D) { |
572 | TRY_DECL(D, IndexCtx.handleDecl(D)); |
573 | IndexCtx.indexDeclContext(D); |
574 | return true; |
575 | } |
576 | |
577 | bool VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { |
578 | TRY_DECL(D, IndexCtx.handleDecl(D)); |
579 | IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); |
580 | IndexCtx.handleReference(D->getAliasedNamespace(), D->getTargetNameLoc(), D, |
581 | D->getLexicalDeclContext()); |
582 | return true; |
583 | } |
584 | |
585 | bool VisitUsingDecl(const UsingDecl *D) { |
586 | IndexCtx.handleDecl(D); |
587 | |
588 | const DeclContext *DC = D->getDeclContext()->getRedeclContext(); |
589 | const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); |
590 | IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, |
591 | D->getLexicalDeclContext()); |
592 | for (const auto *I : D->shadows()) |
593 | IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent, |
594 | D->getLexicalDeclContext(), SymbolRoleSet()); |
595 | return true; |
596 | } |
597 | |
598 | bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { |
599 | const DeclContext *DC = D->getDeclContext()->getRedeclContext(); |
600 | const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); |
601 | |
602 | |
603 | |
604 | if (!D->getParentFunctionOrMethod()) |
605 | IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, |
606 | D->getLexicalDeclContext()); |
607 | |
608 | return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(), |
609 | D->getLocation(), Parent, |
610 | D->getLexicalDeclContext(), |
611 | SymbolRoleSet()); |
612 | } |
613 | |
614 | bool VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) { |
615 | TRY_DECL(D, IndexCtx.handleDecl(D)); |
616 | const DeclContext *DC = D->getDeclContext()->getRedeclContext(); |
617 | const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); |
618 | IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, |
619 | D->getLexicalDeclContext()); |
620 | return true; |
621 | } |
622 | |
623 | bool VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) { |
624 | TRY_DECL(D, IndexCtx.handleDecl(D)); |
625 | const DeclContext *DC = D->getDeclContext()->getRedeclContext(); |
626 | const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); |
627 | IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, |
628 | D->getLexicalDeclContext()); |
629 | return true; |
630 | } |
631 | |
632 | bool VisitClassTemplateSpecializationDecl(const |
633 | ClassTemplateSpecializationDecl *D) { |
634 | |
635 | |
636 | llvm::PointerUnion<ClassTemplateDecl *, |
637 | ClassTemplatePartialSpecializationDecl *> |
638 | Template = D->getSpecializedTemplateOrPartial(); |
639 | const Decl *SpecializationOf = |
640 | Template.is<ClassTemplateDecl *>() |
641 | ? (Decl *)Template.get<ClassTemplateDecl *>() |
642 | : Template.get<ClassTemplatePartialSpecializationDecl *>(); |
643 | if (!D->isThisDeclarationADefinition()) |
644 | IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); |
645 | IndexCtx.indexTagDecl( |
646 | D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf), |
647 | SpecializationOf)); |
648 | if (TypeSourceInfo *TSI = D->getTypeAsWritten()) |
649 | IndexCtx.indexTypeSourceInfo(TSI, , |
650 | D->getLexicalDeclContext()); |
651 | return true; |
652 | } |
653 | |
654 | static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl *D) { |
655 | if (!D) |
656 | return false; |
657 | |
658 | |
659 | if (const auto *FD = dyn_cast<FunctionDecl>(D)) |
660 | return FD->getCanonicalDecl() == FD; |
661 | else if (const auto *TD = dyn_cast<TagDecl>(D)) |
662 | return TD->getCanonicalDecl() == TD; |
663 | else if (const auto *VD = dyn_cast<VarDecl>(D)) |
664 | return VD->getCanonicalDecl() == VD; |
665 | return true; |
666 | } |
667 | |
668 | bool VisitTemplateDecl(const TemplateDecl *D) { |
669 | |
670 | const NamedDecl *Parent = D->getTemplatedDecl(); |
671 | if (!Parent) |
672 | return true; |
673 | |
674 | |
675 | if (D->getTemplateParameters() && |
676 | shouldIndexTemplateParameterDefaultValue(Parent)) { |
677 | const TemplateParameterList *Params = D->getTemplateParameters(); |
678 | for (const NamedDecl *TP : *Params) { |
679 | if (IndexCtx.shouldIndexTemplateParameters()) |
680 | IndexCtx.handleDecl(TP); |
681 | if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) { |
682 | if (TTP->hasDefaultArgument()) |
683 | IndexCtx.indexTypeSourceInfo(TTP->getDefaultArgumentInfo(), Parent); |
684 | } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) { |
685 | if (NTTP->hasDefaultArgument()) |
686 | IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent); |
687 | } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) { |
688 | if (TTPD->hasDefaultArgument()) |
689 | handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent, |
690 | TP->getLexicalDeclContext()); |
691 | } |
692 | } |
693 | } |
694 | |
695 | return Visit(Parent); |
696 | } |
697 | |
698 | bool VisitFriendDecl(const FriendDecl *D) { |
699 | if (auto ND = D->getFriendDecl()) { |
700 | |
701 | |
702 | |
703 | |
704 | |
705 | |
706 | if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext()) |
707 | return true; |
708 | return Visit(ND); |
709 | } |
710 | if (auto Ty = D->getFriendType()) { |
711 | IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext())); |
712 | } |
713 | return true; |
714 | } |
715 | |
716 | bool VisitImportDecl(const ImportDecl *D) { |
717 | return IndexCtx.importedModule(D); |
718 | } |
719 | |
720 | bool VisitStaticAssertDecl(const StaticAssertDecl *D) { |
721 | IndexCtx.indexBody(D->getAssertExpr(), |
722 | dyn_cast<NamedDecl>(D->getDeclContext()), |
723 | D->getLexicalDeclContext()); |
724 | return true; |
725 | } |
726 | }; |
727 | |
728 | } |
729 | |
730 | bool IndexingContext::indexDecl(const Decl *D) { |
731 | if (D->isImplicit() && shouldIgnoreIfImplicit(D)) |
732 | return true; |
733 | |
734 | if (isTemplateImplicitInstantiation(D) && !shouldIndexImplicitInstantiation()) |
735 | return true; |
736 | |
737 | IndexingDeclVisitor Visitor(*this); |
738 | bool ShouldContinue = Visitor.Visit(D); |
739 | if (!ShouldContinue) |
740 | return false; |
741 | |
742 | if (!Visitor.Handled && isa<DeclContext>(D)) |
743 | return indexDeclContext(cast<DeclContext>(D)); |
744 | |
745 | return true; |
746 | } |
747 | |
748 | bool IndexingContext::indexDeclContext(const DeclContext *DC) { |
749 | for (const auto *I : DC->decls()) |
750 | if (!indexDecl(I)) |
751 | return false; |
752 | return true; |
753 | } |
754 | |
755 | bool IndexingContext::indexTopLevelDecl(const Decl *D) { |
756 | if (D->getLocation().isInvalid()) |
757 | return true; |
758 | |
759 | if (isa<ObjCMethodDecl>(D)) |
760 | return true; |
761 | |
762 | return indexDecl(D); |
763 | } |
764 | |
765 | bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) { |
766 | for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) |
767 | if (!indexTopLevelDecl(*I)) |
768 | return false; |
769 | return true; |
770 | } |
771 | |