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