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