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