]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/Index/IndexDecl.cpp
Vendor import of clang trunk r301939:
[FreeBSD/FreeBSD.git] / lib / Index / IndexDecl.cpp
1 //===- IndexDecl.cpp - Indexing declarations ------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "IndexingContext.h"
11 #include "clang/Index/IndexDataConsumer.h"
12 #include "clang/AST/DeclVisitor.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:
36   explicit IndexingDeclVisitor(IndexingContext &indexCtx)
37     : IndexCtx(indexCtx) { }
38
39   bool Handled = true;
40
41   bool VisitDecl(const Decl *D) {
42     Handled = false;
43     return true;
44   }
45
46   /// \brief Returns true if the given method has been defined explicitly by the
47   /// user.
48   static bool hasUserDefined(const ObjCMethodDecl *D,
49                              const ObjCImplDecl *Container) {
50     const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(),
51                                                     D->isInstanceMethod());
52     return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition();
53   }
54
55   void handleDeclarator(const DeclaratorDecl *D,
56                         const NamedDecl *Parent = nullptr,
57                         bool isIBType = false) {
58     if (!Parent) Parent = D;
59
60     IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent,
61                                  Parent->getLexicalDeclContext(),
62                                  /*isBase=*/false, isIBType);
63     IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
64     if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
65       // Only index parameters in definitions, parameters in declarations are
66       // not useful.
67       if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
68         auto *DC = Parm->getDeclContext();
69         if (auto *FD = dyn_cast<FunctionDecl>(DC)) {
70           if (FD->isThisDeclarationADefinition())
71             IndexCtx.handleDecl(Parm);
72         } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) {
73           if (MD->isThisDeclarationADefinition())
74             IndexCtx.handleDecl(Parm);
75         } else {
76           IndexCtx.handleDecl(Parm);
77         }
78       } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
79         if (FD->isThisDeclarationADefinition()) {
80           for (auto PI : FD->parameters()) {
81             IndexCtx.handleDecl(PI);
82           }
83         }
84       }
85     }
86   }
87
88   bool handleObjCMethod(const ObjCMethodDecl *D,
89                         const ObjCPropertyDecl *AssociatedProp = nullptr) {
90     SmallVector<SymbolRelation, 4> Relations;
91     SmallVector<const ObjCMethodDecl*, 4> Overriden;
92
93     D->getOverriddenMethods(Overriden);
94     for(auto overridden: Overriden) {
95       Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf,
96                              overridden);
97     }
98     if (AssociatedProp)
99       Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf,
100                              AssociatedProp);
101
102     // getLocation() returns beginning token of a method declaration, but for
103     // indexing purposes we want to point to the base name.
104     SourceLocation MethodLoc = D->getSelectorStartLoc();
105     if (MethodLoc.isInvalid())
106       MethodLoc = D->getLocation();
107
108     SourceLocation AttrLoc;
109
110     // check for (getter=/setter=)
111     if (AssociatedProp) {
112       bool isGetter = !D->param_size();
113       AttrLoc = isGetter ?
114         AssociatedProp->getGetterNameLoc():
115         AssociatedProp->getSetterNameLoc();
116     }
117
118     SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic;
119     if (D->isImplicit()) {
120       if (AttrLoc.isValid()) {
121         MethodLoc = AttrLoc;
122       } else {
123         Roles |= (SymbolRoleSet)SymbolRole::Implicit;
124       }
125     } else if (AttrLoc.isValid()) {
126       IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()),
127                                D->getDeclContext(), 0);
128     }
129
130     TRY_DECL(D, IndexCtx.handleDecl(D, MethodLoc, Roles, Relations));
131     IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D);
132     bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>();
133     for (const auto *I : D->parameters()) {
134       handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst);
135       hasIBActionAndFirst = false;
136     }
137
138     if (D->isThisDeclarationADefinition()) {
139       const Stmt *Body = D->getBody();
140       if (Body) {
141         IndexCtx.indexBody(Body, D, D);
142       }
143     }
144     return true;
145   }
146
147   /// Gather the declarations which the given declaration \D overrides in a
148   /// pseudo-override manner.
149   ///
150   /// Pseudo-overrides occur when a class template specialization declares
151   /// a declaration that has the same name as a similar declaration in the
152   /// non-specialized template.
153   void
154   gatherTemplatePseudoOverrides(const NamedDecl *D,
155                                 SmallVectorImpl<SymbolRelation> &Relations) {
156     if (!IndexCtx.getLangOpts().CPlusPlus)
157       return;
158     const auto *CTSD =
159         dyn_cast<ClassTemplateSpecializationDecl>(D->getLexicalDeclContext());
160     if (!CTSD)
161       return;
162     llvm::PointerUnion<ClassTemplateDecl *,
163                        ClassTemplatePartialSpecializationDecl *>
164         Template = CTSD->getSpecializedTemplateOrPartial();
165     if (const auto *CTD = Template.dyn_cast<ClassTemplateDecl *>()) {
166       const CXXRecordDecl *Pattern = CTD->getTemplatedDecl();
167       bool TypeOverride = isa<TypeDecl>(D);
168       for (const NamedDecl *ND : Pattern->lookup(D->getDeclName())) {
169         if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND))
170           ND = CTD->getTemplatedDecl();
171         if (ND->isImplicit())
172           continue;
173         // Types can override other types.
174         if (!TypeOverride) {
175           if (ND->getKind() != D->getKind())
176             continue;
177         } else if (!isa<TypeDecl>(ND))
178           continue;
179         if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
180           const auto *DFD = cast<FunctionDecl>(D);
181           // Function overrides are approximated using the number of parameters.
182           if (FD->getStorageClass() != DFD->getStorageClass() ||
183               FD->getNumParams() != DFD->getNumParams())
184             continue;
185         }
186         Relations.emplace_back(
187             SymbolRoleSet(SymbolRole::RelationOverrideOf) |
188                 SymbolRoleSet(SymbolRole::RelationSpecializationOf),
189             ND);
190       }
191     }
192   }
193
194   bool VisitFunctionDecl(const FunctionDecl *D) {
195     if (D->isDeleted())
196       return true;
197
198     SymbolRoleSet Roles{};
199     SmallVector<SymbolRelation, 4> Relations;
200     if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {
201       if (CXXMD->isVirtual())
202         Roles |= (unsigned)SymbolRole::Dynamic;
203       for (auto I = CXXMD->begin_overridden_methods(),
204            E = CXXMD->end_overridden_methods(); I != E; ++I) {
205         Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, *I);
206       }
207     }
208     gatherTemplatePseudoOverrides(D, Relations);
209     if (const auto *Base = D->getPrimaryTemplate())
210       Relations.push_back(
211           SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
212                          Base->getTemplatedDecl()));
213
214     TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations));
215     handleDeclarator(D);
216
217     if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
218       IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(),
219                                Ctor->getParent(), Ctor->getDeclContext());
220
221       // Constructor initializers.
222       for (const auto *Init : Ctor->inits()) {
223         if (Init->isWritten()) {
224           IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
225           if (const FieldDecl *Member = Init->getAnyMember())
226             IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D,
227                                      (unsigned)SymbolRole::Write);
228           IndexCtx.indexBody(Init->getInit(), D, D);
229         }
230       }
231     } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) {
232       if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) {
233         IndexCtx.handleReference(Dtor->getParent(),
234                                  TypeNameInfo->getTypeLoc().getLocStart(),
235                                  Dtor->getParent(), Dtor->getDeclContext());
236       }
237     }
238
239     if (D->isThisDeclarationADefinition()) {
240       const Stmt *Body = D->getBody();
241       if (Body) {
242         IndexCtx.indexBody(Body, D, D);
243       }
244     }
245     return true;
246   }
247
248   bool VisitVarDecl(const VarDecl *D) {
249     SmallVector<SymbolRelation, 4> Relations;
250     gatherTemplatePseudoOverrides(D, Relations);
251     TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
252     handleDeclarator(D);
253     IndexCtx.indexBody(D->getInit(), D);
254     return true;
255   }
256
257   bool VisitFieldDecl(const FieldDecl *D) {
258     SmallVector<SymbolRelation, 4> Relations;
259     gatherTemplatePseudoOverrides(D, Relations);
260     TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
261     handleDeclarator(D);
262     if (D->isBitField())
263       IndexCtx.indexBody(D->getBitWidth(), D);
264     else if (D->hasInClassInitializer())
265       IndexCtx.indexBody(D->getInClassInitializer(), D);
266     return true;
267   }
268
269   bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
270     if (D->getSynthesize()) {
271       // handled in VisitObjCPropertyImplDecl
272       return true;
273     }
274     TRY_DECL(D, IndexCtx.handleDecl(D));
275     handleDeclarator(D);
276     return true;
277   }
278
279   bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
280     handleDeclarator(D);
281     return true;
282   }
283
284   bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
285     TRY_DECL(D, IndexCtx.handleDecl(D));
286     IndexCtx.indexBody(D->getInitExpr(), D);
287     return true;
288   }
289
290   bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
291     if (!D->isTransparentTag()) {
292       SmallVector<SymbolRelation, 4> Relations;
293       gatherTemplatePseudoOverrides(D, Relations);
294       TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
295       IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
296     }
297     return true;
298   }
299
300   bool VisitTagDecl(const TagDecl *D) {
301     // Non-free standing tags are handled in indexTypeSourceInfo.
302     if (D->isFreeStanding()) {
303       if (D->isThisDeclarationADefinition()) {
304         SmallVector<SymbolRelation, 4> Relations;
305         gatherTemplatePseudoOverrides(D, Relations);
306         IndexCtx.indexTagDecl(D, Relations);
307       } else {
308         auto *Parent = dyn_cast<NamedDecl>(D->getDeclContext());
309         return IndexCtx.handleReference(D, D->getLocation(), Parent,
310                                         D->getLexicalDeclContext(),
311                                         SymbolRoleSet());
312       }
313     }
314     return true;
315   }
316
317   bool handleReferencedProtocols(const ObjCProtocolList &ProtList,
318                                  const ObjCContainerDecl *ContD,
319                                  SourceLocation SuperLoc) {
320     ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
321     for (ObjCInterfaceDecl::protocol_iterator
322          I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
323       SourceLocation Loc = *LI;
324       ObjCProtocolDecl *PD = *I;
325       SymbolRoleSet roles{};
326       if (Loc == SuperLoc)
327         roles |= (SymbolRoleSet)SymbolRole::Implicit;
328       TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles,
329           SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD}));
330     }
331     return true;
332   }
333
334   bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
335     if (D->isThisDeclarationADefinition()) {
336       TRY_DECL(D, IndexCtx.handleDecl(D));
337       SourceLocation SuperLoc = D->getSuperClassLoc();
338       if (auto *SuperD = D->getSuperClass()) {
339         bool hasSuperTypedef = false;
340         if (auto *TInfo = D->getSuperClassTInfo()) {
341           if (auto *TT = TInfo->getType()->getAs<TypedefType>()) {
342             if (auto *TD = TT->getDecl()) {
343               hasSuperTypedef = true;
344               TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D,
345                                               SymbolRoleSet()));
346             }
347           }
348         }
349         SymbolRoleSet superRoles{};
350         if (hasSuperTypedef)
351           superRoles |= (SymbolRoleSet)SymbolRole::Implicit;
352         TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles,
353             SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D}));
354       }
355       TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
356                                        SuperLoc));
357       TRY_TO(IndexCtx.indexDeclContext(D));
358     } else {
359       return IndexCtx.handleReference(D, D->getLocation(), nullptr,
360                                       D->getDeclContext(), SymbolRoleSet());
361     }
362     return true;
363   }
364
365   bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
366     if (D->isThisDeclarationADefinition()) {
367       TRY_DECL(D, IndexCtx.handleDecl(D));
368       TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
369                                        /*superLoc=*/SourceLocation()));
370       TRY_TO(IndexCtx.indexDeclContext(D));
371     } else {
372       return IndexCtx.handleReference(D, D->getLocation(), nullptr,
373                                       D->getDeclContext(), SymbolRoleSet());
374     }
375     return true;
376   }
377
378   bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
379     const ObjCInterfaceDecl *Class = D->getClassInterface();
380     if (!Class)
381       return true;
382
383     if (Class->isImplicitInterfaceDecl())
384       IndexCtx.handleDecl(Class);
385
386     TRY_DECL(D, IndexCtx.handleDecl(D));
387
388     // Visit implicit @synthesize property implementations first as their
389     // location is reported at the name of the @implementation block. This
390     // serves no purpose other than to simplify the FileCheck-based tests.
391     for (const auto *I : D->property_impls()) {
392       if (I->getLocation().isInvalid())
393         IndexCtx.indexDecl(I);
394     }
395     for (const auto *I : D->decls()) {
396       if (!isa<ObjCPropertyImplDecl>(I) ||
397           cast<ObjCPropertyImplDecl>(I)->getLocation().isValid())
398         IndexCtx.indexDecl(I);
399     }
400
401     return true;
402   }
403
404   bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
405     if (!IndexCtx.shouldIndex(D))
406       return true;
407     const ObjCInterfaceDecl *C = D->getClassInterface();
408     if (!C)
409       return true;
410     TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(),
411                                    SymbolRelation{
412                                      (unsigned)SymbolRole::RelationExtendedBy, D
413                                    }));
414     SourceLocation CategoryLoc = D->getCategoryNameLoc();
415     if (!CategoryLoc.isValid())
416       CategoryLoc = D->getLocation();
417     TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));
418     TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
419                                      /*superLoc=*/SourceLocation()));
420     TRY_TO(IndexCtx.indexDeclContext(D));
421     return true;
422   }
423
424   bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
425     const ObjCCategoryDecl *Cat = D->getCategoryDecl();
426     if (!Cat)
427       return true;
428     const ObjCInterfaceDecl *C = D->getClassInterface();
429     if (C)
430       TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
431                                       SymbolRoleSet()));
432     SourceLocation CategoryLoc = D->getCategoryNameLoc();
433     if (!CategoryLoc.isValid())
434       CategoryLoc = D->getLocation();
435     TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc));
436     IndexCtx.indexDeclContext(D);
437     return true;
438   }
439
440   bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
441     // Methods associated with a property, even user-declared ones, are
442     // handled when we handle the property.
443     if (D->isPropertyAccessor())
444       return true;
445
446     handleObjCMethod(D);
447     return true;
448   }
449
450   bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
451     if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
452       if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
453         handleObjCMethod(MD, D);
454     if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
455       if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
456         handleObjCMethod(MD, D);
457     TRY_DECL(D, IndexCtx.handleDecl(D));
458     if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>())
459       IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D,
460                                    D->getLexicalDeclContext(), false, true);
461     IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
462     return true;
463   }
464
465   bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
466     ObjCPropertyDecl *PD = D->getPropertyDecl();
467     auto *Container = cast<ObjCImplDecl>(D->getDeclContext());
468     SourceLocation Loc = D->getLocation();
469     SymbolRoleSet Roles = 0;
470     SmallVector<SymbolRelation, 1> Relations;
471
472     if (ObjCIvarDecl *ID = D->getPropertyIvarDecl())
473       Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID});
474     if (Loc.isInvalid()) {
475       Loc = Container->getLocation();
476       Roles |= (SymbolRoleSet)SymbolRole::Implicit;
477     }
478     TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations));
479
480     if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
481       return true;
482
483     assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
484     SymbolRoleSet AccessorMethodRoles =
485       SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit);
486     if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
487       if (MD->isPropertyAccessor() &&
488           !hasUserDefined(MD, Container))
489         IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
490     }
491     if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
492       if (MD->isPropertyAccessor() &&
493           !hasUserDefined(MD, Container))
494         IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
495     }
496     if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
497       if (IvarD->getSynthesize()) {
498         // For synthesized ivars, use the location of its name in the
499         // corresponding @synthesize. If there isn't one, use the containing
500         // @implementation's location, rather than the property's location,
501         // otherwise the header file containing the @interface will have different
502         // indexing contents based on whether the @implementation was present or
503         // not in the translation unit.
504         SymbolRoleSet IvarRoles = 0;
505         SourceLocation IvarLoc = D->getPropertyIvarDeclLoc();
506         if (D->getLocation().isInvalid()) {
507           IvarLoc = Container->getLocation();
508           IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
509         } else if (D->getLocation() == IvarLoc) {
510           IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
511         }
512         TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles));
513       } else {
514         IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
515                                  D->getDeclContext(), SymbolRoleSet());
516       }
517     }
518     return true;
519   }
520
521   bool VisitNamespaceDecl(const NamespaceDecl *D) {
522     TRY_DECL(D, IndexCtx.handleDecl(D));
523     IndexCtx.indexDeclContext(D);
524     return true;
525   }
526
527   bool VisitUsingDecl(const UsingDecl *D) {
528     const DeclContext *DC = D->getDeclContext()->getRedeclContext();
529     const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
530
531     IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
532                                          D->getLexicalDeclContext());
533     for (const auto *I : D->shadows())
534       IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
535                                D->getLexicalDeclContext(), SymbolRoleSet());
536     return true;
537   }
538
539   bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
540     const DeclContext *DC = D->getDeclContext()->getRedeclContext();
541     const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
542
543     IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
544                                          D->getLexicalDeclContext());
545     return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
546                                     D->getLocation(), Parent,
547                                     D->getLexicalDeclContext(),
548                                     SymbolRoleSet());
549   }
550
551   bool VisitClassTemplateSpecializationDecl(const
552                                            ClassTemplateSpecializationDecl *D) {
553     // FIXME: Notify subsequent callbacks if info comes from implicit
554     // instantiation.
555     if (D->isThisDeclarationADefinition()) {
556       llvm::PointerUnion<ClassTemplateDecl *,
557                          ClassTemplatePartialSpecializationDecl *>
558           Template = D->getSpecializedTemplateOrPartial();
559       const Decl *SpecializationOf =
560           Template.is<ClassTemplateDecl *>()
561               ? (Decl *)Template.get<ClassTemplateDecl *>()
562               : Template.get<ClassTemplatePartialSpecializationDecl *>();
563       IndexCtx.indexTagDecl(
564           D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
565                             SpecializationOf));
566     }
567     if (TypeSourceInfo *TSI = D->getTypeAsWritten())
568       IndexCtx.indexTypeSourceInfo(TSI, /*Parent=*/nullptr,
569                                    D->getLexicalDeclContext());
570     return true;
571   }
572
573   bool VisitTemplateDecl(const TemplateDecl *D) {
574     // FIXME: Template parameters.
575     return Visit(D->getTemplatedDecl());
576   }
577
578   bool VisitFriendDecl(const FriendDecl *D) {
579     if (auto ND = D->getFriendDecl()) {
580       // FIXME: Ignore a class template in a dependent context, these are not
581       // linked properly with their redeclarations, ending up with duplicate
582       // USRs.
583       // See comment "Friend templates are visible in fairly strange ways." in
584       // SemaTemplate.cpp which precedes code that prevents the friend template
585       // from becoming visible from the enclosing context.
586       if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
587         return true;
588       return Visit(ND);
589     }
590     if (auto Ty = D->getFriendType()) {
591       IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
592     }
593     return true;
594   }
595
596   bool VisitImportDecl(const ImportDecl *D) {
597     return IndexCtx.importedModule(D);
598   }
599 };
600
601 } // anonymous namespace
602
603 bool IndexingContext::indexDecl(const Decl *D) {
604   if (D->isImplicit() && shouldIgnoreIfImplicit(D))
605     return true;
606
607   if (isTemplateImplicitInstantiation(D))
608     return true;
609
610   IndexingDeclVisitor Visitor(*this);
611   bool ShouldContinue = Visitor.Visit(D);
612   if (!ShouldContinue)
613     return false;
614
615   if (!Visitor.Handled && isa<DeclContext>(D))
616     return indexDeclContext(cast<DeclContext>(D));
617
618   return true;
619 }
620
621 bool IndexingContext::indexDeclContext(const DeclContext *DC) {
622   for (const auto *I : DC->decls())
623     if (!indexDecl(I))
624       return false;
625   return true;
626 }
627
628 bool IndexingContext::indexTopLevelDecl(const Decl *D) {
629   if (D->getLocation().isInvalid())
630     return true;
631
632   if (isa<ObjCMethodDecl>(D))
633     return true; // Wait for the objc container.
634
635   return indexDecl(D);
636 }
637
638 bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
639   for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
640     if (!indexTopLevelDecl(*I))
641       return false;
642   return true;
643 }