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