1 //===- CXIndexDataConsumer.cpp - Index data consumer for libclang----------===// 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 "CXIndexDataConsumer.h" 11 #include "CIndexDiagnostic.h" 12 #include "CXTranslationUnit.h" 13 #include "clang/AST/Attr.h" 14 #include "clang/AST/DeclCXX.h" 15 #include "clang/AST/DeclTemplate.h" 16 #include "clang/AST/DeclVisitor.h" 17 #include "clang/Frontend/ASTUnit.h" 18 19 using namespace clang; 20 using namespace clang::index; 21 using namespace cxindex; 22 using namespace cxcursor; 23 24 namespace { 25 class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> { 26 CXIndexDataConsumer &DataConsumer; 27 SourceLocation DeclLoc; 28 const DeclContext *LexicalDC; 29 30 public: 31 IndexingDeclVisitor(CXIndexDataConsumer &dataConsumer, SourceLocation Loc, 32 const DeclContext *lexicalDC) 33 : DataConsumer(dataConsumer), DeclLoc(Loc), LexicalDC(lexicalDC) { } 34 35 bool VisitFunctionDecl(const FunctionDecl *D) { 36 DataConsumer.handleFunction(D); 37 return true; 38 } 39 40 bool VisitVarDecl(const VarDecl *D) { 41 DataConsumer.handleVar(D); 42 return true; 43 } 44 45 bool VisitFieldDecl(const FieldDecl *D) { 46 DataConsumer.handleField(D); 47 return true; 48 } 49 50 bool VisitMSPropertyDecl(const MSPropertyDecl *D) { 51 return true; 52 } 53 54 bool VisitEnumConstantDecl(const EnumConstantDecl *D) { 55 DataConsumer.handleEnumerator(D); 56 return true; 57 } 58 59 bool VisitTypedefNameDecl(const TypedefNameDecl *D) { 60 DataConsumer.handleTypedefName(D); 61 return true; 62 } 63 64 bool VisitTagDecl(const TagDecl *D) { 65 DataConsumer.handleTagDecl(D); 66 return true; 67 } 68 69 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { 70 DataConsumer.handleObjCInterface(D); 71 return true; 72 } 73 74 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { 75 DataConsumer.handleObjCProtocol(D); 76 return true; 77 } 78 79 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { 80 DataConsumer.handleObjCImplementation(D); 81 return true; 82 } 83 84 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { 85 DataConsumer.handleObjCCategory(D); 86 return true; 87 } 88 89 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { 90 DataConsumer.handleObjCCategoryImpl(D); 91 return true; 92 } 93 94 bool VisitObjCMethodDecl(const ObjCMethodDecl *D) { 95 if (isa<ObjCImplDecl>(LexicalDC) && !D->isThisDeclarationADefinition()) 96 DataConsumer.handleSynthesizedObjCMethod(D, DeclLoc, LexicalDC); 97 else 98 DataConsumer.handleObjCMethod(D); 99 return true; 100 } 101 102 bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { 103 DataConsumer.handleObjCProperty(D); 104 return true; 105 } 106 107 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { 108 DataConsumer.handleSynthesizedObjCProperty(D); 109 return true; 110 } 111 112 bool VisitNamespaceDecl(const NamespaceDecl *D) { 113 DataConsumer.handleNamespace(D); 114 return true; 115 } 116 117 bool VisitUsingDecl(const UsingDecl *D) { 118 return true; 119 } 120 121 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { 122 return true; 123 } 124 125 bool VisitClassTemplateDecl(const ClassTemplateDecl *D) { 126 DataConsumer.handleClassTemplate(D); 127 return true; 128 } 129 130 bool VisitClassTemplateSpecializationDecl(const 131 ClassTemplateSpecializationDecl *D) { 132 DataConsumer.handleTagDecl(D); 133 return true; 134 } 135 136 bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { 137 DataConsumer.handleFunctionTemplate(D); 138 return true; 139 } 140 141 bool VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) { 142 DataConsumer.handleTypeAliasTemplate(D); 143 return true; 144 } 145 146 bool VisitImportDecl(const ImportDecl *D) { 147 DataConsumer.importedModule(D); 148 return true; 149 } 150 }; 151 } 152 153 bool CXIndexDataConsumer::handleDeclOccurence(const Decl *D, 154 SymbolRoleSet Roles, 155 ArrayRef<SymbolRelation> Relations, 156 FileID FID, unsigned Offset, 157 ASTNodeInfo ASTNode) { 158 SourceLocation Loc = getASTContext().getSourceManager() 159 .getLocForStartOfFile(FID).getLocWithOffset(Offset); 160 161 if (Roles & (unsigned)SymbolRole::Reference) { 162 const NamedDecl *ND = dyn_cast<NamedDecl>(D); 163 if (!ND) 164 return true; 165 166 if (auto *ObjCID = dyn_cast_or_null<ObjCInterfaceDecl>(ASTNode.OrigD)) { 167 if (!ObjCID->isThisDeclarationADefinition() && 168 ObjCID->getLocation() == Loc) { 169 // The libclang API treats this as ObjCClassRef declaration. 170 IndexingDeclVisitor(*this, Loc, nullptr).Visit(ObjCID); 171 return true; 172 } 173 } 174 if (auto *ObjCPD = dyn_cast_or_null<ObjCProtocolDecl>(ASTNode.OrigD)) { 175 if (!ObjCPD->isThisDeclarationADefinition() && 176 ObjCPD->getLocation() == Loc) { 177 // The libclang API treats this as ObjCProtocolRef declaration. 178 IndexingDeclVisitor(*this, Loc, nullptr).Visit(ObjCPD); 179 return true; 180 } 181 } 182 183 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct; 184 if (Roles & (unsigned)SymbolRole::Implicit) { 185 Kind = CXIdxEntityRef_Implicit; 186 } 187 188 CXCursor Cursor; 189 if (ASTNode.OrigE) { 190 Cursor = cxcursor::MakeCXCursor(ASTNode.OrigE, 191 cast<Decl>(ASTNode.ContainerDC), 192 getCXTU()); 193 } else { 194 if (ASTNode.OrigD) { 195 if (auto *OrigND = dyn_cast<NamedDecl>(ASTNode.OrigD)) 196 Cursor = getRefCursor(OrigND, Loc); 197 else 198 Cursor = MakeCXCursor(ASTNode.OrigD, CXTU); 199 } else { 200 Cursor = getRefCursor(ND, Loc); 201 } 202 } 203 handleReference(ND, Loc, Cursor, 204 dyn_cast_or_null<NamedDecl>(ASTNode.Parent), 205 ASTNode.ContainerDC, ASTNode.OrigE, Kind); 206 207 } else { 208 const DeclContext *LexicalDC = ASTNode.ContainerDC; 209 if (!LexicalDC) { 210 for (const auto &SymRel : Relations) { 211 if (SymRel.Roles & (unsigned)SymbolRole::RelationChildOf) 212 LexicalDC = dyn_cast<DeclContext>(SymRel.RelatedSymbol); 213 } 214 } 215 IndexingDeclVisitor(*this, Loc, LexicalDC).Visit(ASTNode.OrigD); 216 } 217 218 return !shouldAbort(); 219 } 220 221 bool CXIndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD, 222 SymbolRoleSet Roles, 223 FileID FID, 224 unsigned Offset) { 225 IndexingDeclVisitor(*this, SourceLocation(), nullptr).Visit(ImportD); 226 return !shouldAbort(); 227 } 228 229 void CXIndexDataConsumer::finish() { 230 indexDiagnostics(); 231 } 232 233 234 CXIndexDataConsumer::ObjCProtocolListInfo::ObjCProtocolListInfo( 235 const ObjCProtocolList &ProtList, 236 CXIndexDataConsumer &IdxCtx, 237 ScratchAlloc &SA) { 238 ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin(); 239 for (ObjCInterfaceDecl::protocol_iterator 240 I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) { 241 SourceLocation Loc = *LI; 242 ObjCProtocolDecl *PD = *I; 243 ProtEntities.push_back(EntityInfo()); 244 IdxCtx.getEntityInfo(PD, ProtEntities.back(), SA); 245 CXIdxObjCProtocolRefInfo ProtInfo = { nullptr, 246 MakeCursorObjCProtocolRef(PD, Loc, IdxCtx.CXTU), 247 IdxCtx.getIndexLoc(Loc) }; 248 ProtInfos.push_back(ProtInfo); 249 250 if (IdxCtx.shouldSuppressRefs()) 251 IdxCtx.markEntityOccurrenceInFile(PD, Loc); 252 } 253 254 for (unsigned i = 0, e = ProtInfos.size(); i != e; ++i) 255 ProtInfos[i].protocol = &ProtEntities[i]; 256 257 for (unsigned i = 0, e = ProtInfos.size(); i != e; ++i) 258 Prots.push_back(&ProtInfos[i]); 259 } 260 261 262 IBOutletCollectionInfo::IBOutletCollectionInfo( 263 const IBOutletCollectionInfo &other) 264 : AttrInfo(CXIdxAttr_IBOutletCollection, other.cursor, other.loc, other.A) { 265 266 IBCollInfo.attrInfo = this; 267 IBCollInfo.classCursor = other.IBCollInfo.classCursor; 268 IBCollInfo.classLoc = other.IBCollInfo.classLoc; 269 if (other.IBCollInfo.objcClass) { 270 ClassInfo = other.ClassInfo; 271 IBCollInfo.objcClass = &ClassInfo; 272 } else 273 IBCollInfo.objcClass = nullptr; 274 } 275 276 AttrListInfo::AttrListInfo(const Decl *D, CXIndexDataConsumer &IdxCtx) 277 : SA(IdxCtx), ref_cnt(0) { 278 279 if (!D->hasAttrs()) 280 return; 281 282 for (const auto *A : D->attrs()) { 283 CXCursor C = MakeCXCursor(A, D, IdxCtx.CXTU); 284 CXIdxLoc Loc = IdxCtx.getIndexLoc(A->getLocation()); 285 switch (C.kind) { 286 default: 287 Attrs.push_back(AttrInfo(CXIdxAttr_Unexposed, C, Loc, A)); 288 break; 289 case CXCursor_IBActionAttr: 290 Attrs.push_back(AttrInfo(CXIdxAttr_IBAction, C, Loc, A)); 291 break; 292 case CXCursor_IBOutletAttr: 293 Attrs.push_back(AttrInfo(CXIdxAttr_IBOutlet, C, Loc, A)); 294 break; 295 case CXCursor_IBOutletCollectionAttr: 296 IBCollAttrs.push_back(IBOutletCollectionInfo(C, Loc, A)); 297 break; 298 } 299 } 300 301 for (unsigned i = 0, e = IBCollAttrs.size(); i != e; ++i) { 302 IBOutletCollectionInfo &IBInfo = IBCollAttrs[i]; 303 CXAttrs.push_back(&IBInfo); 304 305 const IBOutletCollectionAttr * 306 IBAttr = cast<IBOutletCollectionAttr>(IBInfo.A); 307 SourceLocation InterfaceLocStart = 308 IBAttr->getInterfaceLoc()->getTypeLoc().getLocStart(); 309 IBInfo.IBCollInfo.attrInfo = &IBInfo; 310 IBInfo.IBCollInfo.classLoc = IdxCtx.getIndexLoc(InterfaceLocStart); 311 IBInfo.IBCollInfo.objcClass = nullptr; 312 IBInfo.IBCollInfo.classCursor = clang_getNullCursor(); 313 QualType Ty = IBAttr->getInterface(); 314 if (const ObjCObjectType *ObjectTy = Ty->getAs<ObjCObjectType>()) { 315 if (const ObjCInterfaceDecl *InterD = ObjectTy->getInterface()) { 316 IdxCtx.getEntityInfo(InterD, IBInfo.ClassInfo, SA); 317 IBInfo.IBCollInfo.objcClass = &IBInfo.ClassInfo; 318 IBInfo.IBCollInfo.classCursor = 319 MakeCursorObjCClassRef(InterD, InterfaceLocStart, IdxCtx.CXTU); 320 } 321 } 322 } 323 324 for (unsigned i = 0, e = Attrs.size(); i != e; ++i) 325 CXAttrs.push_back(&Attrs[i]); 326 } 327 328 IntrusiveRefCntPtr<AttrListInfo> 329 AttrListInfo::create(const Decl *D, CXIndexDataConsumer &IdxCtx) { 330 ScratchAlloc SA(IdxCtx); 331 AttrListInfo *attrs = SA.allocate<AttrListInfo>(); 332 return new (attrs) AttrListInfo(D, IdxCtx); 333 } 334 335 CXIndexDataConsumer::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D, 336 CXIndexDataConsumer &IdxCtx, 337 ScratchAlloc &SA) { 338 for (const auto &Base : D->bases()) { 339 BaseEntities.push_back(EntityInfo()); 340 const NamedDecl *BaseD = nullptr; 341 QualType T = Base.getType(); 342 SourceLocation Loc = getBaseLoc(Base); 343 344 if (const TypedefType *TDT = T->getAs<TypedefType>()) { 345 BaseD = TDT->getDecl(); 346 } else if (const TemplateSpecializationType * 347 TST = T->getAs<TemplateSpecializationType>()) { 348 BaseD = TST->getTemplateName().getAsTemplateDecl(); 349 } else if (const RecordType *RT = T->getAs<RecordType>()) { 350 BaseD = RT->getDecl(); 351 } 352 353 if (BaseD) 354 IdxCtx.getEntityInfo(BaseD, BaseEntities.back(), SA); 355 CXIdxBaseClassInfo BaseInfo = { nullptr, 356 MakeCursorCXXBaseSpecifier(&Base, IdxCtx.CXTU), 357 IdxCtx.getIndexLoc(Loc) }; 358 BaseInfos.push_back(BaseInfo); 359 } 360 361 for (unsigned i = 0, e = BaseInfos.size(); i != e; ++i) { 362 if (BaseEntities[i].name && BaseEntities[i].USR) 363 BaseInfos[i].base = &BaseEntities[i]; 364 } 365 366 for (unsigned i = 0, e = BaseInfos.size(); i != e; ++i) 367 CXBases.push_back(&BaseInfos[i]); 368 } 369 370 SourceLocation CXIndexDataConsumer::CXXBasesListInfo::getBaseLoc( 371 const CXXBaseSpecifier &Base) const { 372 SourceLocation Loc = Base.getSourceRange().getBegin(); 373 TypeLoc TL; 374 if (Base.getTypeSourceInfo()) 375 TL = Base.getTypeSourceInfo()->getTypeLoc(); 376 if (TL.isNull()) 377 return Loc; 378 379 if (QualifiedTypeLoc QL = TL.getAs<QualifiedTypeLoc>()) 380 TL = QL.getUnqualifiedLoc(); 381 382 if (ElaboratedTypeLoc EL = TL.getAs<ElaboratedTypeLoc>()) 383 return EL.getNamedTypeLoc().getBeginLoc(); 384 if (DependentNameTypeLoc DL = TL.getAs<DependentNameTypeLoc>()) 385 return DL.getNameLoc(); 386 if (DependentTemplateSpecializationTypeLoc DTL = 387 TL.getAs<DependentTemplateSpecializationTypeLoc>()) 388 return DTL.getTemplateNameLoc(); 389 390 return Loc; 391 } 392 393 const char *ScratchAlloc::toCStr(StringRef Str) { 394 if (Str.empty()) 395 return ""; 396 if (Str.data()[Str.size()] == '\0') 397 return Str.data(); 398 return copyCStr(Str); 399 } 400 401 const char *ScratchAlloc::copyCStr(StringRef Str) { 402 char *buf = IdxCtx.StrScratch.Allocate<char>(Str.size() + 1); 403 std::uninitialized_copy(Str.begin(), Str.end(), buf); 404 buf[Str.size()] = '\0'; 405 return buf; 406 } 407 408 void CXIndexDataConsumer::setASTContext(ASTContext &ctx) { 409 Ctx = &ctx; 410 cxtu::getASTUnit(CXTU)->setASTContext(&ctx); 411 } 412 413 void CXIndexDataConsumer::setPreprocessor(Preprocessor &PP) { 414 cxtu::getASTUnit(CXTU)->setPreprocessor(&PP); 415 } 416 417 bool CXIndexDataConsumer::isFunctionLocalDecl(const Decl *D) { 418 assert(D); 419 420 if (!D->getParentFunctionOrMethod()) 421 return false; 422 423 if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) { 424 switch (ND->getFormalLinkage()) { 425 case NoLinkage: 426 case VisibleNoLinkage: 427 case InternalLinkage: 428 return true; 429 case UniqueExternalLinkage: 430 llvm_unreachable("Not a sema linkage"); 431 case ExternalLinkage: 432 return false; 433 } 434 } 435 436 return true; 437 } 438 439 bool CXIndexDataConsumer::shouldAbort() { 440 if (!CB.abortQuery) 441 return false; 442 return CB.abortQuery(ClientData, nullptr); 443 } 444 445 void CXIndexDataConsumer::enteredMainFile(const FileEntry *File) { 446 if (File && CB.enteredMainFile) { 447 CXIdxClientFile idxFile = 448 CB.enteredMainFile(ClientData, 449 static_cast<CXFile>(const_cast<FileEntry *>(File)), 450 nullptr); 451 FileMap[File] = idxFile; 452 } 453 } 454 455 void CXIndexDataConsumer::ppIncludedFile(SourceLocation hashLoc, 456 StringRef filename, 457 const FileEntry *File, 458 bool isImport, bool isAngled, 459 bool isModuleImport) { 460 if (!CB.ppIncludedFile) 461 return; 462 463 ScratchAlloc SA(*this); 464 CXIdxIncludedFileInfo Info = { getIndexLoc(hashLoc), 465 SA.toCStr(filename), 466 static_cast<CXFile>( 467 const_cast<FileEntry *>(File)), 468 isImport, isAngled, isModuleImport }; 469 CXIdxClientFile idxFile = CB.ppIncludedFile(ClientData, &Info); 470 FileMap[File] = idxFile; 471 } 472 473 void CXIndexDataConsumer::importedModule(const ImportDecl *ImportD) { 474 if (!CB.importedASTFile) 475 return; 476 477 Module *Mod = ImportD->getImportedModule(); 478 if (!Mod) 479 return; 480 481 CXIdxImportedASTFileInfo Info = { 482 static_cast<CXFile>( 483 const_cast<FileEntry *>(Mod->getASTFile())), 484 Mod, 485 getIndexLoc(ImportD->getLocation()), 486 ImportD->isImplicit() 487 }; 488 CXIdxClientASTFile astFile = CB.importedASTFile(ClientData, &Info); 489 (void)astFile; 490 } 491 492 void CXIndexDataConsumer::importedPCH(const FileEntry *File) { 493 if (!CB.importedASTFile) 494 return; 495 496 CXIdxImportedASTFileInfo Info = { 497 static_cast<CXFile>( 498 const_cast<FileEntry *>(File)), 499 /*module=*/nullptr, 500 getIndexLoc(SourceLocation()), 501 /*isImplicit=*/false 502 }; 503 CXIdxClientASTFile astFile = CB.importedASTFile(ClientData, &Info); 504 (void)astFile; 505 } 506 507 void CXIndexDataConsumer::startedTranslationUnit() { 508 CXIdxClientContainer idxCont = nullptr; 509 if (CB.startedTranslationUnit) 510 idxCont = CB.startedTranslationUnit(ClientData, nullptr); 511 addContainerInMap(Ctx->getTranslationUnitDecl(), idxCont); 512 } 513 514 void CXIndexDataConsumer::indexDiagnostics() { 515 if (!hasDiagnosticCallback()) 516 return; 517 518 CXDiagnosticSetImpl *DiagSet = cxdiag::lazyCreateDiags(getCXTU()); 519 handleDiagnosticSet(DiagSet); 520 } 521 522 void CXIndexDataConsumer::handleDiagnosticSet(CXDiagnostic CXDiagSet) { 523 if (!CB.diagnostic) 524 return; 525 526 CB.diagnostic(ClientData, CXDiagSet, nullptr); 527 } 528 529 bool CXIndexDataConsumer::handleDecl(const NamedDecl *D, 530 SourceLocation Loc, CXCursor Cursor, 531 DeclInfo &DInfo, 532 const DeclContext *LexicalDC, 533 const DeclContext *SemaDC) { 534 if (!CB.indexDeclaration || !D) 535 return false; 536 if (D->isImplicit() && shouldIgnoreIfImplicit(D)) 537 return false; 538 539 ScratchAlloc SA(*this); 540 getEntityInfo(D, DInfo.EntInfo, SA); 541 if ((!shouldIndexFunctionLocalSymbols() && !DInfo.EntInfo.USR) 542 || Loc.isInvalid()) 543 return false; 544 545 if (!LexicalDC) 546 LexicalDC = D->getLexicalDeclContext(); 547 548 if (shouldSuppressRefs()) 549 markEntityOccurrenceInFile(D, Loc); 550 551 DInfo.entityInfo = &DInfo.EntInfo; 552 DInfo.cursor = Cursor; 553 DInfo.loc = getIndexLoc(Loc); 554 DInfo.isImplicit = D->isImplicit(); 555 556 DInfo.attributes = DInfo.EntInfo.attributes; 557 DInfo.numAttributes = DInfo.EntInfo.numAttributes; 558 559 if (!SemaDC) 560 SemaDC = D->getDeclContext(); 561 getContainerInfo(SemaDC, DInfo.SemanticContainer); 562 DInfo.semanticContainer = &DInfo.SemanticContainer; 563 564 if (LexicalDC == SemaDC) { 565 DInfo.lexicalContainer = &DInfo.SemanticContainer; 566 } else if (isTemplateImplicitInstantiation(D)) { 567 // Implicit instantiations have the lexical context of where they were 568 // instantiated first. We choose instead the semantic context because: 569 // 1) at the time that we see the instantiation we have not seen the 570 // function where it occurred yet. 571 // 2) the lexical context of the first instantiation is not useful 572 // information anyway. 573 DInfo.lexicalContainer = &DInfo.SemanticContainer; 574 } else { 575 getContainerInfo(LexicalDC, DInfo.LexicalContainer); 576 DInfo.lexicalContainer = &DInfo.LexicalContainer; 577 } 578 579 if (DInfo.isContainer) { 580 getContainerInfo(getEntityContainer(D), DInfo.DeclAsContainer); 581 DInfo.declAsContainer = &DInfo.DeclAsContainer; 582 } 583 584 CB.indexDeclaration(ClientData, &DInfo); 585 return true; 586 } 587 588 bool CXIndexDataConsumer::handleObjCContainer(const ObjCContainerDecl *D, 589 SourceLocation Loc, CXCursor Cursor, 590 ObjCContainerDeclInfo &ContDInfo) { 591 ContDInfo.ObjCContDeclInfo.declInfo = &ContDInfo; 592 return handleDecl(D, Loc, Cursor, ContDInfo); 593 } 594 595 bool CXIndexDataConsumer::handleFunction(const FunctionDecl *D) { 596 bool isDef = D->isThisDeclarationADefinition(); 597 bool isContainer = isDef; 598 bool isSkipped = false; 599 if (D->hasSkippedBody()) { 600 isSkipped = true; 601 isDef = true; 602 isContainer = false; 603 } 604 605 DeclInfo DInfo(!D->isFirstDecl(), isDef, isContainer); 606 if (isSkipped) 607 DInfo.flags |= CXIdxDeclFlag_Skipped; 608 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 609 } 610 611 bool CXIndexDataConsumer::handleVar(const VarDecl *D) { 612 DeclInfo DInfo(!D->isFirstDecl(), D->isThisDeclarationADefinition(), 613 /*isContainer=*/false); 614 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 615 } 616 617 bool CXIndexDataConsumer::handleField(const FieldDecl *D) { 618 DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true, 619 /*isContainer=*/false); 620 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 621 } 622 623 bool CXIndexDataConsumer::handleMSProperty(const MSPropertyDecl *D) { 624 DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true, 625 /*isContainer=*/false); 626 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 627 } 628 629 bool CXIndexDataConsumer::handleEnumerator(const EnumConstantDecl *D) { 630 DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true, 631 /*isContainer=*/false); 632 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 633 } 634 635 bool CXIndexDataConsumer::handleTagDecl(const TagDecl *D) { 636 if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(D)) 637 return handleCXXRecordDecl(CXXRD, D); 638 639 DeclInfo DInfo(!D->isFirstDecl(), D->isThisDeclarationADefinition(), 640 D->isThisDeclarationADefinition()); 641 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 642 } 643 644 bool CXIndexDataConsumer::handleTypedefName(const TypedefNameDecl *D) { 645 DeclInfo DInfo(!D->isFirstDecl(), /*isDefinition=*/true, 646 /*isContainer=*/false); 647 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 648 } 649 650 bool CXIndexDataConsumer::handleObjCInterface(const ObjCInterfaceDecl *D) { 651 // For @class forward declarations, suppress them the same way as references. 652 if (!D->isThisDeclarationADefinition()) { 653 if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, D->getLocation())) 654 return false; // already occurred. 655 656 // FIXME: This seems like the wrong definition for redeclaration. 657 bool isRedeclaration = D->hasDefinition() || D->getPreviousDecl(); 658 ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true, isRedeclaration, 659 /*isImplementation=*/false); 660 return handleObjCContainer(D, D->getLocation(), 661 MakeCursorObjCClassRef(D, D->getLocation(), 662 CXTU), 663 ContDInfo); 664 } 665 666 ScratchAlloc SA(*this); 667 668 CXIdxBaseClassInfo BaseClass; 669 EntityInfo BaseEntity; 670 BaseClass.cursor = clang_getNullCursor(); 671 if (ObjCInterfaceDecl *SuperD = D->getSuperClass()) { 672 getEntityInfo(SuperD, BaseEntity, SA); 673 SourceLocation SuperLoc = D->getSuperClassLoc(); 674 BaseClass.base = &BaseEntity; 675 BaseClass.cursor = MakeCursorObjCSuperClassRef(SuperD, SuperLoc, CXTU); 676 BaseClass.loc = getIndexLoc(SuperLoc); 677 678 if (shouldSuppressRefs()) 679 markEntityOccurrenceInFile(SuperD, SuperLoc); 680 } 681 682 ObjCProtocolList EmptyProtoList; 683 ObjCProtocolListInfo ProtInfo(D->isThisDeclarationADefinition() 684 ? D->getReferencedProtocols() 685 : EmptyProtoList, 686 *this, SA); 687 688 ObjCInterfaceDeclInfo InterInfo(D); 689 InterInfo.ObjCProtoListInfo = ProtInfo.getListInfo(); 690 InterInfo.ObjCInterDeclInfo.containerInfo = &InterInfo.ObjCContDeclInfo; 691 InterInfo.ObjCInterDeclInfo.superInfo = D->getSuperClass() ? &BaseClass 692 : nullptr; 693 InterInfo.ObjCInterDeclInfo.protocols = &InterInfo.ObjCProtoListInfo; 694 695 return handleObjCContainer(D, D->getLocation(), getCursor(D), InterInfo); 696 } 697 698 bool CXIndexDataConsumer::handleObjCImplementation( 699 const ObjCImplementationDecl *D) { 700 ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/false, 701 /*isRedeclaration=*/true, 702 /*isImplementation=*/true); 703 return handleObjCContainer(D, D->getLocation(), getCursor(D), ContDInfo); 704 } 705 706 bool CXIndexDataConsumer::handleObjCProtocol(const ObjCProtocolDecl *D) { 707 if (!D->isThisDeclarationADefinition()) { 708 if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, D->getLocation())) 709 return false; // already occurred. 710 711 // FIXME: This seems like the wrong definition for redeclaration. 712 bool isRedeclaration = D->hasDefinition() || D->getPreviousDecl(); 713 ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true, 714 isRedeclaration, 715 /*isImplementation=*/false); 716 return handleObjCContainer(D, D->getLocation(), 717 MakeCursorObjCProtocolRef(D, D->getLocation(), 718 CXTU), 719 ContDInfo); 720 } 721 722 ScratchAlloc SA(*this); 723 ObjCProtocolList EmptyProtoList; 724 ObjCProtocolListInfo ProtListInfo(D->isThisDeclarationADefinition() 725 ? D->getReferencedProtocols() 726 : EmptyProtoList, 727 *this, SA); 728 729 ObjCProtocolDeclInfo ProtInfo(D); 730 ProtInfo.ObjCProtoRefListInfo = ProtListInfo.getListInfo(); 731 732 return handleObjCContainer(D, D->getLocation(), getCursor(D), ProtInfo); 733 } 734 735 bool CXIndexDataConsumer::handleObjCCategory(const ObjCCategoryDecl *D) { 736 ScratchAlloc SA(*this); 737 738 ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/false); 739 EntityInfo ClassEntity; 740 const ObjCInterfaceDecl *IFaceD = D->getClassInterface(); 741 SourceLocation ClassLoc = D->getLocation(); 742 SourceLocation CategoryLoc = D->IsClassExtension() ? ClassLoc 743 : D->getCategoryNameLoc(); 744 getEntityInfo(IFaceD, ClassEntity, SA); 745 746 if (shouldSuppressRefs()) 747 markEntityOccurrenceInFile(IFaceD, ClassLoc); 748 749 ObjCProtocolListInfo ProtInfo(D->getReferencedProtocols(), *this, SA); 750 751 CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo; 752 if (IFaceD) { 753 CatDInfo.ObjCCatDeclInfo.objcClass = &ClassEntity; 754 CatDInfo.ObjCCatDeclInfo.classCursor = 755 MakeCursorObjCClassRef(IFaceD, ClassLoc, CXTU); 756 } else { 757 CatDInfo.ObjCCatDeclInfo.objcClass = nullptr; 758 CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor(); 759 } 760 CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(ClassLoc); 761 CatDInfo.ObjCProtoListInfo = ProtInfo.getListInfo(); 762 CatDInfo.ObjCCatDeclInfo.protocols = &CatDInfo.ObjCProtoListInfo; 763 764 return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo); 765 } 766 767 bool CXIndexDataConsumer::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) { 768 ScratchAlloc SA(*this); 769 770 const ObjCCategoryDecl *CatD = D->getCategoryDecl(); 771 ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/true); 772 EntityInfo ClassEntity; 773 const ObjCInterfaceDecl *IFaceD = CatD->getClassInterface(); 774 SourceLocation ClassLoc = D->getLocation(); 775 SourceLocation CategoryLoc = D->getCategoryNameLoc(); 776 getEntityInfo(IFaceD, ClassEntity, SA); 777 778 if (shouldSuppressRefs()) 779 markEntityOccurrenceInFile(IFaceD, ClassLoc); 780 781 CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo; 782 if (IFaceD) { 783 CatDInfo.ObjCCatDeclInfo.objcClass = &ClassEntity; 784 CatDInfo.ObjCCatDeclInfo.classCursor = 785 MakeCursorObjCClassRef(IFaceD, ClassLoc, CXTU); 786 } else { 787 CatDInfo.ObjCCatDeclInfo.objcClass = nullptr; 788 CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor(); 789 } 790 CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(ClassLoc); 791 CatDInfo.ObjCCatDeclInfo.protocols = nullptr; 792 793 return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo); 794 } 795 796 bool CXIndexDataConsumer::handleObjCMethod(const ObjCMethodDecl *D) { 797 bool isDef = D->isThisDeclarationADefinition(); 798 bool isContainer = isDef; 799 bool isSkipped = false; 800 if (D->hasSkippedBody()) { 801 isSkipped = true; 802 isDef = true; 803 isContainer = false; 804 } 805 806 DeclInfo DInfo(!D->isCanonicalDecl(), isDef, isContainer); 807 if (isSkipped) 808 DInfo.flags |= CXIdxDeclFlag_Skipped; 809 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 810 } 811 812 bool CXIndexDataConsumer::handleSynthesizedObjCProperty( 813 const ObjCPropertyImplDecl *D) { 814 ObjCPropertyDecl *PD = D->getPropertyDecl(); 815 auto *DC = D->getDeclContext(); 816 return handleReference(PD, D->getLocation(), getCursor(D), 817 dyn_cast<NamedDecl>(DC), DC); 818 } 819 820 bool CXIndexDataConsumer::handleSynthesizedObjCMethod(const ObjCMethodDecl *D, 821 SourceLocation Loc, 822 const DeclContext *LexicalDC) { 823 DeclInfo DInfo(/*isRedeclaration=*/true, /*isDefinition=*/true, 824 /*isContainer=*/false); 825 return handleDecl(D, Loc, getCursor(D), DInfo, LexicalDC, D->getDeclContext()); 826 } 827 828 bool CXIndexDataConsumer::handleObjCProperty(const ObjCPropertyDecl *D) { 829 ScratchAlloc SA(*this); 830 831 ObjCPropertyDeclInfo DInfo; 832 EntityInfo GetterEntity; 833 EntityInfo SetterEntity; 834 835 DInfo.ObjCPropDeclInfo.declInfo = &DInfo; 836 837 if (ObjCMethodDecl *Getter = D->getGetterMethodDecl()) { 838 getEntityInfo(Getter, GetterEntity, SA); 839 DInfo.ObjCPropDeclInfo.getter = &GetterEntity; 840 } else { 841 DInfo.ObjCPropDeclInfo.getter = nullptr; 842 } 843 if (ObjCMethodDecl *Setter = D->getSetterMethodDecl()) { 844 getEntityInfo(Setter, SetterEntity, SA); 845 DInfo.ObjCPropDeclInfo.setter = &SetterEntity; 846 } else { 847 DInfo.ObjCPropDeclInfo.setter = nullptr; 848 } 849 850 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 851 } 852 853 bool CXIndexDataConsumer::handleNamespace(const NamespaceDecl *D) { 854 DeclInfo DInfo(/*isRedeclaration=*/!D->isOriginalNamespace(), 855 /*isDefinition=*/true, 856 /*isContainer=*/true); 857 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 858 } 859 860 bool CXIndexDataConsumer::handleClassTemplate(const ClassTemplateDecl *D) { 861 return handleCXXRecordDecl(D->getTemplatedDecl(), D); 862 } 863 864 bool CXIndexDataConsumer::handleFunctionTemplate(const FunctionTemplateDecl *D) { 865 DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(), 866 /*isDefinition=*/D->isThisDeclarationADefinition(), 867 /*isContainer=*/D->isThisDeclarationADefinition()); 868 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 869 } 870 871 bool CXIndexDataConsumer::handleTypeAliasTemplate(const TypeAliasTemplateDecl *D) { 872 DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(), 873 /*isDefinition=*/true, /*isContainer=*/false); 874 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 875 } 876 877 bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc, 878 const NamedDecl *Parent, 879 const DeclContext *DC, 880 const Expr *E, 881 CXIdxEntityRefKind Kind) { 882 if (!D) 883 return false; 884 885 CXCursor Cursor = E ? MakeCXCursor(E, cast<Decl>(DC), CXTU) 886 : getRefCursor(D, Loc); 887 return handleReference(D, Loc, Cursor, Parent, DC, E, Kind); 888 } 889 890 bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc, 891 CXCursor Cursor, 892 const NamedDecl *Parent, 893 const DeclContext *DC, 894 const Expr *E, 895 CXIdxEntityRefKind Kind) { 896 if (!CB.indexEntityReference) 897 return false; 898 899 if (!D) 900 return false; 901 if (Loc.isInvalid()) 902 return false; 903 if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D)) 904 return false; 905 if (isNotFromSourceFile(D->getLocation())) 906 return false; 907 if (D->isImplicit() && shouldIgnoreIfImplicit(D)) 908 return false; 909 910 if (shouldSuppressRefs()) { 911 if (markEntityOccurrenceInFile(D, Loc)) 912 return false; // already occurred. 913 } 914 915 ScratchAlloc SA(*this); 916 EntityInfo RefEntity, ParentEntity; 917 getEntityInfo(D, RefEntity, SA); 918 if (!RefEntity.USR) 919 return false; 920 921 getEntityInfo(Parent, ParentEntity, SA); 922 923 ContainerInfo Container; 924 getContainerInfo(DC, Container); 925 926 CXIdxEntityRefInfo Info = { Kind, 927 Cursor, 928 getIndexLoc(Loc), 929 &RefEntity, 930 Parent ? &ParentEntity : nullptr, 931 &Container }; 932 CB.indexEntityReference(ClientData, &Info); 933 return true; 934 } 935 936 bool CXIndexDataConsumer::isNotFromSourceFile(SourceLocation Loc) const { 937 if (Loc.isInvalid()) 938 return true; 939 SourceManager &SM = Ctx->getSourceManager(); 940 SourceLocation FileLoc = SM.getFileLoc(Loc); 941 FileID FID = SM.getFileID(FileLoc); 942 return SM.getFileEntryForID(FID) == nullptr; 943 } 944 945 void CXIndexDataConsumer::addContainerInMap(const DeclContext *DC, 946 CXIdxClientContainer container) { 947 if (!DC) 948 return; 949 950 ContainerMapTy::iterator I = ContainerMap.find(DC); 951 if (I == ContainerMap.end()) { 952 if (container) 953 ContainerMap[DC] = container; 954 return; 955 } 956 // Allow changing the container of a previously seen DeclContext so we 957 // can handle invalid user code, like a function re-definition. 958 if (container) 959 I->second = container; 960 else 961 ContainerMap.erase(I); 962 } 963 964 CXIdxClientEntity CXIndexDataConsumer::getClientEntity(const Decl *D) const { 965 if (!D) 966 return nullptr; 967 EntityMapTy::const_iterator I = EntityMap.find(D); 968 if (I == EntityMap.end()) 969 return nullptr; 970 return I->second; 971 } 972 973 void CXIndexDataConsumer::setClientEntity(const Decl *D, CXIdxClientEntity client) { 974 if (!D) 975 return; 976 EntityMap[D] = client; 977 } 978 979 bool CXIndexDataConsumer::handleCXXRecordDecl(const CXXRecordDecl *RD, 980 const NamedDecl *OrigD) { 981 if (RD->isThisDeclarationADefinition()) { 982 ScratchAlloc SA(*this); 983 CXXClassDeclInfo CXXDInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(), 984 /*isDefinition=*/RD->isThisDeclarationADefinition()); 985 CXXBasesListInfo BaseList(RD, *this, SA); 986 CXXDInfo.CXXClassInfo.declInfo = &CXXDInfo; 987 CXXDInfo.CXXClassInfo.bases = BaseList.getBases(); 988 CXXDInfo.CXXClassInfo.numBases = BaseList.getNumBases(); 989 990 if (shouldSuppressRefs()) { 991 // Go through bases and mark them as referenced. 992 for (unsigned i = 0, e = BaseList.getNumBases(); i != e; ++i) { 993 const CXIdxBaseClassInfo *baseInfo = BaseList.getBases()[i]; 994 if (baseInfo->base) { 995 const NamedDecl *BaseD = BaseList.BaseEntities[i].Dcl; 996 SourceLocation 997 Loc = SourceLocation::getFromRawEncoding(baseInfo->loc.int_data); 998 markEntityOccurrenceInFile(BaseD, Loc); 999 } 1000 } 1001 } 1002 1003 return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), CXXDInfo); 1004 } 1005 1006 DeclInfo DInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(), 1007 /*isDefinition=*/RD->isThisDeclarationADefinition(), 1008 /*isContainer=*/RD->isThisDeclarationADefinition()); 1009 return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), DInfo); 1010 } 1011 1012 bool CXIndexDataConsumer::markEntityOccurrenceInFile(const NamedDecl *D, 1013 SourceLocation Loc) { 1014 if (!D || Loc.isInvalid()) 1015 return true; 1016 1017 SourceManager &SM = Ctx->getSourceManager(); 1018 D = getEntityDecl(D); 1019 1020 std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SM.getFileLoc(Loc)); 1021 FileID FID = LocInfo.first; 1022 if (FID.isInvalid()) 1023 return true; 1024 1025 const FileEntry *FE = SM.getFileEntryForID(FID); 1026 if (!FE) 1027 return true; 1028 RefFileOccurrence RefOccur(FE, D); 1029 std::pair<llvm::DenseSet<RefFileOccurrence>::iterator, bool> 1030 res = RefFileOccurrences.insert(RefOccur); 1031 return !res.second; // already in map 1032 } 1033 1034 const NamedDecl *CXIndexDataConsumer::getEntityDecl(const NamedDecl *D) const { 1035 assert(D); 1036 D = cast<NamedDecl>(D->getCanonicalDecl()); 1037 1038 if (const ObjCImplementationDecl * 1039 ImplD = dyn_cast<ObjCImplementationDecl>(D)) { 1040 return getEntityDecl(ImplD->getClassInterface()); 1041 1042 } else if (const ObjCCategoryImplDecl * 1043 CatImplD = dyn_cast<ObjCCategoryImplDecl>(D)) { 1044 return getEntityDecl(CatImplD->getCategoryDecl()); 1045 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 1046 if (FunctionTemplateDecl *TemplD = FD->getDescribedFunctionTemplate()) 1047 return getEntityDecl(TemplD); 1048 } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { 1049 if (ClassTemplateDecl *TemplD = RD->getDescribedClassTemplate()) 1050 return getEntityDecl(TemplD); 1051 } 1052 1053 return D; 1054 } 1055 1056 const DeclContext * 1057 CXIndexDataConsumer::getEntityContainer(const Decl *D) const { 1058 const DeclContext *DC = dyn_cast<DeclContext>(D); 1059 if (DC) 1060 return DC; 1061 1062 if (const ClassTemplateDecl *ClassTempl = dyn_cast<ClassTemplateDecl>(D)) { 1063 DC = ClassTempl->getTemplatedDecl(); 1064 } else if (const FunctionTemplateDecl * 1065 FuncTempl = dyn_cast<FunctionTemplateDecl>(D)) { 1066 DC = FuncTempl->getTemplatedDecl(); 1067 } 1068 1069 return DC; 1070 } 1071 1072 CXIdxClientContainer 1073 CXIndexDataConsumer::getClientContainerForDC(const DeclContext *DC) const { 1074 if (!DC) 1075 return nullptr; 1076 1077 ContainerMapTy::const_iterator I = ContainerMap.find(DC); 1078 if (I == ContainerMap.end()) 1079 return nullptr; 1080 1081 return I->second; 1082 } 1083 1084 CXIdxClientFile CXIndexDataConsumer::getIndexFile(const FileEntry *File) { 1085 if (!File) 1086 return nullptr; 1087 1088 FileMapTy::iterator FI = FileMap.find(File); 1089 if (FI != FileMap.end()) 1090 return FI->second; 1091 1092 return nullptr; 1093 } 1094 1095 CXIdxLoc CXIndexDataConsumer::getIndexLoc(SourceLocation Loc) const { 1096 CXIdxLoc idxLoc = { {nullptr, nullptr}, 0 }; 1097 if (Loc.isInvalid()) 1098 return idxLoc; 1099 1100 idxLoc.ptr_data[0] = const_cast<CXIndexDataConsumer *>(this); 1101 idxLoc.int_data = Loc.getRawEncoding(); 1102 return idxLoc; 1103 } 1104 1105 void CXIndexDataConsumer::translateLoc(SourceLocation Loc, 1106 CXIdxClientFile *indexFile, CXFile *file, 1107 unsigned *line, unsigned *column, 1108 unsigned *offset) { 1109 if (Loc.isInvalid()) 1110 return; 1111 1112 SourceManager &SM = Ctx->getSourceManager(); 1113 Loc = SM.getFileLoc(Loc); 1114 1115 std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); 1116 FileID FID = LocInfo.first; 1117 unsigned FileOffset = LocInfo.second; 1118 1119 if (FID.isInvalid()) 1120 return; 1121 1122 const FileEntry *FE = SM.getFileEntryForID(FID); 1123 if (indexFile) 1124 *indexFile = getIndexFile(FE); 1125 if (file) 1126 *file = const_cast<FileEntry *>(FE); 1127 if (line) 1128 *line = SM.getLineNumber(FID, FileOffset); 1129 if (column) 1130 *column = SM.getColumnNumber(FID, FileOffset); 1131 if (offset) 1132 *offset = FileOffset; 1133 } 1134 1135 static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage L); 1136 static CXIdxEntityCXXTemplateKind 1137 getEntityKindFromSymbolSubKinds(SymbolSubKindSet K); 1138 static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L); 1139 1140 void CXIndexDataConsumer::getEntityInfo(const NamedDecl *D, 1141 EntityInfo &EntityInfo, 1142 ScratchAlloc &SA) { 1143 if (!D) 1144 return; 1145 1146 D = getEntityDecl(D); 1147 EntityInfo.cursor = getCursor(D); 1148 EntityInfo.Dcl = D; 1149 EntityInfo.IndexCtx = this; 1150 1151 SymbolInfo SymInfo = getSymbolInfo(D); 1152 EntityInfo.kind = getEntityKindFromSymbolKind(SymInfo.Kind, SymInfo.Lang); 1153 EntityInfo.templateKind = getEntityKindFromSymbolSubKinds(SymInfo.SubKinds); 1154 EntityInfo.lang = getEntityLangFromSymbolLang(SymInfo.Lang); 1155 1156 if (D->hasAttrs()) { 1157 EntityInfo.AttrList = AttrListInfo::create(D, *this); 1158 EntityInfo.attributes = EntityInfo.AttrList->getAttrs(); 1159 EntityInfo.numAttributes = EntityInfo.AttrList->getNumAttrs(); 1160 } 1161 1162 if (EntityInfo.kind == CXIdxEntity_Unexposed) 1163 return; 1164 1165 if (IdentifierInfo *II = D->getIdentifier()) { 1166 EntityInfo.name = SA.toCStr(II->getName()); 1167 1168 } else if (isa<TagDecl>(D) || isa<FieldDecl>(D) || isa<NamespaceDecl>(D)) { 1169 EntityInfo.name = nullptr; // anonymous tag/field/namespace. 1170 1171 } else { 1172 SmallString<256> StrBuf; 1173 { 1174 llvm::raw_svector_ostream OS(StrBuf); 1175 D->printName(OS); 1176 } 1177 EntityInfo.name = SA.copyCStr(StrBuf.str()); 1178 } 1179 1180 { 1181 SmallString<512> StrBuf; 1182 bool Ignore = getDeclCursorUSR(D, StrBuf); 1183 if (Ignore) { 1184 EntityInfo.USR = nullptr; 1185 } else { 1186 EntityInfo.USR = SA.copyCStr(StrBuf.str()); 1187 } 1188 } 1189 } 1190 1191 void CXIndexDataConsumer::getContainerInfo(const DeclContext *DC, 1192 ContainerInfo &ContInfo) { 1193 ContInfo.cursor = getCursor(cast<Decl>(DC)); 1194 ContInfo.DC = DC; 1195 ContInfo.IndexCtx = this; 1196 } 1197 1198 CXCursor CXIndexDataConsumer::getRefCursor(const NamedDecl *D, SourceLocation Loc) { 1199 if (const TypeDecl *TD = dyn_cast<TypeDecl>(D)) 1200 return MakeCursorTypeRef(TD, Loc, CXTU); 1201 if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) 1202 return MakeCursorObjCClassRef(ID, Loc, CXTU); 1203 if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) 1204 return MakeCursorObjCProtocolRef(PD, Loc, CXTU); 1205 if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) 1206 return MakeCursorTemplateRef(Template, Loc, CXTU); 1207 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(D)) 1208 return MakeCursorNamespaceRef(Namespace, Loc, CXTU); 1209 if (const NamespaceAliasDecl *Namespace = dyn_cast<NamespaceAliasDecl>(D)) 1210 return MakeCursorNamespaceRef(Namespace, Loc, CXTU); 1211 if (const FieldDecl *Field = dyn_cast<FieldDecl>(D)) 1212 return MakeCursorMemberRef(Field, Loc, CXTU); 1213 if (const VarDecl *Var = dyn_cast<VarDecl>(D)) 1214 return MakeCursorVariableRef(Var, Loc, CXTU); 1215 1216 return clang_getNullCursor(); 1217 } 1218 1219 bool CXIndexDataConsumer::shouldIgnoreIfImplicit(const Decl *D) { 1220 if (isa<ObjCInterfaceDecl>(D)) 1221 return false; 1222 if (isa<ObjCCategoryDecl>(D)) 1223 return false; 1224 if (isa<ObjCIvarDecl>(D)) 1225 return false; 1226 if (isa<ObjCMethodDecl>(D)) 1227 return false; 1228 if (isa<ImportDecl>(D)) 1229 return false; 1230 return true; 1231 } 1232 1233 bool CXIndexDataConsumer::isTemplateImplicitInstantiation(const Decl *D) { 1234 if (const ClassTemplateSpecializationDecl * 1235 SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) { 1236 return SD->getSpecializationKind() == TSK_ImplicitInstantiation; 1237 } 1238 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 1239 return FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation; 1240 } 1241 return false; 1242 } 1243 1244 static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage Lang) { 1245 switch (K) { 1246 case SymbolKind::Unknown: 1247 case SymbolKind::Module: 1248 case SymbolKind::Macro: 1249 case SymbolKind::ClassProperty: 1250 return CXIdxEntity_Unexposed; 1251 1252 case SymbolKind::Enum: return CXIdxEntity_Enum; 1253 case SymbolKind::Struct: return CXIdxEntity_Struct; 1254 case SymbolKind::Union: return CXIdxEntity_Union; 1255 case SymbolKind::TypeAlias: 1256 if (Lang == SymbolLanguage::CXX) 1257 return CXIdxEntity_CXXTypeAlias; 1258 return CXIdxEntity_Typedef; 1259 case SymbolKind::Function: return CXIdxEntity_Function; 1260 case SymbolKind::Variable: return CXIdxEntity_Variable; 1261 case SymbolKind::Field: 1262 if (Lang == SymbolLanguage::ObjC) 1263 return CXIdxEntity_ObjCIvar; 1264 return CXIdxEntity_Field; 1265 case SymbolKind::EnumConstant: return CXIdxEntity_EnumConstant; 1266 case SymbolKind::Class: 1267 if (Lang == SymbolLanguage::ObjC) 1268 return CXIdxEntity_ObjCClass; 1269 return CXIdxEntity_CXXClass; 1270 case SymbolKind::Protocol: 1271 if (Lang == SymbolLanguage::ObjC) 1272 return CXIdxEntity_ObjCProtocol; 1273 return CXIdxEntity_CXXInterface; 1274 case SymbolKind::Extension: return CXIdxEntity_ObjCCategory; 1275 case SymbolKind::InstanceMethod: 1276 if (Lang == SymbolLanguage::ObjC) 1277 return CXIdxEntity_ObjCInstanceMethod; 1278 return CXIdxEntity_CXXInstanceMethod; 1279 case SymbolKind::ClassMethod: return CXIdxEntity_ObjCClassMethod; 1280 case SymbolKind::StaticMethod: return CXIdxEntity_CXXStaticMethod; 1281 case SymbolKind::InstanceProperty: return CXIdxEntity_ObjCProperty; 1282 case SymbolKind::StaticProperty: return CXIdxEntity_CXXStaticVariable; 1283 case SymbolKind::Namespace: return CXIdxEntity_CXXNamespace; 1284 case SymbolKind::NamespaceAlias: return CXIdxEntity_CXXNamespaceAlias; 1285 case SymbolKind::Constructor: return CXIdxEntity_CXXConstructor; 1286 case SymbolKind::Destructor: return CXIdxEntity_CXXDestructor; 1287 case SymbolKind::ConversionFunction: return CXIdxEntity_CXXConversionFunction; 1288 } 1289 llvm_unreachable("invalid symbol kind"); 1290 } 1291 1292 static CXIdxEntityCXXTemplateKind 1293 getEntityKindFromSymbolSubKinds(SymbolSubKindSet K) { 1294 if (K & (unsigned)SymbolSubKind::TemplatePartialSpecialization) 1295 return CXIdxEntity_TemplatePartialSpecialization; 1296 if (K & (unsigned)SymbolSubKind::TemplateSpecialization) 1297 return CXIdxEntity_TemplateSpecialization; 1298 if (K & (unsigned)SymbolSubKind::Generic) 1299 return CXIdxEntity_Template; 1300 return CXIdxEntity_NonTemplate; 1301 } 1302 1303 static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L) { 1304 switch (L) { 1305 case SymbolLanguage::C: return CXIdxEntityLang_C; 1306 case SymbolLanguage::ObjC: return CXIdxEntityLang_ObjC; 1307 case SymbolLanguage::CXX: return CXIdxEntityLang_CXX; 1308 } 1309 llvm_unreachable("invalid symbol language"); 1310 } 1311