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