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