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 /// Returns true if the given method has been defined explicitly by the 46 /// user. 47 static bool hasUserDefined(const ObjCMethodDecl *D, 48 const ObjCImplDecl *Container) { 49 const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(), 50 D->isInstanceMethod()); 51 return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition(); 52 } 53 54 void handleTemplateArgumentLoc(const TemplateArgumentLoc &TALoc, 55 const NamedDecl *Parent, 56 const DeclContext *DC) { 57 const TemplateArgumentLocInfo &LocInfo = TALoc.getLocInfo(); 58 switch (TALoc.getArgument().getKind()) { 59 case TemplateArgument::Expression: 60 IndexCtx.indexBody(LocInfo.getAsExpr(), Parent, DC); 61 break; 62 case TemplateArgument::Type: 63 IndexCtx.indexTypeSourceInfo(LocInfo.getAsTypeSourceInfo(), Parent, DC); 64 break; 65 case TemplateArgument::Template: 66 case TemplateArgument::TemplateExpansion: 67 IndexCtx.indexNestedNameSpecifierLoc(TALoc.getTemplateQualifierLoc(), 68 Parent, DC); 69 if (const TemplateDecl *TD = TALoc.getArgument() 70 .getAsTemplateOrTemplatePattern() 71 .getAsTemplateDecl()) { 72 if (const NamedDecl *TTD = TD->getTemplatedDecl()) 73 IndexCtx.handleReference(TTD, TALoc.getTemplateNameLoc(), Parent, DC); 74 } 75 break; 76 default: 77 break; 78 } 79 } 80 81 void handleDeclarator(const DeclaratorDecl *D, 82 const NamedDecl *Parent = nullptr, 83 bool isIBType = false) { 84 if (!Parent) Parent = D; 85 86 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent, 87 Parent->getLexicalDeclContext(), 88 /*isBase=*/false, isIBType); 89 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent); 90 if (IndexCtx.shouldIndexFunctionLocalSymbols()) { 91 if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) { 92 auto *DC = Parm->getDeclContext(); 93 if (auto *FD = dyn_cast<FunctionDecl>(DC)) { 94 if (IndexCtx.shouldIndexParametersInDeclarations() || 95 FD->isThisDeclarationADefinition()) 96 IndexCtx.handleDecl(Parm); 97 } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) { 98 if (MD->isThisDeclarationADefinition()) 99 IndexCtx.handleDecl(Parm); 100 } else { 101 IndexCtx.handleDecl(Parm); 102 } 103 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 104 if (IndexCtx.shouldIndexParametersInDeclarations() || 105 FD->isThisDeclarationADefinition()) { 106 for (auto PI : FD->parameters()) { 107 IndexCtx.handleDecl(PI); 108 } 109 } 110 } 111 } else { 112 // Index the default parameter value for function definitions. 113 if (const auto *FD = dyn_cast<FunctionDecl>(D)) { 114 if (FD->isThisDeclarationADefinition()) { 115 for (const auto *PV : FD->parameters()) { 116 if (PV->hasDefaultArg() && !PV->hasUninstantiatedDefaultArg() && 117 !PV->hasUnparsedDefaultArg()) 118 IndexCtx.indexBody(PV->getDefaultArg(), D); 119 } 120 } 121 } 122 } 123 } 124 125 bool handleObjCMethod(const ObjCMethodDecl *D, 126 const ObjCPropertyDecl *AssociatedProp = nullptr) { 127 SmallVector<SymbolRelation, 4> Relations; 128 SmallVector<const ObjCMethodDecl*, 4> Overriden; 129 130 D->getOverriddenMethods(Overriden); 131 for(auto overridden: Overriden) { 132 Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf, 133 overridden); 134 } 135 if (AssociatedProp) 136 Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf, 137 AssociatedProp); 138 139 // getLocation() returns beginning token of a method declaration, but for 140 // indexing purposes we want to point to the base name. 141 SourceLocation MethodLoc = D->getSelectorStartLoc(); 142 if (MethodLoc.isInvalid()) 143 MethodLoc = D->getLocation(); 144 145 SourceLocation AttrLoc; 146 147 // check for (getter=/setter=) 148 if (AssociatedProp) { 149 bool isGetter = !D->param_size(); 150 AttrLoc = isGetter ? 151 AssociatedProp->getGetterNameLoc(): 152 AssociatedProp->getSetterNameLoc(); 153 } 154 155 SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic; 156 if (D->isImplicit()) { 157 if (AttrLoc.isValid()) { 158 MethodLoc = AttrLoc; 159 } else { 160 Roles |= (SymbolRoleSet)SymbolRole::Implicit; 161 } 162 } else if (AttrLoc.isValid()) { 163 IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()), 164 D->getDeclContext(), 0); 165 } 166 167 TRY_DECL(D, IndexCtx.handleDecl(D, MethodLoc, Roles, Relations)); 168 IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D); 169 bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>(); 170 for (const auto *I : D->parameters()) { 171 handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst); 172 hasIBActionAndFirst = false; 173 } 174 175 if (D->isThisDeclarationADefinition()) { 176 const Stmt *Body = D->getBody(); 177 if (Body) { 178 IndexCtx.indexBody(Body, D, D); 179 } 180 } 181 return true; 182 } 183 184 /// Gather the declarations which the given declaration \D overrides in a 185 /// pseudo-override manner. 186 /// 187 /// Pseudo-overrides occur when a class template specialization declares 188 /// a declaration that has the same name as a similar declaration in the 189 /// non-specialized template. 190 void 191 gatherTemplatePseudoOverrides(const NamedDecl *D, 192 SmallVectorImpl<SymbolRelation> &Relations) { 193 if (!IndexCtx.getLangOpts().CPlusPlus) 194 return; 195 const auto *CTSD = 196 dyn_cast<ClassTemplateSpecializationDecl>(D->getLexicalDeclContext()); 197 if (!CTSD) 198 return; 199 llvm::PointerUnion<ClassTemplateDecl *, 200 ClassTemplatePartialSpecializationDecl *> 201 Template = CTSD->getSpecializedTemplateOrPartial(); 202 if (const auto *CTD = Template.dyn_cast<ClassTemplateDecl *>()) { 203 const CXXRecordDecl *Pattern = CTD->getTemplatedDecl(); 204 bool TypeOverride = isa<TypeDecl>(D); 205 for (const NamedDecl *ND : Pattern->lookup(D->getDeclName())) { 206 if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND)) 207 ND = CTD->getTemplatedDecl(); 208 if (ND->isImplicit()) 209 continue; 210 // Types can override other types. 211 if (!TypeOverride) { 212 if (ND->getKind() != D->getKind()) 213 continue; 214 } else if (!isa<TypeDecl>(ND)) 215 continue; 216 if (const auto *FD = dyn_cast<FunctionDecl>(ND)) { 217 const auto *DFD = cast<FunctionDecl>(D); 218 // Function overrides are approximated using the number of parameters. 219 if (FD->getStorageClass() != DFD->getStorageClass() || 220 FD->getNumParams() != DFD->getNumParams()) 221 continue; 222 } 223 Relations.emplace_back( 224 SymbolRoleSet(SymbolRole::RelationSpecializationOf), ND); 225 } 226 } 227 } 228 229 bool VisitFunctionDecl(const FunctionDecl *D) { 230 SymbolRoleSet Roles{}; 231 SmallVector<SymbolRelation, 4> Relations; 232 if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) { 233 if (CXXMD->isVirtual()) 234 Roles |= (unsigned)SymbolRole::Dynamic; 235 for (const CXXMethodDecl *O : CXXMD->overridden_methods()) { 236 Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, O); 237 } 238 } 239 gatherTemplatePseudoOverrides(D, Relations); 240 if (const auto *Base = D->getPrimaryTemplate()) 241 Relations.push_back( 242 SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf), 243 Base->getTemplatedDecl())); 244 245 TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations)); 246 handleDeclarator(D); 247 248 if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { 249 IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(), 250 Ctor->getParent(), Ctor->getDeclContext(), 251 (unsigned)SymbolRole::NameReference); 252 253 // Constructor initializers. 254 for (const auto *Init : Ctor->inits()) { 255 if (Init->isWritten()) { 256 IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D); 257 if (const FieldDecl *Member = Init->getAnyMember()) 258 IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D, 259 (unsigned)SymbolRole::Write); 260 IndexCtx.indexBody(Init->getInit(), D, D); 261 } 262 } 263 } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) { 264 if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) { 265 IndexCtx.handleReference(Dtor->getParent(), 266 TypeNameInfo->getTypeLoc().getBeginLoc(), 267 Dtor->getParent(), Dtor->getDeclContext(), 268 (unsigned)SymbolRole::NameReference); 269 } 270 } else if (const auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) { 271 IndexCtx.handleReference(Guide->getDeducedTemplate()->getTemplatedDecl(), 272 Guide->getLocation(), Guide, 273 Guide->getDeclContext()); 274 } 275 // Template specialization arguments. 276 if (const ASTTemplateArgumentListInfo *TemplateArgInfo = 277 D->getTemplateSpecializationArgsAsWritten()) { 278 for (const auto &Arg : TemplateArgInfo->arguments()) 279 handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext()); 280 } 281 282 if (D->isThisDeclarationADefinition()) { 283 const Stmt *Body = D->getBody(); 284 if (Body) { 285 IndexCtx.indexBody(Body, D, D); 286 } 287 } 288 return true; 289 } 290 291 bool VisitVarDecl(const VarDecl *D) { 292 SmallVector<SymbolRelation, 4> Relations; 293 gatherTemplatePseudoOverrides(D, Relations); 294 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); 295 handleDeclarator(D); 296 IndexCtx.indexBody(D->getInit(), D); 297 return true; 298 } 299 300 bool VisitDecompositionDecl(const DecompositionDecl *D) { 301 for (const auto *Binding : D->bindings()) 302 TRY_DECL(Binding, IndexCtx.handleDecl(Binding)); 303 return Base::VisitDecompositionDecl(D); 304 } 305 306 bool VisitFieldDecl(const FieldDecl *D) { 307 SmallVector<SymbolRelation, 4> Relations; 308 gatherTemplatePseudoOverrides(D, Relations); 309 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); 310 handleDeclarator(D); 311 if (D->isBitField()) 312 IndexCtx.indexBody(D->getBitWidth(), D); 313 else if (D->hasInClassInitializer()) 314 IndexCtx.indexBody(D->getInClassInitializer(), D); 315 return true; 316 } 317 318 bool VisitObjCIvarDecl(const ObjCIvarDecl *D) { 319 if (D->getSynthesize()) { 320 // handled in VisitObjCPropertyImplDecl 321 return true; 322 } 323 TRY_DECL(D, IndexCtx.handleDecl(D)); 324 handleDeclarator(D); 325 return true; 326 } 327 328 bool VisitMSPropertyDecl(const MSPropertyDecl *D) { 329 TRY_DECL(D, IndexCtx.handleDecl(D)); 330 handleDeclarator(D); 331 return true; 332 } 333 334 bool VisitEnumConstantDecl(const EnumConstantDecl *D) { 335 TRY_DECL(D, IndexCtx.handleDecl(D)); 336 IndexCtx.indexBody(D->getInitExpr(), D); 337 return true; 338 } 339 340 bool VisitTypedefNameDecl(const TypedefNameDecl *D) { 341 if (!D->isTransparentTag()) { 342 SmallVector<SymbolRelation, 4> Relations; 343 gatherTemplatePseudoOverrides(D, Relations); 344 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); 345 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 346 } 347 return true; 348 } 349 350 bool VisitTagDecl(const TagDecl *D) { 351 // Non-free standing tags are handled in indexTypeSourceInfo. 352 if (D->isFreeStanding()) { 353 if (D->isThisDeclarationADefinition()) { 354 SmallVector<SymbolRelation, 4> Relations; 355 gatherTemplatePseudoOverrides(D, Relations); 356 IndexCtx.indexTagDecl(D, Relations); 357 } else { 358 SmallVector<SymbolRelation, 1> Relations; 359 gatherTemplatePseudoOverrides(D, Relations); 360 return IndexCtx.handleDecl(D, D->getLocation(), SymbolRoleSet(), 361 Relations, D->getLexicalDeclContext()); 362 } 363 } 364 return true; 365 } 366 367 bool handleReferencedProtocols(const ObjCProtocolList &ProtList, 368 const ObjCContainerDecl *ContD, 369 SourceLocation SuperLoc) { 370 ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin(); 371 for (ObjCInterfaceDecl::protocol_iterator 372 I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) { 373 SourceLocation Loc = *LI; 374 ObjCProtocolDecl *PD = *I; 375 SymbolRoleSet roles{}; 376 if (Loc == SuperLoc) 377 roles |= (SymbolRoleSet)SymbolRole::Implicit; 378 TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles, 379 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD})); 380 } 381 return true; 382 } 383 384 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { 385 if (D->isThisDeclarationADefinition()) { 386 TRY_DECL(D, IndexCtx.handleDecl(D)); 387 SourceLocation SuperLoc = D->getSuperClassLoc(); 388 if (auto *SuperD = D->getSuperClass()) { 389 bool hasSuperTypedef = false; 390 if (auto *TInfo = D->getSuperClassTInfo()) { 391 if (auto *TT = TInfo->getType()->getAs<TypedefType>()) { 392 if (auto *TD = TT->getDecl()) { 393 hasSuperTypedef = true; 394 TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D, 395 SymbolRoleSet())); 396 } 397 } 398 } 399 SymbolRoleSet superRoles{}; 400 if (hasSuperTypedef) 401 superRoles |= (SymbolRoleSet)SymbolRole::Implicit; 402 TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles, 403 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D})); 404 } 405 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, 406 SuperLoc)); 407 TRY_TO(IndexCtx.indexDeclContext(D)); 408 } else { 409 return IndexCtx.handleReference(D, D->getLocation(), nullptr, 410 D->getDeclContext(), SymbolRoleSet()); 411 } 412 return true; 413 } 414 415 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { 416 if (D->isThisDeclarationADefinition()) { 417 TRY_DECL(D, IndexCtx.handleDecl(D)); 418 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, 419 /*SuperLoc=*/SourceLocation())); 420 TRY_TO(IndexCtx.indexDeclContext(D)); 421 } else { 422 return IndexCtx.handleReference(D, D->getLocation(), nullptr, 423 D->getDeclContext(), SymbolRoleSet()); 424 } 425 return true; 426 } 427 428 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { 429 const ObjCInterfaceDecl *Class = D->getClassInterface(); 430 if (!Class) 431 return true; 432 433 if (Class->isImplicitInterfaceDecl()) 434 IndexCtx.handleDecl(Class); 435 436 TRY_DECL(D, IndexCtx.handleDecl(D)); 437 438 // Visit implicit @synthesize property implementations first as their 439 // location is reported at the name of the @implementation block. This 440 // serves no purpose other than to simplify the FileCheck-based tests. 441 for (const auto *I : D->property_impls()) { 442 if (I->getLocation().isInvalid()) 443 IndexCtx.indexDecl(I); 444 } 445 for (const auto *I : D->decls()) { 446 if (!isa<ObjCPropertyImplDecl>(I) || 447 cast<ObjCPropertyImplDecl>(I)->getLocation().isValid()) 448 IndexCtx.indexDecl(I); 449 } 450 451 return true; 452 } 453 454 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { 455 if (!IndexCtx.shouldIndex(D)) 456 return true; 457 const ObjCInterfaceDecl *C = D->getClassInterface(); 458 if (!C) 459 return true; 460 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(), 461 SymbolRelation{ 462 (unsigned)SymbolRole::RelationExtendedBy, D 463 })); 464 SourceLocation CategoryLoc = D->getCategoryNameLoc(); 465 if (!CategoryLoc.isValid()) 466 CategoryLoc = D->getLocation(); 467 TRY_TO(IndexCtx.handleDecl(D, CategoryLoc)); 468 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, 469 /*SuperLoc=*/SourceLocation())); 470 TRY_TO(IndexCtx.indexDeclContext(D)); 471 return true; 472 } 473 474 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { 475 const ObjCCategoryDecl *Cat = D->getCategoryDecl(); 476 if (!Cat) 477 return true; 478 const ObjCInterfaceDecl *C = D->getClassInterface(); 479 if (C) 480 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, 481 SymbolRoleSet())); 482 SourceLocation CategoryLoc = D->getCategoryNameLoc(); 483 if (!CategoryLoc.isValid()) 484 CategoryLoc = D->getLocation(); 485 TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc)); 486 IndexCtx.indexDeclContext(D); 487 return true; 488 } 489 490 bool VisitObjCMethodDecl(const ObjCMethodDecl *D) { 491 // Methods associated with a property, even user-declared ones, are 492 // handled when we handle the property. 493 if (D->isPropertyAccessor()) 494 return true; 495 496 handleObjCMethod(D); 497 return true; 498 } 499 500 bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { 501 if (ObjCMethodDecl *MD = D->getGetterMethodDecl()) 502 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) 503 handleObjCMethod(MD, D); 504 if (ObjCMethodDecl *MD = D->getSetterMethodDecl()) 505 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) 506 handleObjCMethod(MD, D); 507 TRY_DECL(D, IndexCtx.handleDecl(D)); 508 if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>()) 509 IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D, 510 D->getLexicalDeclContext(), false, true); 511 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 512 return true; 513 } 514 515 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { 516 ObjCPropertyDecl *PD = D->getPropertyDecl(); 517 auto *Container = cast<ObjCImplDecl>(D->getDeclContext()); 518 SourceLocation Loc = D->getLocation(); 519 SymbolRoleSet Roles = 0; 520 SmallVector<SymbolRelation, 1> Relations; 521 522 if (ObjCIvarDecl *ID = D->getPropertyIvarDecl()) 523 Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID}); 524 if (Loc.isInvalid()) { 525 Loc = Container->getLocation(); 526 Roles |= (SymbolRoleSet)SymbolRole::Implicit; 527 } 528 TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations)); 529 530 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 531 return true; 532 533 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); 534 SymbolRoleSet AccessorMethodRoles = 535 SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit); 536 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) { 537 if (MD->isPropertyAccessor() && 538 !hasUserDefined(MD, Container)) 539 IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container); 540 } 541 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) { 542 if (MD->isPropertyAccessor() && 543 !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