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