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