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