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