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_TO(CALL_EXPR) \ 18 do { \ 19 if (!CALL_EXPR) \ 20 return false; \ 21 } while (0) 22 23 namespace { 24 25 class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> { 26 IndexingContext &IndexCtx; 27 28 public: 29 explicit IndexingDeclVisitor(IndexingContext &indexCtx) 30 : IndexCtx(indexCtx) { } 31 32 bool Handled = true; 33 34 bool VisitDecl(const Decl *D) { 35 Handled = false; 36 return true; 37 } 38 39 /// \brief Returns true if the given method has been defined explicitly by the 40 /// user. 41 static bool hasUserDefined(const ObjCMethodDecl *D, 42 const ObjCImplDecl *Container) { 43 const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(), 44 D->isInstanceMethod()); 45 return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition(); 46 } 47 48 void handleDeclarator(const DeclaratorDecl *D, 49 const NamedDecl *Parent = nullptr, 50 bool isIBType = false) { 51 if (!Parent) Parent = D; 52 53 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent, 54 Parent->getLexicalDeclContext(), 55 /*isBase=*/false, isIBType); 56 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent); 57 if (IndexCtx.shouldIndexFunctionLocalSymbols()) { 58 // Only index parameters in definitions, parameters in declarations are 59 // not useful. 60 if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) { 61 auto *DC = Parm->getDeclContext(); 62 if (auto *FD = dyn_cast<FunctionDecl>(DC)) { 63 if (FD->isThisDeclarationADefinition()) 64 IndexCtx.handleDecl(Parm); 65 } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) { 66 if (MD->isThisDeclarationADefinition()) 67 IndexCtx.handleDecl(Parm); 68 } else { 69 IndexCtx.handleDecl(Parm); 70 } 71 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 72 if (FD->isThisDeclarationADefinition()) { 73 for (auto PI : FD->parameters()) { 74 IndexCtx.handleDecl(PI); 75 } 76 } 77 } 78 } 79 } 80 81 bool handleObjCMethod(const ObjCMethodDecl *D, 82 const ObjCPropertyDecl *AssociatedProp = nullptr) { 83 SmallVector<SymbolRelation, 4> Relations; 84 SmallVector<const ObjCMethodDecl*, 4> Overriden; 85 86 D->getOverriddenMethods(Overriden); 87 for(auto overridden: Overriden) { 88 Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf, 89 overridden); 90 } 91 if (AssociatedProp) 92 Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf, 93 AssociatedProp); 94 95 if (!IndexCtx.handleDecl(D, (unsigned)SymbolRole::Dynamic, Relations)) 96 return false; 97 IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D); 98 bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>(); 99 for (const auto *I : D->parameters()) { 100 handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst); 101 hasIBActionAndFirst = false; 102 } 103 104 if (D->isThisDeclarationADefinition()) { 105 const Stmt *Body = D->getBody(); 106 if (Body) { 107 IndexCtx.indexBody(Body, D, D); 108 } 109 } 110 return true; 111 } 112 113 bool VisitFunctionDecl(const FunctionDecl *D) { 114 if (D->isDeleted()) 115 return true; 116 117 SymbolRoleSet Roles{}; 118 SmallVector<SymbolRelation, 4> Relations; 119 if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) { 120 if (CXXMD->isVirtual()) 121 Roles |= (unsigned)SymbolRole::Dynamic; 122 for (auto I = CXXMD->begin_overridden_methods(), 123 E = CXXMD->end_overridden_methods(); I != E; ++I) { 124 Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, *I); 125 } 126 } 127 128 if (!IndexCtx.handleDecl(D, Roles, Relations)) 129 return false; 130 handleDeclarator(D); 131 132 if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { 133 // Constructor initializers. 134 for (const auto *Init : Ctor->inits()) { 135 if (Init->isWritten()) { 136 IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D); 137 if (const FieldDecl *Member = Init->getAnyMember()) 138 IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D, 139 (unsigned)SymbolRole::Write); 140 IndexCtx.indexBody(Init->getInit(), D, D); 141 } 142 } 143 } 144 145 if (D->isThisDeclarationADefinition()) { 146 const Stmt *Body = D->getBody(); 147 if (Body) { 148 IndexCtx.indexBody(Body, D, D); 149 } 150 } 151 return true; 152 } 153 154 bool VisitVarDecl(const VarDecl *D) { 155 if (!IndexCtx.handleDecl(D)) 156 return false; 157 handleDeclarator(D); 158 IndexCtx.indexBody(D->getInit(), D); 159 return true; 160 } 161 162 bool VisitFieldDecl(const FieldDecl *D) { 163 if (!IndexCtx.handleDecl(D)) 164 return false; 165 handleDeclarator(D); 166 if (D->isBitField()) 167 IndexCtx.indexBody(D->getBitWidth(), D); 168 else if (D->hasInClassInitializer()) 169 IndexCtx.indexBody(D->getInClassInitializer(), D); 170 return true; 171 } 172 173 bool VisitObjCIvarDecl(const ObjCIvarDecl *D) { 174 if (D->getSynthesize()) { 175 // For synthesized ivars, use the location of the ObjC implementation, 176 // not the location of the property. 177 // Otherwise the header file containing the @interface will have different 178 // indexing contents based on whether the @implementation was present or 179 // not in the translation unit. 180 return IndexCtx.handleDecl(D, 181 cast<Decl>(D->getDeclContext())->getLocation(), 182 (unsigned)SymbolRole::Implicit); 183 } 184 if (!IndexCtx.handleDecl(D)) 185 return false; 186 handleDeclarator(D); 187 return true; 188 } 189 190 bool VisitMSPropertyDecl(const MSPropertyDecl *D) { 191 handleDeclarator(D); 192 return true; 193 } 194 195 bool VisitEnumConstantDecl(const EnumConstantDecl *D) { 196 if (!IndexCtx.handleDecl(D)) 197 return false; 198 IndexCtx.indexBody(D->getInitExpr(), D); 199 return true; 200 } 201 202 bool VisitTypedefNameDecl(const TypedefNameDecl *D) { 203 if (!IndexCtx.handleDecl(D)) 204 return false; 205 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 206 return true; 207 } 208 209 bool VisitTagDecl(const TagDecl *D) { 210 // Non-free standing tags are handled in indexTypeSourceInfo. 211 if (D->isFreeStanding()) { 212 if (D->isThisDeclarationADefinition()) { 213 IndexCtx.indexTagDecl(D); 214 } else { 215 auto *Parent = dyn_cast<NamedDecl>(D->getDeclContext()); 216 return IndexCtx.handleReference(D, D->getLocation(), Parent, 217 D->getLexicalDeclContext(), 218 SymbolRoleSet()); 219 } 220 } 221 return true; 222 } 223 224 bool handleReferencedProtocols(const ObjCProtocolList &ProtList, 225 const ObjCContainerDecl *ContD) { 226 ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin(); 227 for (ObjCInterfaceDecl::protocol_iterator 228 I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) { 229 SourceLocation Loc = *LI; 230 ObjCProtocolDecl *PD = *I; 231 TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, 232 SymbolRoleSet(), 233 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD})); 234 } 235 return true; 236 } 237 238 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { 239 if (D->isThisDeclarationADefinition()) { 240 TRY_TO(IndexCtx.handleDecl(D)); 241 if (auto *SuperD = D->getSuperClass()) { 242 TRY_TO(IndexCtx.handleReference(SuperD, D->getSuperClassLoc(), D, D, 243 SymbolRoleSet(), 244 SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D})); 245 } 246 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D)); 247 TRY_TO(IndexCtx.indexDeclContext(D)); 248 } else { 249 return IndexCtx.handleReference(D, D->getLocation(), nullptr, 250 D->getDeclContext(), SymbolRoleSet()); 251 } 252 return true; 253 } 254 255 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { 256 if (D->isThisDeclarationADefinition()) { 257 TRY_TO(IndexCtx.handleDecl(D)); 258 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D)); 259 TRY_TO(IndexCtx.indexDeclContext(D)); 260 } else { 261 return IndexCtx.handleReference(D, D->getLocation(), nullptr, 262 D->getDeclContext(), SymbolRoleSet()); 263 } 264 return true; 265 } 266 267 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { 268 const ObjCInterfaceDecl *Class = D->getClassInterface(); 269 if (!Class) 270 return true; 271 272 if (Class->isImplicitInterfaceDecl()) 273 IndexCtx.handleDecl(Class); 274 275 if (!IndexCtx.handleDecl(D)) 276 return false; 277 278 // Index the ivars first to make sure the synthesized ivars are indexed 279 // before indexing the methods that can reference them. 280 for (const auto *IvarI : D->ivars()) 281 IndexCtx.indexDecl(IvarI); 282 for (const auto *I : D->decls()) { 283 if (!isa<ObjCIvarDecl>(I)) 284 IndexCtx.indexDecl(I); 285 } 286 287 return true; 288 } 289 290 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { 291 const ObjCInterfaceDecl *C = D->getClassInterface(); 292 if (!C) 293 return true; 294 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(), 295 SymbolRelation{ 296 (unsigned)SymbolRole::RelationExtendedBy, D 297 })); 298 SourceLocation CategoryLoc = D->getCategoryNameLoc(); 299 if (!CategoryLoc.isValid()) 300 CategoryLoc = D->getLocation(); 301 TRY_TO(IndexCtx.handleDecl(D, CategoryLoc)); 302 TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D)); 303 TRY_TO(IndexCtx.indexDeclContext(D)); 304 return true; 305 } 306 307 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { 308 const ObjCCategoryDecl *Cat = D->getCategoryDecl(); 309 if (!Cat) 310 return true; 311 const ObjCInterfaceDecl *C = D->getClassInterface(); 312 if (C) 313 TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, 314 SymbolRoleSet())); 315 SourceLocation CategoryLoc = D->getCategoryNameLoc(); 316 if (!CategoryLoc.isValid()) 317 CategoryLoc = D->getLocation(); 318 if (!IndexCtx.handleDecl(D, CategoryLoc)) 319 return false; 320 IndexCtx.indexDeclContext(D); 321 return true; 322 } 323 324 bool VisitObjCMethodDecl(const ObjCMethodDecl *D) { 325 // Methods associated with a property, even user-declared ones, are 326 // handled when we handle the property. 327 if (D->isPropertyAccessor()) 328 return true; 329 330 handleObjCMethod(D); 331 return true; 332 } 333 334 bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { 335 if (ObjCMethodDecl *MD = D->getGetterMethodDecl()) 336 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) 337 handleObjCMethod(MD, D); 338 if (ObjCMethodDecl *MD = D->getSetterMethodDecl()) 339 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) 340 handleObjCMethod(MD, D); 341 if (!IndexCtx.handleDecl(D)) 342 return false; 343 if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>()) 344 IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D, 345 D->getLexicalDeclContext(), false, true); 346 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 347 return true; 348 } 349 350 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { 351 ObjCPropertyDecl *PD = D->getPropertyDecl(); 352 if (!IndexCtx.handleReference(PD, D->getLocation(), 353 /*Parent=*/cast<NamedDecl>(D->getDeclContext()), 354 D->getDeclContext(), SymbolRoleSet(), {}, 355 /*RefE=*/nullptr, D)) 356 return false; 357 358 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 359 return true; 360 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); 361 362 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) { 363 if (!IvarD->getSynthesize()) 364 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr, 365 D->getDeclContext(), SymbolRoleSet()); 366 } 367 368 auto *ImplD = cast<ObjCImplDecl>(D->getDeclContext()); 369 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) { 370 if (MD->isPropertyAccessor() && 371 !hasUserDefined(MD, ImplD)) 372 IndexCtx.handleDecl(MD, D->getLocation(), SymbolRoleSet(), {}, ImplD); 373 } 374 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) { 375 if (MD->isPropertyAccessor() && 376 !hasUserDefined(MD, ImplD)) 377 IndexCtx.handleDecl(MD, D->getLocation(), SymbolRoleSet(), {}, ImplD); 378 } 379 return true; 380 } 381 382 bool VisitNamespaceDecl(const NamespaceDecl *D) { 383 if (!IndexCtx.handleDecl(D)) 384 return false; 385 IndexCtx.indexDeclContext(D); 386 return true; 387 } 388 389 bool VisitUsingDecl(const UsingDecl *D) { 390 const DeclContext *DC = D->getDeclContext()->getRedeclContext(); 391 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); 392 393 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, 394 D->getLexicalDeclContext()); 395 for (const auto *I : D->shadows()) 396 IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent, 397 D->getLexicalDeclContext(), SymbolRoleSet()); 398 return true; 399 } 400 401 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { 402 const DeclContext *DC = D->getDeclContext()->getRedeclContext(); 403 const NamedDecl *Parent = dyn_cast<NamedDecl>(DC); 404 405 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent, 406 D->getLexicalDeclContext()); 407 return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(), 408 D->getLocation(), Parent, 409 D->getLexicalDeclContext(), 410 SymbolRoleSet()); 411 } 412 413 bool VisitClassTemplateSpecializationDecl(const 414 ClassTemplateSpecializationDecl *D) { 415 // FIXME: Notify subsequent callbacks if info comes from implicit 416 // instantiation. 417 if (D->isThisDeclarationADefinition()) 418 IndexCtx.indexTagDecl(D); 419 return true; 420 } 421 422 bool VisitTemplateDecl(const TemplateDecl *D) { 423 // FIXME: Template parameters. 424 return Visit(D->getTemplatedDecl()); 425 } 426 427 bool VisitFriendDecl(const FriendDecl *D) { 428 if (auto ND = D->getFriendDecl()) { 429 // FIXME: Ignore a class template in a dependent context, these are not 430 // linked properly with their redeclarations, ending up with duplicate 431 // USRs. 432 // See comment "Friend templates are visible in fairly strange ways." in 433 // SemaTemplate.cpp which precedes code that prevents the friend template 434 // from becoming visible from the enclosing context. 435 if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext()) 436 return true; 437 return Visit(ND); 438 } 439 if (auto Ty = D->getFriendType()) { 440 IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext())); 441 } 442 return true; 443 } 444 445 bool VisitImportDecl(const ImportDecl *D) { 446 return IndexCtx.importedModule(D); 447 } 448 }; 449 450 } // anonymous namespace 451 452 bool IndexingContext::indexDecl(const Decl *D) { 453 if (D->isImplicit() && shouldIgnoreIfImplicit(D)) 454 return true; 455 456 if (isTemplateImplicitInstantiation(D)) 457 return true; 458 459 IndexingDeclVisitor Visitor(*this); 460 bool ShouldContinue = Visitor.Visit(D); 461 if (!ShouldContinue) 462 return false; 463 464 if (!Visitor.Handled && isa<DeclContext>(D)) 465 return indexDeclContext(cast<DeclContext>(D)); 466 467 return true; 468 } 469 470 bool IndexingContext::indexDeclContext(const DeclContext *DC) { 471 for (const auto *I : DC->decls()) 472 if (!indexDecl(I)) 473 return false; 474 return true; 475 } 476 477 bool IndexingContext::indexTopLevelDecl(const Decl *D) { 478 if (D->getLocation().isInvalid()) 479 return true; 480 481 if (isa<ObjCMethodDecl>(D)) 482 return true; // Wait for the objc container. 483 484 return indexDecl(D); 485 } 486 487 bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) { 488 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) 489 if (!indexTopLevelDecl(*I)) 490 return false; 491 return true; 492 } 493