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