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