Clang Project

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