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