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