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