1 //===- IndexDecl.cpp - Indexing declarations ------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "IndexingContext.h" 11 #include "clang/Index/IndexDataConsumer.h" 12 #include "clang/AST/DeclVisitor.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 /// \brief Returns true if the given method has been defined explicitly by the 47 /// user. 48 static bool hasUserDefined(const ObjCMethodDecl *D, 49 const ObjCImplDecl *Container) { 50 const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(), 51 D->isInstanceMethod()); 52 return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition(); 53 } 54 55 void handleDeclarator(const DeclaratorDecl *D, 56 const NamedDecl *Parent = nullptr, 57 bool isIBType = false) { 58 if (!Parent) Parent = D; 59 60 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent, 61 Parent->getLexicalDeclContext(), 62 /*isBase=*/false, isIBType); 63 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent); 64 if (IndexCtx.shouldIndexFunctionLocalSymbols()) { 65 // Only index parameters in definitions, parameters in declarations are 66 // not useful. 67 if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) { 68 auto *DC = Parm->getDeclContext(); 69 if (auto *FD = dyn_cast<FunctionDecl>(DC)) { 70 if (FD->isThisDeclarationADefinition()) 71 IndexCtx.handleDecl(Parm); 72 } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) { 73 if (MD->isThisDeclarationADefinition()) 74 IndexCtx.handleDecl(Parm); 75 } else { 76 IndexCtx.handleDecl(Parm); 77 } 78 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 79 if (FD->isThisDeclarationADefinition()) { 80 for (auto PI : FD->parameters()) { 81 IndexCtx.handleDecl(PI); 82 } 83 } 84 } 85 } 86 } 87 88 bool handleObjCMethod(const ObjCMethodDecl *D, 89 const ObjCPropertyDecl *AssociatedProp = nullptr) { 90 SmallVector<SymbolRelation, 4> Relations; 91 SmallVector<const ObjCMethodDecl*, 4> Overriden; 92 93 D->getOverriddenMethods(Overriden); 94 for(auto overridden: Overriden) { 95 Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf, 96 overridden); 97 } 98 if (AssociatedProp) 99 Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf, 100 AssociatedProp); 101 102 // getLocation() returns beginning token of a method declaration, but for 103 // indexing purposes we want to point to the base name. 104 SourceLocation MethodLoc = D->getSelectorStartLoc(); 105 if (MethodLoc.isInvalid()) 106 MethodLoc = D->getLocation(); 107 108 SourceLocation AttrLoc; 109 110 // check for (getter=/setter=) 111 if (AssociatedProp) { 112 bool isGetter = !D->param_size(); 113 AttrLoc = isGetter ? 114 AssociatedProp->getGetterNameLoc(): 115 AssociatedProp->getSetterNameLoc(); 116 } 117 118 SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic; 119 if (D->isImplicit()) { 120 if (AttrLoc.isValid()) { 121 MethodLoc = AttrLoc; 122 } else { 123 Roles |= (SymbolRoleSet)SymbolRole::Implicit; 124 } 125 } else if (AttrLoc.isValid()) { 126 IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()), 127 D->getDeclContext(), 0); 128 } 129 130 TRY_DECL(D, IndexCtx.handleDecl(D, MethodLoc, Roles, Relations)); 131 IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D); 132 bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>(); 133 for (const auto *I : D->parameters()) { 134 handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst); 135 hasIBActionAndFirst = false; 136 } 137 138 if (D->isThisDeclarationADefinition()) { 139 const Stmt *Body = D->getBody(); 140 if (Body) { 141 IndexCtx.indexBody(Body, D, D); 142 } 143 } 144 return true; 145 } 146 147 /// Gather the declarations which the given declaration \D overrides in a 148 /// pseudo-override manner. 149 /// 150 /// Pseudo-overrides occur when a class template specialization declares 151 /// a declaration that has the same name as a similar declaration in the 152 /// non-specialized template. 153 void 154 gatherTemplatePseudoOverrides(const NamedDecl *D, 155 SmallVectorImpl<SymbolRelation> &Relations) { 156 if (!IndexCtx.getLangOpts().CPlusPlus) 157 return; 158 const auto *CTSD = 159 dyn_cast<ClassTemplateSpecializationDecl>(D->getLexicalDeclContext()); 160 if (!CTSD) 161 return; 162 llvm::PointerUnion<ClassTemplateDecl *, 163 ClassTemplatePartialSpecializationDecl *> 164 Template = CTSD->getSpecializedTemplateOrPartial(); 165 if (const auto *CTD = Template.dyn_cast<ClassTemplateDecl *>()) { 166 const CXXRecordDecl *Pattern = CTD->getTemplatedDecl(); 167 bool TypeOverride = isa<TypeDecl>(D); 168 for (const NamedDecl *ND : Pattern->lookup(D->getDeclName())) { 169 if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND)) 170 ND = CTD->getTemplatedDecl(); 171 if (ND->isImplicit()) 172 continue; 173 // Types can override other types. 174 if (!TypeOverride) { 175 if (ND->getKind() != D->getKind()) 176 continue; 177 } else if (!isa<TypeDecl>(ND)) 178 continue; 179 if (const auto *FD = dyn_cast<FunctionDecl>(ND)) { 180 const auto *DFD = cast<FunctionDecl>(D); 181 // Function overrides are approximated using the number of parameters. 182 if (FD->getStorageClass() != DFD->getStorageClass() || 183 FD->getNumParams() != DFD->getNumParams()) 184 continue; 185 } 186 Relations.emplace_back( 187 SymbolRoleSet(SymbolRole::RelationOverrideOf) | 188 SymbolRoleSet(SymbolRole::RelationSpecializationOf), 189 ND); 190 } 191 } 192 } 193 194 bool VisitFunctionDecl(const FunctionDecl *D) { 195 if (D->isDeleted()) 196 return true; 197 198 SymbolRoleSet Roles{}; 199 SmallVector<SymbolRelation, 4> Relations; 200 if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) { 201 if (CXXMD->isVirtual()) 202 Roles |= (unsigned)SymbolRole::Dynamic; 203 for (auto I = CXXMD->begin_overridden_methods(), 204 E = CXXMD->end_overridden_methods(); I != E; ++I) { 205 Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, *I); 206 } 207 } 208 gatherTemplatePseudoOverrides(D, Relations); 209 if (const auto *Base = D->getPrimaryTemplate()) 210 Relations.push_back( 211 SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf), 212 Base->getTemplatedDecl())); 213 214 TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations)); 215 handleDeclarator(D); 216 217 if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { 218 IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(), 219 Ctor->getParent(), Ctor->getDeclContext()); 220 221 // Constructor initializers. 222 for (const auto *Init : Ctor->inits()) { 223 if (Init->isWritten()) { 224 IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D); 225 if (const FieldDecl *Member = Init->getAnyMember()) 226 IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D, 227 (unsigned)SymbolRole::Write); 228 IndexCtx.indexBody(Init->getInit(), D, D); 229 } 230 } 231 } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) { 232 if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) { 233 IndexCtx.handleReference(Dtor->getParent(), 234 TypeNameInfo->getTypeLoc().getLocStart(), 235 Dtor->getParent(), Dtor->getDeclContext()); 236 } 237 } 238 239 if (D->isThisDeclarationADefinition()) { 240 const Stmt *Body = D->getBody(); 241 if (Body) { 242 IndexCtx.indexBody(Body, D, D); 243 } 244 } 245 return true; 246 } 247 248 bool VisitVarDecl(const VarDecl *D) { 249 SmallVector<SymbolRelation, 4> Relations; 250 gatherTemplatePseudoOverrides(D, Relations); 251 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); 252 handleDeclarator(D); 253 IndexCtx.indexBody(D->getInit(), D); 254 return true; 255 } 256 257 bool VisitFieldDecl(const FieldDecl *D) { 258 SmallVector<SymbolRelation, 4> Relations; 259 gatherTemplatePseudoOverrides(D, Relations); 260 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); 261 handleDeclarator(D); 262 if (D->isBitField()) 263 IndexCtx.indexBody(D->getBitWidth(), D); 264 else if (D->hasInClassInitializer()) 265 IndexCtx.indexBody(D->getInClassInitializer(), D); 266 return true; 267 } 268 269 bool VisitObjCIvarDecl(const ObjCIvarDecl *D) { 270 if (D->getSynthesize()) { 271 // handled in VisitObjCPropertyImplDecl 272 return true; 273 } 274 TRY_DECL(D, IndexCtx.handleDecl(D)); 275 handleDeclarator(D); 276 return true; 277 } 278 279 bool VisitMSPropertyDecl(const MSPropertyDecl *D) { 280 handleDeclarator(D); 281 return true; 282 } 283 284 bool VisitEnumConstantDecl(const EnumConstantDecl *D) { 285 TRY_DECL(D, IndexCtx.handleDecl(D)); 286 IndexCtx.indexBody(D->getInitExpr(), D); 287 return true; 288 } 289 290 bool VisitTypedefNameDecl(const TypedefNameDecl *D) { 291 if (!D->isTransparentTag()) { 292 SmallVector<SymbolRelation, 4> Relations; 293 gatherTemplatePseudoOverrides(D, Relations); 294 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); 295 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 296 } 297 return true; 298 } 299 300 bool VisitTagDecl(const TagDecl *D) { 301 // Non-free standing tags are handled in indexTypeSourceInfo. 302 if (D->isFreeStanding()) { 303 if (D->isThisDeclarationADefinition()) { 304 SmallVector<SymbolRelation, 4> Relations; 305 gatherTemplatePseudoOverrides(D, Relations); 306 IndexCtx.indexTagDecl(D, Relations); 307 } else { 308 auto *Parent = dyn_cast<NamedDecl>(D->getDeclContext()); 309 return IndexCtx.handleReference(D, D->getLocation(), Parent, 310 D->getLexicalDeclContext(), 311 SymbolRoleSet()); 312 } 313 } 314 return true; 315 } 316 317 bool handleReferencedProtocols(const ObjCProtocolList &ProtList, 318 const ObjCContainerDecl *ContD, 319 SourceLocation SuperLoc) { 320 ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin(); 321 for (ObjCInterfaceDecl::protocol_iterator 322 I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) { 323 SourceLocation Loc = *LI; 324 ObjCProtocolDecl *PD = *I; 325 SymbolRoleSet roles{}; 326 if (Loc == SuperLoc) 327 roles |= (SymbolRoleSet)SymbolRole::Implicit; 328 TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles, 329 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD})); 330 } 331 return true; 332 } 333 334 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { 335 if (D->isThisDeclarationADefinition()) { 336 TRY_DECL(D, IndexCtx.handleDecl(D)); 337 SourceLocation SuperLoc = D->getSuperClassLoc(); 338 if (auto *SuperD = D->getSuperClass()) { 339 bool hasSuperTypedef = false; 340 if (auto *TInfo = D->getSuperClassTInfo()) { 341 if (auto *TT = TInfo->getType()->getAs<TypedefType>()) { 342 if (auto *TD = TT->getDecl()) { 343 hasSuperTypedef = true; 344 TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D, 345 SymbolRoleSet())); 346 } 347 } 348 } 349 SymbolRoleSet superRoles{}; 350 if (hasSuperTypedef) 351 superRoles |= (SymbolRoleSet)SymbolRole::Implicit; 352 TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles, 353 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D})); 354 } 355 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, 356 SuperLoc)); 357 TRY_TO(IndexCtx.indexDeclContext(D)); 358 } else { 359 return IndexCtx.handleReference(D, D->getLocation(), nullptr, 360 D->getDeclContext(), SymbolRoleSet()); 361 } 362 return true; 363 } 364 365 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { 366 if (D->isThisDeclarationADefinition()) { 367 TRY_DECL(D, IndexCtx.handleDecl(D)); 368 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, 369 /*superLoc=*/SourceLocation())); 370 TRY_TO(IndexCtx.indexDeclContext(D)); 371 } else { 372 return IndexCtx.handleReference(D, D->getLocation(), nullptr, 373 D->getDeclContext(), SymbolRoleSet()); 374 } 375 return true; 376 } 377 378 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { 379 const ObjCInterfaceDecl *Class = D->getClassInterface(); 380 if (!Class) 381 return true; 382 383 if (Class->isImplicitInterfaceDecl()) 384 IndexCtx.handleDecl(Class); 385 386 TRY_DECL(D, IndexCtx.handleDecl(D)); 387 388 // Visit implicit @synthesize property implementations first as their 389 // location is reported at the name of the @implementation block. This 390 // serves no purpose other than to simplify the FileCheck-based tests. 391 for (const auto *I : D->property_impls()) { 392 if (I->getLocation().isInvalid()) 393 IndexCtx.indexDecl(I); 394 } 395 for (const auto *I : D->decls()) { 396 if (!isa<ObjCPropertyImplDecl>(I) || 397 cast<ObjCPropertyImplDecl>(I)->getLocation().isValid()) 398 IndexCtx.indexDecl(I); 399 } 400 401 return true; 402 } 403 404 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { 405 if (!IndexCtx.shouldIndex(D)) 406 return true; 407 const ObjCInterfaceDecl *C = D->getClassInterface(); 408 if (!C) 409 return true; 410 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(), 411 SymbolRelation{ 412 (unsigned)SymbolRole::RelationExtendedBy, D 413 })); 414 SourceLocation CategoryLoc = D->getCategoryNameLoc(); 415 if (!CategoryLoc.isValid()) 416 CategoryLoc = D->getLocation(); 417 TRY_TO(IndexCtx.handleDecl(D, CategoryLoc)); 418 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, 419 /*superLoc=*/SourceLocation())); 420 TRY_TO(IndexCtx.indexDeclContext(D)); 421 return true; 422 } 423 424 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { 425 const ObjCCategoryDecl *Cat = D->getCategoryDecl(); 426 if (!Cat) 427 return true; 428 const ObjCInterfaceDecl *C = D->getClassInterface(); 429 if (C) 430 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, 431 SymbolRoleSet())); 432 SourceLocation CategoryLoc = D->getCategoryNameLoc(); 433 if (!CategoryLoc.isValid()) 434 CategoryLoc = D->getLocation(); 435 TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc)); 436 IndexCtx.indexDeclContext(D); 437 return true; 438 } 439 440 bool VisitObjCMethodDecl(const ObjCMethodDecl *D) { 441 // Methods associated with a property, even user-declared ones, are 442 // handled when we handle the property. 443 if (D->isPropertyAccessor()) 444 return true; 445 446 handleObjCMethod(D); 447 return true; 448 } 449 450 bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { 451 if (ObjCMethodDecl *MD = D->getGetterMethodDecl()) 452 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) 453 handleObjCMethod(MD, D); 454 if (ObjCMethodDecl *MD = D->getSetterMethodDecl()) 455 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) 456 handleObjCMethod(MD, D); 457 TRY_DECL(D, IndexCtx.handleDecl(D)); 458 if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>()) 459 IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D, 460 D->getLexicalDeclContext(), false, true); 461 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 462 return true; 463 } 464 465 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { 466 ObjCPropertyDecl *PD = D->getPropertyDecl(); 467 auto *Container = cast<ObjCImplDecl>(D->getDeclContext()); 468 SourceLocation Loc = D->getLocation(); 469 SymbolRoleSet Roles = 0; 470 SmallVector<SymbolRelation, 1> Relations; 471 472 if (ObjCIvarDecl *ID = D->getPropertyIvarDecl()) 473 Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID}); 474 if (Loc.isInvalid()) { 475 Loc = Container->getLocation(); 476 Roles |= (SymbolRoleSet)SymbolRole::Implicit; 477 } 478 TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations)); 479 480 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 481 return true; 482 483 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); 484 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) { 485 if (MD->isPropertyAccessor() && 486 !hasUserDefined(MD, Container)) 487 IndexCtx.handleDecl(MD, Loc, SymbolRoleSet(SymbolRole::Implicit), {}, 488 Container); 489 } 490 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) { 491 if (MD->isPropertyAccessor() && 492 !hasUserDefined(MD, Container)) 493 IndexCtx.handleDecl(MD, Loc, SymbolRoleSet(SymbolRole::Implicit), {}, 494 Container); 495 } 496 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) { 497 if (IvarD->getSynthesize()) { 498 // For synthesized ivars, use the location of its name in the 499 // corresponding @synthesize. If there isn't one, use the containing 500 // @implementation's location, rather than the property's location, 501 // otherwise the header file containing the @interface will have different 502 // indexing contents based on whether the @implementation was present or 503 // not in the translation unit. 504 SymbolRoleSet IvarRoles = 0; 505 SourceLocation IvarLoc = D->getPropertyIvarDeclLoc(); 506 if (D->getLocation().isInvalid()) { 507 IvarLoc = Container->getLocation(); 508 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit; 509 } else if (D->getLocation() == IvarLoc) { 510 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit; 511 } 512 TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles)); 513 } else { 514 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr, 515 D->getDeclContext(), SymbolRoleSet()); 516 } 517 } 518 return true; 519 } 520 521 bool VisitNamespaceDecl(const NamespaceDecl *D) { 522 TRY_DECL(D, IndexCtx.handleDecl(D)); 523 IndexCtx.indexDeclContext(D); 524 return true; 525 } 526 527 bool VisitUsingDecl(const UsingDecl *D) { 528 const DeclContext *DC = D->getDeclContext()->getRedeclContext(); 529 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); 530 531 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, 532 D->getLexicalDeclContext()); 533 for (const auto *I : D->shadows()) 534 IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent, 535 D->getLexicalDeclContext(), SymbolRoleSet()); 536 return true; 537 } 538 539 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { 540 const DeclContext *DC = D->getDeclContext()->getRedeclContext(); 541 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); 542 543 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, 544 D->getLexicalDeclContext()); 545 return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(), 546 D->getLocation(), Parent, 547 D->getLexicalDeclContext(), 548 SymbolRoleSet()); 549 } 550 551 bool VisitClassTemplateSpecializationDecl(const 552 ClassTemplateSpecializationDecl *D) { 553 // FIXME: Notify subsequent callbacks if info comes from implicit 554 // instantiation. 555 if (D->isThisDeclarationADefinition()) { 556 llvm::PointerUnion<ClassTemplateDecl *, 557 ClassTemplatePartialSpecializationDecl *> 558 Template = D->getSpecializedTemplateOrPartial(); 559 const Decl *SpecializationOf = 560 Template.is<ClassTemplateDecl *>() 561 ? (Decl *)Template.get<ClassTemplateDecl *>() 562 : Template.get<ClassTemplatePartialSpecializationDecl *>(); 563 IndexCtx.indexTagDecl( 564 D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf), 565 SpecializationOf)); 566 } 567 if (TypeSourceInfo *TSI = D->getTypeAsWritten()) 568 IndexCtx.indexTypeSourceInfo(TSI, /*Parent=*/nullptr, 569 D->getLexicalDeclContext()); 570 return true; 571 } 572 573 bool VisitTemplateDecl(const TemplateDecl *D) { 574 // FIXME: Template parameters. 575 return Visit(D->getTemplatedDecl()); 576 } 577 578 bool VisitFriendDecl(const FriendDecl *D) { 579 if (auto ND = D->getFriendDecl()) { 580 // FIXME: Ignore a class template in a dependent context, these are not 581 // linked properly with their redeclarations, ending up with duplicate 582 // USRs. 583 // See comment "Friend templates are visible in fairly strange ways." in 584 // SemaTemplate.cpp which precedes code that prevents the friend template 585 // from becoming visible from the enclosing context. 586 if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext()) 587 return true; 588 return Visit(ND); 589 } 590 if (auto Ty = D->getFriendType()) { 591 IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext())); 592 } 593 return true; 594 } 595 596 bool VisitImportDecl(const ImportDecl *D) { 597 return IndexCtx.importedModule(D); 598 } 599 }; 600 601 } // anonymous namespace 602 603 bool IndexingContext::indexDecl(const Decl *D) { 604 if (D->isImplicit() && shouldIgnoreIfImplicit(D)) 605 return true; 606 607 if (isTemplateImplicitInstantiation(D)) 608 return true; 609 610 IndexingDeclVisitor Visitor(*this); 611 bool ShouldContinue = Visitor.Visit(D); 612 if (!ShouldContinue) 613 return false; 614 615 if (!Visitor.Handled && isa<DeclContext>(D)) 616 return indexDeclContext(cast<DeclContext>(D)); 617 618 return true; 619 } 620 621 bool IndexingContext::indexDeclContext(const DeclContext *DC) { 622 for (const auto *I : DC->decls()) 623 if (!indexDecl(I)) 624 return false; 625 return true; 626 } 627 628 bool IndexingContext::indexTopLevelDecl(const Decl *D) { 629 if (D->getLocation().isInvalid()) 630 return true; 631 632 if (isa<ObjCMethodDecl>(D)) 633 return true; // Wait for the objc container. 634 635 return indexDecl(D); 636 } 637 638 bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) { 639 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) 640 if (!indexTopLevelDecl(*I)) 641 return false; 642 return true; 643 } 644