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 252 // Constructor initializers. 253 for (const auto *Init : Ctor->inits()) { 254 if (Init->isWritten()) { 255 IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D); 256 if (const FieldDecl *Member = Init->getAnyMember()) 257 IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D, 258 (unsigned)SymbolRole::Write); 259 IndexCtx.indexBody(Init->getInit(), D, D); 260 } 261 } 262 } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) { 263 if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) { 264 IndexCtx.handleReference(Dtor->getParent(), 265 TypeNameInfo->getTypeLoc().getBeginLoc(), 266 Dtor->getParent(), Dtor->getDeclContext()); 267 } 268 } else if (const auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) { 269 IndexCtx.handleReference(Guide->getDeducedTemplate()->getTemplatedDecl(), 270 Guide->getLocation(), Guide, 271 Guide->getDeclContext()); 272 } 273 // Template specialization arguments. 274 if (const ASTTemplateArgumentListInfo *TemplateArgInfo = 275 D->getTemplateSpecializationArgsAsWritten()) { 276 for (const auto &Arg : TemplateArgInfo->arguments()) 277 handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext()); 278 } 279 280 if (D->isThisDeclarationADefinition()) { 281 const Stmt *Body = D->getBody(); 282 if (Body) { 283 IndexCtx.indexBody(Body, D, D); 284 } 285 } 286 return true; 287 } 288 289 bool VisitVarDecl(const VarDecl *D) { 290 SmallVector<SymbolRelation, 4> Relations; 291 gatherTemplatePseudoOverrides(D, Relations); 292 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); 293 handleDeclarator(D); 294 IndexCtx.indexBody(D->getInit(), D); 295 return true; 296 } 297 298 bool VisitDecompositionDecl(const DecompositionDecl *D) { 299 for (const auto *Binding : D->bindings()) 300 TRY_DECL(Binding, IndexCtx.handleDecl(Binding)); 301 return Base::VisitDecompositionDecl(D); 302 } 303 304 bool VisitFieldDecl(const FieldDecl *D) { 305 SmallVector<SymbolRelation, 4> Relations; 306 gatherTemplatePseudoOverrides(D, Relations); 307 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); 308 handleDeclarator(D); 309 if (D->isBitField()) 310 IndexCtx.indexBody(D->getBitWidth(), D); 311 else if (D->hasInClassInitializer()) 312 IndexCtx.indexBody(D->getInClassInitializer(), D); 313 return true; 314 } 315 316 bool VisitObjCIvarDecl(const ObjCIvarDecl *D) { 317 if (D->getSynthesize()) { 318 // handled in VisitObjCPropertyImplDecl 319 return true; 320 } 321 TRY_DECL(D, IndexCtx.handleDecl(D)); 322 handleDeclarator(D); 323 return true; 324 } 325 326 bool VisitMSPropertyDecl(const MSPropertyDecl *D) { 327 TRY_DECL(D, IndexCtx.handleDecl(D)); 328 handleDeclarator(D); 329 return true; 330 } 331 332 bool VisitEnumConstantDecl(const EnumConstantDecl *D) { 333 TRY_DECL(D, IndexCtx.handleDecl(D)); 334 IndexCtx.indexBody(D->getInitExpr(), D); 335 return true; 336 } 337 338 bool VisitTypedefNameDecl(const TypedefNameDecl *D) { 339 if (!D->isTransparentTag()) { 340 SmallVector<SymbolRelation, 4> Relations; 341 gatherTemplatePseudoOverrides(D, Relations); 342 TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations)); 343 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 344 } 345 return true; 346 } 347 348 bool VisitTagDecl(const TagDecl *D) { 349 // Non-free standing tags are handled in indexTypeSourceInfo. 350 if (D->isFreeStanding()) { 351 if (D->isThisDeclarationADefinition()) { 352 SmallVector<SymbolRelation, 4> Relations; 353 gatherTemplatePseudoOverrides(D, Relations); 354 IndexCtx.indexTagDecl(D, Relations); 355 } else { 356 SmallVector<SymbolRelation, 1> Relations; 357 gatherTemplatePseudoOverrides(D, Relations); 358 return IndexCtx.handleDecl(D, D->getLocation(), SymbolRoleSet(), 359 Relations, D->getLexicalDeclContext()); 360 } 361 } 362 return true; 363 } 364 365 bool handleReferencedProtocols(const ObjCProtocolList &ProtList, 366 const ObjCContainerDecl *ContD, 367 SourceLocation SuperLoc) { 368 ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin(); 369 for (ObjCInterfaceDecl::protocol_iterator 370 I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) { 371 SourceLocation Loc = *LI; 372 ObjCProtocolDecl *PD = *I; 373 SymbolRoleSet roles{}; 374 if (Loc == SuperLoc) 375 roles |= (SymbolRoleSet)SymbolRole::Implicit; 376 TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles, 377 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD})); 378 } 379 return true; 380 } 381 382 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { 383 if (D->isThisDeclarationADefinition()) { 384 TRY_DECL(D, IndexCtx.handleDecl(D)); 385 SourceLocation SuperLoc = D->getSuperClassLoc(); 386 if (auto *SuperD = D->getSuperClass()) { 387 bool hasSuperTypedef = false; 388 if (auto *TInfo = D->getSuperClassTInfo()) { 389 if (auto *TT = TInfo->getType()->getAs<TypedefType>()) { 390 if (auto *TD = TT->getDecl()) { 391 hasSuperTypedef = true; 392 TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D, 393 SymbolRoleSet())); 394 } 395 } 396 } 397 SymbolRoleSet superRoles{}; 398 if (hasSuperTypedef) 399 superRoles |= (SymbolRoleSet)SymbolRole::Implicit; 400 TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles, 401 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D})); 402 } 403 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, 404 SuperLoc)); 405 TRY_TO(IndexCtx.indexDeclContext(D)); 406 } else { 407 return IndexCtx.handleReference(D, D->getLocation(), nullptr, 408 D->getDeclContext(), SymbolRoleSet()); 409 } 410 return true; 411 } 412 413 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { 414 if (D->isThisDeclarationADefinition()) { 415 TRY_DECL(D, IndexCtx.handleDecl(D)); 416 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, 417 /*superLoc=*/SourceLocation())); 418 TRY_TO(IndexCtx.indexDeclContext(D)); 419 } else { 420 return IndexCtx.handleReference(D, D->getLocation(), nullptr, 421 D->getDeclContext(), SymbolRoleSet()); 422 } 423 return true; 424 } 425 426 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { 427 const ObjCInterfaceDecl *Class = D->getClassInterface(); 428 if (!Class) 429 return true; 430 431 if (Class->isImplicitInterfaceDecl()) 432 IndexCtx.handleDecl(Class); 433 434 TRY_DECL(D, IndexCtx.handleDecl(D)); 435 436 // Visit implicit @synthesize property implementations first as their 437 // location is reported at the name of the @implementation block. This 438 // serves no purpose other than to simplify the FileCheck-based tests. 439 for (const auto *I : D->property_impls()) { 440 if (I->getLocation().isInvalid()) 441 IndexCtx.indexDecl(I); 442 } 443 for (const auto *I : D->decls()) { 444 if (!isa<ObjCPropertyImplDecl>(I) || 445 cast<ObjCPropertyImplDecl>(I)->getLocation().isValid()) 446 IndexCtx.indexDecl(I); 447 } 448 449 return true; 450 } 451 452 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { 453 if (!IndexCtx.shouldIndex(D)) 454 return true; 455 const ObjCInterfaceDecl *C = D->getClassInterface(); 456 if (!C) 457 return true; 458 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(), 459 SymbolRelation{ 460 (unsigned)SymbolRole::RelationExtendedBy, D 461 })); 462 SourceLocation CategoryLoc = D->getCategoryNameLoc(); 463 if (!CategoryLoc.isValid()) 464 CategoryLoc = D->getLocation(); 465 TRY_TO(IndexCtx.handleDecl(D, CategoryLoc)); 466 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D, 467 /*superLoc=*/SourceLocation())); 468 TRY_TO(IndexCtx.indexDeclContext(D)); 469 return true; 470 } 471 472 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { 473 const ObjCCategoryDecl *Cat = D->getCategoryDecl(); 474 if (!Cat) 475 return true; 476 const ObjCInterfaceDecl *C = D->getClassInterface(); 477 if (C) 478 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, 479 SymbolRoleSet())); 480 SourceLocation CategoryLoc = D->getCategoryNameLoc(); 481 if (!CategoryLoc.isValid()) 482 CategoryLoc = D->getLocation(); 483 TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc)); 484 IndexCtx.indexDeclContext(D); 485 return true; 486 } 487 488 bool VisitObjCMethodDecl(const ObjCMethodDecl *D) { 489 // Methods associated with a property, even user-declared ones, are 490 // handled when we handle the property. 491 if (D->isPropertyAccessor()) 492 return true; 493 494 handleObjCMethod(D); 495 return true; 496 } 497 498 bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { 499 if (ObjCMethodDecl *MD = D->getGetterMethodDecl()) 500 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) 501 handleObjCMethod(MD, D); 502 if (ObjCMethodDecl *MD = D->getSetterMethodDecl()) 503 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) 504 handleObjCMethod(MD, D); 505 TRY_DECL(D, IndexCtx.handleDecl(D)); 506 if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>()) 507 IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D, 508 D->getLexicalDeclContext(), false, true); 509 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 510 return true; 511 } 512 513 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { 514 ObjCPropertyDecl *PD = D->getPropertyDecl(); 515 auto *Container = cast<ObjCImplDecl>(D->getDeclContext()); 516 SourceLocation Loc = D->getLocation(); 517 SymbolRoleSet Roles = 0; 518 SmallVector<SymbolRelation, 1> Relations; 519 520 if (ObjCIvarDecl *ID = D->getPropertyIvarDecl()) 521 Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID}); 522 if (Loc.isInvalid()) { 523 Loc = Container->getLocation(); 524 Roles |= (SymbolRoleSet)SymbolRole::Implicit; 525 } 526 TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations)); 527 528 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 529 return true; 530 531 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); 532 SymbolRoleSet AccessorMethodRoles = 533 SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit); 534 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) { 535 if (MD->isPropertyAccessor() && 536 !hasUserDefined(MD, Container)) 537 IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container); 538 } 539 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) { 540 if (MD->isPropertyAccessor() && 541 !hasUserDefined(MD, Container)) 542 IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container); 543 } 544 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) { 545 if (IvarD->getSynthesize()) { 546 // For synthesized ivars, use the location of its name in the 547 // corresponding @synthesize. If there isn't one, use the containing 548 // @implementation's location, rather than the property's location, 549 // otherwise the header file containing the @interface will have different 550 // indexing contents based on whether the @implementation was present or 551 // not in the translation unit. 552 SymbolRoleSet IvarRoles = 0; 553 SourceLocation IvarLoc = D->getPropertyIvarDeclLoc(); 554 if (D->getLocation().isInvalid()) { 555 IvarLoc = Container->getLocation(); 556 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit; 557 } else if (D->getLocation() == IvarLoc) { 558 IvarRoles = (SymbolRoleSet)SymbolRole::Implicit; 559 } 560 TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles)); 561 } else { 562 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr, 563 D->getDeclContext(), SymbolRoleSet()); 564 } 565 } 566 return true; 567 } 568 569 bool VisitNamespaceDecl(const NamespaceDecl *D) { 570 TRY_DECL(D, IndexCtx.handleDecl(D)); 571 IndexCtx.indexDeclContext(D); 572 return true; 573 } 574 575 bool VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { 576 TRY_DECL(D, IndexCtx.handleDecl(D)); 577 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); 578 IndexCtx.handleReference(D->getAliasedNamespace(), D->getTargetNameLoc(), D, 579 D->getLexicalDeclContext()); 580 return true; 581 } 582 583 bool VisitUsingDecl(const UsingDecl *D) { 584 IndexCtx.handleDecl(D); 585 586 const DeclContext *DC = D->getDeclContext()->getRedeclContext(); 587 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); 588 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, 589 D->getLexicalDeclContext()); 590 for (const auto *I : D->shadows()) 591 IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent, 592 D->getLexicalDeclContext(), SymbolRoleSet()); 593 return true; 594 } 595 596 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { 597 const DeclContext *DC = D->getDeclContext()->getRedeclContext(); 598 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); 599 600 // NNS for the local 'using namespace' directives is visited by the body 601 // visitor. 602 if (!D->getParentFunctionOrMethod()) 603 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, 604 D->getLexicalDeclContext()); 605 606 return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(), 607 D->getLocation(), Parent, 608 D->getLexicalDeclContext(), 609 SymbolRoleSet()); 610 } 611 612 bool VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) { 613 TRY_DECL(D, IndexCtx.handleDecl(D)); 614 const DeclContext *DC = D->getDeclContext()->getRedeclContext(); 615 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); 616 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, 617 D->getLexicalDeclContext()); 618 return true; 619 } 620 621 bool VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) { 622 TRY_DECL(D, IndexCtx.handleDecl(D)); 623 const DeclContext *DC = D->getDeclContext()->getRedeclContext(); 624 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); 625 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, 626 D->getLexicalDeclContext()); 627 return true; 628 } 629 630 bool VisitClassTemplateSpecializationDecl(const 631 ClassTemplateSpecializationDecl *D) { 632 // FIXME: Notify subsequent callbacks if info comes from implicit 633 // instantiation. 634 llvm::PointerUnion<ClassTemplateDecl *, 635 ClassTemplatePartialSpecializationDecl *> 636 Template = D->getSpecializedTemplateOrPartial(); 637 const Decl *SpecializationOf = 638 Template.is<ClassTemplateDecl *>() 639 ? (Decl *)Template.get<ClassTemplateDecl *>() 640 : Template.get<ClassTemplatePartialSpecializationDecl *>(); 641 if (!D->isThisDeclarationADefinition()) 642 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); 643 IndexCtx.indexTagDecl( 644 D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf), 645 SpecializationOf)); 646 if (TypeSourceInfo *TSI = D->getTypeAsWritten()) 647 IndexCtx.indexTypeSourceInfo(TSI, /*Parent=*/nullptr, 648 D->getLexicalDeclContext()); 649 return true; 650 } 651 652 static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl *D) { 653 if (!D) 654 return false; 655 // We want to index the template parameters only once when indexing the 656 // canonical declaration. 657 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 658 return FD->getCanonicalDecl() == FD; 659 else if (const auto *TD = dyn_cast<TagDecl>(D)) 660 return TD->getCanonicalDecl() == TD; 661 else if (const auto *VD = dyn_cast<VarDecl>(D)) 662 return VD->getCanonicalDecl() == VD; 663 return true; 664 } 665 666 bool VisitTemplateDecl(const TemplateDecl *D) { 667 668 const NamedDecl *Parent = D->getTemplatedDecl(); 669 if (!Parent) 670 return true; 671 672 // Index the default values for the template parameters. 673 if (D->getTemplateParameters() && 674 shouldIndexTemplateParameterDefaultValue(Parent)) { 675 const TemplateParameterList *Params = D->getTemplateParameters(); 676 for (const NamedDecl *TP : *Params) { 677 if (IndexCtx.shouldIndexTemplateParameters()) 678 IndexCtx.handleDecl(TP); 679 if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) { 680 if (TTP->hasDefaultArgument()) 681 IndexCtx.indexTypeSourceInfo(TTP->getDefaultArgumentInfo(), Parent); 682 } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) { 683 if (NTTP->hasDefaultArgument()) 684 IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent); 685 } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) { 686 if (TTPD->hasDefaultArgument()) 687 handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent, 688 TP->getLexicalDeclContext()); 689 } 690 } 691 } 692 693 return Visit(Parent); 694 } 695 696 bool VisitFriendDecl(const FriendDecl *D) { 697 if (auto ND = D->getFriendDecl()) { 698 // FIXME: Ignore a class template in a dependent context, these are not 699 // linked properly with their redeclarations, ending up with duplicate 700 // USRs. 701 // See comment "Friend templates are visible in fairly strange ways." in 702 // SemaTemplate.cpp which precedes code that prevents the friend template 703 // from becoming visible from the enclosing context. 704 if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext()) 705 return true; 706 return Visit(ND); 707 } 708 if (auto Ty = D->getFriendType()) { 709 IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext())); 710 } 711 return true; 712 } 713 714 bool VisitImportDecl(const ImportDecl *D) { 715 return IndexCtx.importedModule(D); 716 } 717 718 bool VisitStaticAssertDecl(const StaticAssertDecl *D) { 719 IndexCtx.indexBody(D->getAssertExpr(), 720 dyn_cast<NamedDecl>(D->getDeclContext()), 721 D->getLexicalDeclContext()); 722 return true; 723 } 724 }; 725 726 } // anonymous namespace 727 728 bool IndexingContext::indexDecl(const Decl *D) { 729 if (D->isImplicit() && shouldIgnoreIfImplicit(D)) 730 return true; 731 732 if (isTemplateImplicitInstantiation(D) && !shouldIndexImplicitInstantiation()) 733 return true; 734 735 IndexingDeclVisitor Visitor(*this); 736 bool ShouldContinue = Visitor.Visit(D); 737 if (!ShouldContinue) 738 return false; 739 740 if (!Visitor.Handled && isa<DeclContext>(D)) 741 return indexDeclContext(cast<DeclContext>(D)); 742 743 return true; 744 } 745 746 bool IndexingContext::indexDeclContext(const DeclContext *DC) { 747 for (const auto *I : DC->decls()) 748 if (!indexDecl(I)) 749 return false; 750 return true; 751 } 752 753 bool IndexingContext::indexTopLevelDecl(const Decl *D) { 754 if (D->getLocation().isInvalid()) 755 return true; 756 757 if (isa<ObjCMethodDecl>(D)) 758 return true; // Wait for the objc container. 759 760 return indexDecl(D); 761 } 762 763 bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) { 764 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) 765 if (!indexTopLevelDecl(*I)) 766 return false; 767 return true; 768 } 769