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