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