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