brintos

brintos / llvm-project-archived public Read only

0
0
Text · 31.3 KiB · df875e0 Raw
824 lines · 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-exception6//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 18using namespace clang;19using 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 34namespace {35 36class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {37  IndexingContext &IndexCtx;38 39public:40  explicit IndexingDeclVisitor(IndexingContext &indexCtx)41    : IndexCtx(indexCtx) { }42 43  bool Handled = true;44 45  bool VisitDecl(const Decl *D) {46    Handled = false;47    return true;48  }49 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 the78  /// user.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 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 (const AssociatedConstraint &C = D->getTrailingRequiresClause())136      IndexCtx.indexBody(C.ConstraintExpr, Parent);137  }138 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 for154    // 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 a199  /// pseudo-override manner.200  ///201  /// Pseudo-overrides occur when a class template specialization declares202  /// a declaration that has the same name as a similar declaration in the203  /// non-specialized template.204  void205  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 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 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 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 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 332  bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {333    if (D->getSynthesize()) {334      // handled in VisitObjCPropertyImplDecl335      return true;336    }337    TRY_DECL(D, IndexCtx.handleDecl(D));338    handleDeclarator(D);339    return true;340  }341 342  bool VisitMSPropertyDecl(const MSPropertyDecl *D) {343    TRY_DECL(D, IndexCtx.handleDecl(D));344    handleDeclarator(D);345    return true;346  }347 348  bool VisitEnumConstantDecl(const EnumConstantDecl *D) {349    TRY_DECL(D, IndexCtx.handleDecl(D));350    IndexCtx.indexBody(D->getInitExpr(), D);351    return true;352  }353 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 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 381  bool VisitEnumDecl(const EnumDecl *ED) {382    TRY_TO(VisitTagDecl(ED));383    // Indexing for enumdecl itself is handled inside TagDecl, we just want to384    // 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 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_iterator395         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 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 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 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 their462    // location is reported at the name of the @implementation block. This463    // 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 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, D486                                   }));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 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 513  bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {514    // Methods associated with a property, even user-declared ones, are515    // handled when we handle the property.516    if (D->isPropertyAccessor())517      return true;518 519    handleObjCMethod(D);520    return true;521  }522 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 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 the570        // corresponding @synthesize. If there isn't one, use the containing571        // @implementation's location, rather than the property's location,572        // otherwise the header file containing the @interface will have different573        // indexing contents based on whether the @implementation was present or574        // 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 592  bool VisitNamespaceDecl(const NamespaceDecl *D) {593    TRY_DECL(D, IndexCtx.handleDecl(D));594    IndexCtx.indexDeclContext(D);595    return true;596  }597 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 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 using615      // itself, so there's not much point adding another decl or reference to616      // 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 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 body631    // 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 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 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 660  bool VisitClassTemplateSpecializationDecl(const661                                           ClassTemplateSpecializationDecl *D) {662    // FIXME: Notify subsequent callbacks if info comes from implicit663    // instantiation.664    llvm::PointerUnion<ClassTemplateDecl *,665                       ClassTemplatePartialSpecializationDecl *>666        Template = D->getSpecializedTemplateOrPartial();667    const Decl *SpecializationOf =668        isa<ClassTemplateDecl *>(Template)669            ? (Decl *)cast<ClassTemplateDecl *>(Template)670            : cast<ClassTemplatePartialSpecializationDecl *>(Template);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 685  static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl *D) {686    // We want to index the template parameters only once when indexing the687    // 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 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 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 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 748  bool VisitFriendDecl(const FriendDecl *D) {749    if (auto ND = D->getFriendDecl()) {750      // FIXME: Ignore a class template in a dependent context, these are not751      // linked properly with their redeclarations, ending up with duplicate752      // USRs.753      // See comment "Friend templates are visible in fairly strange ways." in754      // SemaTemplate.cpp which precedes code that prevents the friend template755      // 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 766  bool VisitImportDecl(const ImportDecl *D) {767    return IndexCtx.importedModule(D);768  }769 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 namespace779 780bool 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 798bool IndexingContext::indexDeclContext(const DeclContext *DC) {799  for (const auto *I : DC->decls())800    if (!indexDecl(I))801      return false;802  return true;803}804 805bool 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; // skip814 815  return indexDecl(D);816}817 818bool 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