1 //===- CXIndexDataConsumer.cpp - Index data consumer for libclang----------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "CXIndexDataConsumer.h" 11 #include "CIndexDiagnostic.h" 12 #include "CXTranslationUnit.h" 13 #include "clang/AST/Attr.h" 14 #include "clang/AST/DeclCXX.h" 15 #include "clang/AST/DeclTemplate.h" 16 #include "clang/AST/DeclVisitor.h" 17 #include "clang/Frontend/ASTUnit.h" 18 19 using namespace clang; 20 using namespace clang::index; 21 using namespace cxindex; 22 using namespace cxcursor; 23 24 namespace { 25 class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> { 26 CXIndexDataConsumer &DataConsumer; 27 SourceLocation DeclLoc; 28 const DeclContext *LexicalDC; 29 30 public: 31 IndexingDeclVisitor(CXIndexDataConsumer &dataConsumer, SourceLocation Loc, 32 const DeclContext *lexicalDC) 33 : DataConsumer(dataConsumer), DeclLoc(Loc), LexicalDC(lexicalDC) { } 34 35 bool VisitFunctionDecl(const FunctionDecl *D) { 36 DataConsumer.handleFunction(D); 37 return true; 38 } 39 40 bool VisitVarDecl(const VarDecl *D) { 41 DataConsumer.handleVar(D); 42 return true; 43 } 44 45 bool VisitFieldDecl(const FieldDecl *D) { 46 DataConsumer.handleField(D); 47 return true; 48 } 49 50 bool VisitMSPropertyDecl(const MSPropertyDecl *D) { 51 return true; 52 } 53 54 bool VisitEnumConstantDecl(const EnumConstantDecl *D) { 55 DataConsumer.handleEnumerator(D); 56 return true; 57 } 58 59 bool VisitTypedefNameDecl(const TypedefNameDecl *D) { 60 DataConsumer.handleTypedefName(D); 61 return true; 62 } 63 64 bool VisitTagDecl(const TagDecl *D) { 65 DataConsumer.handleTagDecl(D); 66 return true; 67 } 68 69 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { 70 DataConsumer.handleObjCInterface(D); 71 return true; 72 } 73 74 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { 75 DataConsumer.handleObjCProtocol(D); 76 return true; 77 } 78 79 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { 80 DataConsumer.handleObjCImplementation(D); 81 return true; 82 } 83 84 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { 85 DataConsumer.handleObjCCategory(D); 86 return true; 87 } 88 89 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { 90 DataConsumer.handleObjCCategoryImpl(D); 91 return true; 92 } 93 94 bool VisitObjCMethodDecl(const ObjCMethodDecl *D) { 95 if (isa<ObjCImplDecl>(LexicalDC) && !D->isThisDeclarationADefinition()) 96 DataConsumer.handleSynthesizedObjCMethod(D, DeclLoc, LexicalDC); 97 else 98 DataConsumer.handleObjCMethod(D, DeclLoc); 99 return true; 100 } 101 102 bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { 103 DataConsumer.handleObjCProperty(D); 104 return true; 105 } 106 107 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { 108 DataConsumer.handleSynthesizedObjCProperty(D); 109 return true; 110 } 111 112 bool VisitNamespaceDecl(const NamespaceDecl *D) { 113 DataConsumer.handleNamespace(D); 114 return true; 115 } 116 117 bool VisitUsingDecl(const UsingDecl *D) { 118 return true; 119 } 120 121 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { 122 return true; 123 } 124 125 bool VisitClassTemplateDecl(const ClassTemplateDecl *D) { 126 DataConsumer.handleClassTemplate(D); 127 return true; 128 } 129 130 bool VisitClassTemplateSpecializationDecl(const 131 ClassTemplateSpecializationDecl *D) { 132 DataConsumer.handleTagDecl(D); 133 return true; 134 } 135 136 bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { 137 DataConsumer.handleFunctionTemplate(D); 138 return true; 139 } 140 141 bool VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) { 142 DataConsumer.handleTypeAliasTemplate(D); 143 return true; 144 } 145 146 bool VisitImportDecl(const ImportDecl *D) { 147 DataConsumer.importedModule(D); 148 return true; 149 } 150 }; 151 } 152 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 InternalLinkage: 427 return true; 428 case VisibleNoLinkage: 429 case ModuleInternalLinkage: 430 case UniqueExternalLinkage: 431 llvm_unreachable("Not a sema linkage"); 432 case ModuleLinkage: 433 case ExternalLinkage: 434 return false; 435 } 436 } 437 438 return true; 439 } 440 441 bool CXIndexDataConsumer::shouldAbort() { 442 if (!CB.abortQuery) 443 return false; 444 return CB.abortQuery(ClientData, nullptr); 445 } 446 447 void CXIndexDataConsumer::enteredMainFile(const FileEntry *File) { 448 if (File && CB.enteredMainFile) { 449 CXIdxClientFile idxFile = 450 CB.enteredMainFile(ClientData, 451 static_cast<CXFile>(const_cast<FileEntry *>(File)), 452 nullptr); 453 FileMap[File] = idxFile; 454 } 455 } 456 457 void CXIndexDataConsumer::ppIncludedFile(SourceLocation hashLoc, 458 StringRef filename, 459 const FileEntry *File, 460 bool isImport, bool isAngled, 461 bool isModuleImport) { 462 if (!CB.ppIncludedFile) 463 return; 464 465 ScratchAlloc SA(*this); 466 CXIdxIncludedFileInfo Info = { getIndexLoc(hashLoc), 467 SA.toCStr(filename), 468 static_cast<CXFile>( 469 const_cast<FileEntry *>(File)), 470 isImport, isAngled, isModuleImport }; 471 CXIdxClientFile idxFile = CB.ppIncludedFile(ClientData, &Info); 472 FileMap[File] = idxFile; 473 } 474 475 void CXIndexDataConsumer::importedModule(const ImportDecl *ImportD) { 476 if (!CB.importedASTFile) 477 return; 478 479 Module *Mod = ImportD->getImportedModule(); 480 if (!Mod) 481 return; 482 483 // If the imported module is part of the top-level module that we're 484 // indexing, it doesn't correspond to an imported AST file. 485 // FIXME: This assumes that AST files and top-level modules directly 486 // correspond, which is unlikely to remain true forever. 487 if (Module *SrcMod = ImportD->getImportedOwningModule()) 488 if (SrcMod->getTopLevelModule() == Mod->getTopLevelModule()) 489 return; 490 491 CXIdxImportedASTFileInfo Info = { 492 static_cast<CXFile>( 493 const_cast<FileEntry *>(Mod->getASTFile())), 494 Mod, 495 getIndexLoc(ImportD->getLocation()), 496 ImportD->isImplicit() 497 }; 498 CXIdxClientASTFile astFile = CB.importedASTFile(ClientData, &Info); 499 (void)astFile; 500 } 501 502 void CXIndexDataConsumer::importedPCH(const FileEntry *File) { 503 if (!CB.importedASTFile) 504 return; 505 506 CXIdxImportedASTFileInfo Info = { 507 static_cast<CXFile>( 508 const_cast<FileEntry *>(File)), 509 /*module=*/nullptr, 510 getIndexLoc(SourceLocation()), 511 /*isImplicit=*/false 512 }; 513 CXIdxClientASTFile astFile = CB.importedASTFile(ClientData, &Info); 514 (void)astFile; 515 } 516 517 void CXIndexDataConsumer::startedTranslationUnit() { 518 CXIdxClientContainer idxCont = nullptr; 519 if (CB.startedTranslationUnit) 520 idxCont = CB.startedTranslationUnit(ClientData, nullptr); 521 addContainerInMap(Ctx->getTranslationUnitDecl(), idxCont); 522 } 523 524 void CXIndexDataConsumer::indexDiagnostics() { 525 if (!hasDiagnosticCallback()) 526 return; 527 528 CXDiagnosticSetImpl *DiagSet = cxdiag::lazyCreateDiags(getCXTU()); 529 handleDiagnosticSet(DiagSet); 530 } 531 532 void CXIndexDataConsumer::handleDiagnosticSet(CXDiagnostic CXDiagSet) { 533 if (!CB.diagnostic) 534 return; 535 536 CB.diagnostic(ClientData, CXDiagSet, nullptr); 537 } 538 539 bool CXIndexDataConsumer::handleDecl(const NamedDecl *D, 540 SourceLocation Loc, CXCursor Cursor, 541 DeclInfo &DInfo, 542 const DeclContext *LexicalDC, 543 const DeclContext *SemaDC) { 544 if (!CB.indexDeclaration || !D) 545 return false; 546 if (D->isImplicit() && shouldIgnoreIfImplicit(D)) 547 return false; 548 549 ScratchAlloc SA(*this); 550 getEntityInfo(D, DInfo.EntInfo, SA); 551 if ((!shouldIndexFunctionLocalSymbols() && !DInfo.EntInfo.USR) 552 || Loc.isInvalid()) 553 return false; 554 555 if (!LexicalDC) 556 LexicalDC = D->getLexicalDeclContext(); 557 558 if (shouldSuppressRefs()) 559 markEntityOccurrenceInFile(D, Loc); 560 561 DInfo.entityInfo = &DInfo.EntInfo; 562 DInfo.cursor = Cursor; 563 DInfo.loc = getIndexLoc(Loc); 564 DInfo.isImplicit = D->isImplicit(); 565 566 DInfo.attributes = DInfo.EntInfo.attributes; 567 DInfo.numAttributes = DInfo.EntInfo.numAttributes; 568 569 if (!SemaDC) 570 SemaDC = D->getDeclContext(); 571 getContainerInfo(SemaDC, DInfo.SemanticContainer); 572 DInfo.semanticContainer = &DInfo.SemanticContainer; 573 574 if (LexicalDC == SemaDC) { 575 DInfo.lexicalContainer = &DInfo.SemanticContainer; 576 } else if (isTemplateImplicitInstantiation(D)) { 577 // Implicit instantiations have the lexical context of where they were 578 // instantiated first. We choose instead the semantic context because: 579 // 1) at the time that we see the instantiation we have not seen the 580 // function where it occurred yet. 581 // 2) the lexical context of the first instantiation is not useful 582 // information anyway. 583 DInfo.lexicalContainer = &DInfo.SemanticContainer; 584 } else { 585 getContainerInfo(LexicalDC, DInfo.LexicalContainer); 586 DInfo.lexicalContainer = &DInfo.LexicalContainer; 587 } 588 589 if (DInfo.isContainer) { 590 getContainerInfo(getEntityContainer(D), DInfo.DeclAsContainer); 591 DInfo.declAsContainer = &DInfo.DeclAsContainer; 592 } 593 594 CB.indexDeclaration(ClientData, &DInfo); 595 return true; 596 } 597 598 bool CXIndexDataConsumer::handleObjCContainer(const ObjCContainerDecl *D, 599 SourceLocation Loc, CXCursor Cursor, 600 ObjCContainerDeclInfo &ContDInfo) { 601 ContDInfo.ObjCContDeclInfo.declInfo = &ContDInfo; 602 return handleDecl(D, Loc, Cursor, ContDInfo); 603 } 604 605 bool CXIndexDataConsumer::handleFunction(const FunctionDecl *D) { 606 bool isDef = D->isThisDeclarationADefinition(); 607 bool isContainer = isDef; 608 bool isSkipped = false; 609 if (D->hasSkippedBody()) { 610 isSkipped = true; 611 isDef = true; 612 isContainer = false; 613 } 614 615 DeclInfo DInfo(!D->isFirstDecl(), isDef, isContainer); 616 if (isSkipped) 617 DInfo.flags |= CXIdxDeclFlag_Skipped; 618 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 619 } 620 621 bool CXIndexDataConsumer::handleVar(const VarDecl *D) { 622 DeclInfo DInfo(!D->isFirstDecl(), D->isThisDeclarationADefinition(), 623 /*isContainer=*/false); 624 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 625 } 626 627 bool CXIndexDataConsumer::handleField(const FieldDecl *D) { 628 DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true, 629 /*isContainer=*/false); 630 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 631 } 632 633 bool CXIndexDataConsumer::handleMSProperty(const MSPropertyDecl *D) { 634 DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true, 635 /*isContainer=*/false); 636 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 637 } 638 639 bool CXIndexDataConsumer::handleEnumerator(const EnumConstantDecl *D) { 640 DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true, 641 /*isContainer=*/false); 642 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 643 } 644 645 bool CXIndexDataConsumer::handleTagDecl(const TagDecl *D) { 646 if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(D)) 647 return handleCXXRecordDecl(CXXRD, D); 648 649 DeclInfo DInfo(!D->isFirstDecl(), D->isThisDeclarationADefinition(), 650 D->isThisDeclarationADefinition()); 651 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 652 } 653 654 bool CXIndexDataConsumer::handleTypedefName(const TypedefNameDecl *D) { 655 DeclInfo DInfo(!D->isFirstDecl(), /*isDefinition=*/true, 656 /*isContainer=*/false); 657 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 658 } 659 660 bool CXIndexDataConsumer::handleObjCInterface(const ObjCInterfaceDecl *D) { 661 // For @class forward declarations, suppress them the same way as references. 662 if (!D->isThisDeclarationADefinition()) { 663 if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, D->getLocation())) 664 return false; // already occurred. 665 666 // FIXME: This seems like the wrong definition for redeclaration. 667 bool isRedeclaration = D->hasDefinition() || D->getPreviousDecl(); 668 ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true, isRedeclaration, 669 /*isImplementation=*/false); 670 return handleObjCContainer(D, D->getLocation(), 671 MakeCursorObjCClassRef(D, D->getLocation(), 672 CXTU), 673 ContDInfo); 674 } 675 676 ScratchAlloc SA(*this); 677 678 CXIdxBaseClassInfo BaseClass; 679 EntityInfo BaseEntity; 680 BaseClass.cursor = clang_getNullCursor(); 681 if (ObjCInterfaceDecl *SuperD = D->getSuperClass()) { 682 getEntityInfo(SuperD, BaseEntity, SA); 683 SourceLocation SuperLoc = D->getSuperClassLoc(); 684 BaseClass.base = &BaseEntity; 685 BaseClass.cursor = MakeCursorObjCSuperClassRef(SuperD, SuperLoc, CXTU); 686 BaseClass.loc = getIndexLoc(SuperLoc); 687 688 if (shouldSuppressRefs()) 689 markEntityOccurrenceInFile(SuperD, SuperLoc); 690 } 691 692 ObjCProtocolList EmptyProtoList; 693 ObjCProtocolListInfo ProtInfo(D->isThisDeclarationADefinition() 694 ? D->getReferencedProtocols() 695 : EmptyProtoList, 696 *this, SA); 697 698 ObjCInterfaceDeclInfo InterInfo(D); 699 InterInfo.ObjCProtoListInfo = ProtInfo.getListInfo(); 700 InterInfo.ObjCInterDeclInfo.containerInfo = &InterInfo.ObjCContDeclInfo; 701 InterInfo.ObjCInterDeclInfo.superInfo = D->getSuperClass() ? &BaseClass 702 : nullptr; 703 InterInfo.ObjCInterDeclInfo.protocols = &InterInfo.ObjCProtoListInfo; 704 705 return handleObjCContainer(D, D->getLocation(), getCursor(D), InterInfo); 706 } 707 708 bool CXIndexDataConsumer::handleObjCImplementation( 709 const ObjCImplementationDecl *D) { 710 ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/false, 711 /*isRedeclaration=*/true, 712 /*isImplementation=*/true); 713 return handleObjCContainer(D, D->getLocation(), getCursor(D), ContDInfo); 714 } 715 716 bool CXIndexDataConsumer::handleObjCProtocol(const ObjCProtocolDecl *D) { 717 if (!D->isThisDeclarationADefinition()) { 718 if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, D->getLocation())) 719 return false; // already occurred. 720 721 // FIXME: This seems like the wrong definition for redeclaration. 722 bool isRedeclaration = D->hasDefinition() || D->getPreviousDecl(); 723 ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true, 724 isRedeclaration, 725 /*isImplementation=*/false); 726 return handleObjCContainer(D, D->getLocation(), 727 MakeCursorObjCProtocolRef(D, D->getLocation(), 728 CXTU), 729 ContDInfo); 730 } 731 732 ScratchAlloc SA(*this); 733 ObjCProtocolList EmptyProtoList; 734 ObjCProtocolListInfo ProtListInfo(D->isThisDeclarationADefinition() 735 ? D->getReferencedProtocols() 736 : EmptyProtoList, 737 *this, SA); 738 739 ObjCProtocolDeclInfo ProtInfo(D); 740 ProtInfo.ObjCProtoRefListInfo = ProtListInfo.getListInfo(); 741 742 return handleObjCContainer(D, D->getLocation(), getCursor(D), ProtInfo); 743 } 744 745 bool CXIndexDataConsumer::handleObjCCategory(const ObjCCategoryDecl *D) { 746 ScratchAlloc SA(*this); 747 748 ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/false); 749 EntityInfo ClassEntity; 750 const ObjCInterfaceDecl *IFaceD = D->getClassInterface(); 751 SourceLocation ClassLoc = D->getLocation(); 752 SourceLocation CategoryLoc = D->IsClassExtension() ? ClassLoc 753 : D->getCategoryNameLoc(); 754 getEntityInfo(IFaceD, ClassEntity, SA); 755 756 if (shouldSuppressRefs()) 757 markEntityOccurrenceInFile(IFaceD, ClassLoc); 758 759 ObjCProtocolListInfo ProtInfo(D->getReferencedProtocols(), *this, SA); 760 761 CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo; 762 if (IFaceD) { 763 CatDInfo.ObjCCatDeclInfo.objcClass = &ClassEntity; 764 CatDInfo.ObjCCatDeclInfo.classCursor = 765 MakeCursorObjCClassRef(IFaceD, ClassLoc, CXTU); 766 } else { 767 CatDInfo.ObjCCatDeclInfo.objcClass = nullptr; 768 CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor(); 769 } 770 CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(ClassLoc); 771 CatDInfo.ObjCProtoListInfo = ProtInfo.getListInfo(); 772 CatDInfo.ObjCCatDeclInfo.protocols = &CatDInfo.ObjCProtoListInfo; 773 774 return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo); 775 } 776 777 bool CXIndexDataConsumer::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) { 778 ScratchAlloc SA(*this); 779 780 const ObjCCategoryDecl *CatD = D->getCategoryDecl(); 781 ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/true); 782 EntityInfo ClassEntity; 783 const ObjCInterfaceDecl *IFaceD = CatD->getClassInterface(); 784 SourceLocation ClassLoc = D->getLocation(); 785 SourceLocation CategoryLoc = D->getCategoryNameLoc(); 786 getEntityInfo(IFaceD, ClassEntity, SA); 787 788 if (shouldSuppressRefs()) 789 markEntityOccurrenceInFile(IFaceD, ClassLoc); 790 791 CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo; 792 if (IFaceD) { 793 CatDInfo.ObjCCatDeclInfo.objcClass = &ClassEntity; 794 CatDInfo.ObjCCatDeclInfo.classCursor = 795 MakeCursorObjCClassRef(IFaceD, ClassLoc, CXTU); 796 } else { 797 CatDInfo.ObjCCatDeclInfo.objcClass = nullptr; 798 CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor(); 799 } 800 CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(ClassLoc); 801 CatDInfo.ObjCCatDeclInfo.protocols = nullptr; 802 803 return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo); 804 } 805 806 bool CXIndexDataConsumer::handleObjCMethod(const ObjCMethodDecl *D, 807 SourceLocation Loc) { 808 bool isDef = D->isThisDeclarationADefinition(); 809 bool isContainer = isDef; 810 bool isSkipped = false; 811 if (D->hasSkippedBody()) { 812 isSkipped = true; 813 isDef = true; 814 isContainer = false; 815 } 816 817 DeclInfo DInfo(!D->isCanonicalDecl(), isDef, isContainer); 818 if (isSkipped) 819 DInfo.flags |= CXIdxDeclFlag_Skipped; 820 return handleDecl(D, Loc, getCursor(D), DInfo); 821 } 822 823 bool CXIndexDataConsumer::handleSynthesizedObjCProperty( 824 const ObjCPropertyImplDecl *D) { 825 ObjCPropertyDecl *PD = D->getPropertyDecl(); 826 auto *DC = D->getDeclContext(); 827 return handleReference(PD, D->getLocation(), getCursor(D), 828 dyn_cast<NamedDecl>(DC), DC); 829 } 830 831 bool CXIndexDataConsumer::handleSynthesizedObjCMethod(const ObjCMethodDecl *D, 832 SourceLocation Loc, 833 const DeclContext *LexicalDC) { 834 DeclInfo DInfo(/*isRedeclaration=*/true, /*isDefinition=*/true, 835 /*isContainer=*/false); 836 return handleDecl(D, Loc, getCursor(D), DInfo, LexicalDC, D->getDeclContext()); 837 } 838 839 bool CXIndexDataConsumer::handleObjCProperty(const ObjCPropertyDecl *D) { 840 ScratchAlloc SA(*this); 841 842 ObjCPropertyDeclInfo DInfo; 843 EntityInfo GetterEntity; 844 EntityInfo SetterEntity; 845 846 DInfo.ObjCPropDeclInfo.declInfo = &DInfo; 847 848 if (ObjCMethodDecl *Getter = D->getGetterMethodDecl()) { 849 getEntityInfo(Getter, GetterEntity, SA); 850 DInfo.ObjCPropDeclInfo.getter = &GetterEntity; 851 } else { 852 DInfo.ObjCPropDeclInfo.getter = nullptr; 853 } 854 if (ObjCMethodDecl *Setter = D->getSetterMethodDecl()) { 855 getEntityInfo(Setter, SetterEntity, SA); 856 DInfo.ObjCPropDeclInfo.setter = &SetterEntity; 857 } else { 858 DInfo.ObjCPropDeclInfo.setter = nullptr; 859 } 860 861 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 862 } 863 864 bool CXIndexDataConsumer::handleNamespace(const NamespaceDecl *D) { 865 DeclInfo DInfo(/*isRedeclaration=*/!D->isOriginalNamespace(), 866 /*isDefinition=*/true, 867 /*isContainer=*/true); 868 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 869 } 870 871 bool CXIndexDataConsumer::handleClassTemplate(const ClassTemplateDecl *D) { 872 return handleCXXRecordDecl(D->getTemplatedDecl(), D); 873 } 874 875 bool CXIndexDataConsumer::handleFunctionTemplate(const FunctionTemplateDecl *D) { 876 DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(), 877 /*isDefinition=*/D->isThisDeclarationADefinition(), 878 /*isContainer=*/D->isThisDeclarationADefinition()); 879 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 880 } 881 882 bool CXIndexDataConsumer::handleTypeAliasTemplate(const TypeAliasTemplateDecl *D) { 883 DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(), 884 /*isDefinition=*/true, /*isContainer=*/false); 885 return handleDecl(D, D->getLocation(), getCursor(D), DInfo); 886 } 887 888 bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc, 889 const NamedDecl *Parent, 890 const DeclContext *DC, 891 const Expr *E, 892 CXIdxEntityRefKind Kind) { 893 if (!D) 894 return false; 895 896 CXCursor Cursor = E ? MakeCXCursor(E, cast<Decl>(DC), CXTU) 897 : getRefCursor(D, Loc); 898 return handleReference(D, Loc, Cursor, Parent, DC, E, Kind); 899 } 900 901 bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc, 902 CXCursor Cursor, 903 const NamedDecl *Parent, 904 const DeclContext *DC, 905 const Expr *E, 906 CXIdxEntityRefKind Kind) { 907 if (!CB.indexEntityReference) 908 return false; 909 910 if (!D) 911 return false; 912 if (Loc.isInvalid()) 913 return false; 914 if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D)) 915 return false; 916 if (isNotFromSourceFile(D->getLocation())) 917 return false; 918 if (D->isImplicit() && shouldIgnoreIfImplicit(D)) 919 return false; 920 921 if (shouldSuppressRefs()) { 922 if (markEntityOccurrenceInFile(D, Loc)) 923 return false; // already occurred. 924 } 925 926 ScratchAlloc SA(*this); 927 EntityInfo RefEntity, ParentEntity; 928 getEntityInfo(D, RefEntity, SA); 929 if (!RefEntity.USR) 930 return false; 931 932 getEntityInfo(Parent, ParentEntity, SA); 933 934 ContainerInfo Container; 935 getContainerInfo(DC, Container); 936 937 CXIdxEntityRefInfo Info = { Kind, 938 Cursor, 939 getIndexLoc(Loc), 940 &RefEntity, 941 Parent ? &ParentEntity : nullptr, 942 &Container }; 943 CB.indexEntityReference(ClientData, &Info); 944 return true; 945 } 946 947 bool CXIndexDataConsumer::isNotFromSourceFile(SourceLocation Loc) const { 948 if (Loc.isInvalid()) 949 return true; 950 SourceManager &SM = Ctx->getSourceManager(); 951 SourceLocation FileLoc = SM.getFileLoc(Loc); 952 FileID FID = SM.getFileID(FileLoc); 953 return SM.getFileEntryForID(FID) == nullptr; 954 } 955 956 void CXIndexDataConsumer::addContainerInMap(const DeclContext *DC, 957 CXIdxClientContainer container) { 958 if (!DC) 959 return; 960 961 ContainerMapTy::iterator I = ContainerMap.find(DC); 962 if (I == ContainerMap.end()) { 963 if (container) 964 ContainerMap[DC] = container; 965 return; 966 } 967 // Allow changing the container of a previously seen DeclContext so we 968 // can handle invalid user code, like a function re-definition. 969 if (container) 970 I->second = container; 971 else 972 ContainerMap.erase(I); 973 } 974 975 CXIdxClientEntity CXIndexDataConsumer::getClientEntity(const Decl *D) const { 976 if (!D) 977 return nullptr; 978 EntityMapTy::const_iterator I = EntityMap.find(D); 979 if (I == EntityMap.end()) 980 return nullptr; 981 return I->second; 982 } 983 984 void CXIndexDataConsumer::setClientEntity(const Decl *D, CXIdxClientEntity client) { 985 if (!D) 986 return; 987 EntityMap[D] = client; 988 } 989 990 bool CXIndexDataConsumer::handleCXXRecordDecl(const CXXRecordDecl *RD, 991 const NamedDecl *OrigD) { 992 if (RD->isThisDeclarationADefinition()) { 993 ScratchAlloc SA(*this); 994 CXXClassDeclInfo CXXDInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(), 995 /*isDefinition=*/RD->isThisDeclarationADefinition()); 996 CXXBasesListInfo BaseList(RD, *this, SA); 997 CXXDInfo.CXXClassInfo.declInfo = &CXXDInfo; 998 CXXDInfo.CXXClassInfo.bases = BaseList.getBases(); 999 CXXDInfo.CXXClassInfo.numBases = BaseList.getNumBases(); 1000 1001 if (shouldSuppressRefs()) { 1002 // Go through bases and mark them as referenced. 1003 for (unsigned i = 0, e = BaseList.getNumBases(); i != e; ++i) { 1004 const CXIdxBaseClassInfo *baseInfo = BaseList.getBases()[i]; 1005 if (baseInfo->base) { 1006 const NamedDecl *BaseD = BaseList.BaseEntities[i].Dcl; 1007 SourceLocation 1008 Loc = SourceLocation::getFromRawEncoding(baseInfo->loc.int_data); 1009 markEntityOccurrenceInFile(BaseD, Loc); 1010 } 1011 } 1012 } 1013 1014 return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), CXXDInfo); 1015 } 1016 1017 DeclInfo DInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(), 1018 /*isDefinition=*/RD->isThisDeclarationADefinition(), 1019 /*isContainer=*/RD->isThisDeclarationADefinition()); 1020 return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), DInfo); 1021 } 1022 1023 bool CXIndexDataConsumer::markEntityOccurrenceInFile(const NamedDecl *D, 1024 SourceLocation Loc) { 1025 if (!D || Loc.isInvalid()) 1026 return true; 1027 1028 SourceManager &SM = Ctx->getSourceManager(); 1029 D = getEntityDecl(D); 1030 1031 std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SM.getFileLoc(Loc)); 1032 FileID FID = LocInfo.first; 1033 if (FID.isInvalid()) 1034 return true; 1035 1036 const FileEntry *FE = SM.getFileEntryForID(FID); 1037 if (!FE) 1038 return true; 1039 RefFileOccurrence RefOccur(FE, D); 1040 std::pair<llvm::DenseSet<RefFileOccurrence>::iterator, bool> 1041 res = RefFileOccurrences.insert(RefOccur); 1042 return !res.second; // already in map 1043 } 1044 1045 const NamedDecl *CXIndexDataConsumer::getEntityDecl(const NamedDecl *D) const { 1046 assert(D); 1047 D = cast<NamedDecl>(D->getCanonicalDecl()); 1048 1049 if (const ObjCImplementationDecl * 1050 ImplD = dyn_cast<ObjCImplementationDecl>(D)) { 1051 return getEntityDecl(ImplD->getClassInterface()); 1052 1053 } else if (const ObjCCategoryImplDecl * 1054 CatImplD = dyn_cast<ObjCCategoryImplDecl>(D)) { 1055 return getEntityDecl(CatImplD->getCategoryDecl()); 1056 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 1057 if (FunctionTemplateDecl *TemplD = FD->getDescribedFunctionTemplate()) 1058 return getEntityDecl(TemplD); 1059 } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { 1060 if (ClassTemplateDecl *TemplD = RD->getDescribedClassTemplate()) 1061 return getEntityDecl(TemplD); 1062 } 1063 1064 return D; 1065 } 1066 1067 const DeclContext * 1068 CXIndexDataConsumer::getEntityContainer(const Decl *D) const { 1069 const DeclContext *DC = dyn_cast<DeclContext>(D); 1070 if (DC) 1071 return DC; 1072 1073 if (const ClassTemplateDecl *ClassTempl = dyn_cast<ClassTemplateDecl>(D)) { 1074 DC = ClassTempl->getTemplatedDecl(); 1075 } else if (const FunctionTemplateDecl * 1076 FuncTempl = dyn_cast<FunctionTemplateDecl>(D)) { 1077 DC = FuncTempl->getTemplatedDecl(); 1078 } 1079 1080 return DC; 1081 } 1082 1083 CXIdxClientContainer 1084 CXIndexDataConsumer::getClientContainerForDC(const DeclContext *DC) const { 1085 if (!DC) 1086 return nullptr; 1087 1088 ContainerMapTy::const_iterator I = ContainerMap.find(DC); 1089 if (I == ContainerMap.end()) 1090 return nullptr; 1091 1092 return I->second; 1093 } 1094 1095 CXIdxClientFile CXIndexDataConsumer::getIndexFile(const FileEntry *File) { 1096 if (!File) 1097 return nullptr; 1098 1099 FileMapTy::iterator FI = FileMap.find(File); 1100 if (FI != FileMap.end()) 1101 return FI->second; 1102 1103 return nullptr; 1104 } 1105 1106 CXIdxLoc CXIndexDataConsumer::getIndexLoc(SourceLocation Loc) const { 1107 CXIdxLoc idxLoc = { {nullptr, nullptr}, 0 }; 1108 if (Loc.isInvalid()) 1109 return idxLoc; 1110 1111 idxLoc.ptr_data[0] = const_cast<CXIndexDataConsumer *>(this); 1112 idxLoc.int_data = Loc.getRawEncoding(); 1113 return idxLoc; 1114 } 1115 1116 void CXIndexDataConsumer::translateLoc(SourceLocation Loc, 1117 CXIdxClientFile *indexFile, CXFile *file, 1118 unsigned *line, unsigned *column, 1119 unsigned *offset) { 1120 if (Loc.isInvalid()) 1121 return; 1122 1123 SourceManager &SM = Ctx->getSourceManager(); 1124 Loc = SM.getFileLoc(Loc); 1125 1126 std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc); 1127 FileID FID = LocInfo.first; 1128 unsigned FileOffset = LocInfo.second; 1129 1130 if (FID.isInvalid()) 1131 return; 1132 1133 const FileEntry *FE = SM.getFileEntryForID(FID); 1134 if (indexFile) 1135 *indexFile = getIndexFile(FE); 1136 if (file) 1137 *file = const_cast<FileEntry *>(FE); 1138 if (line) 1139 *line = SM.getLineNumber(FID, FileOffset); 1140 if (column) 1141 *column = SM.getColumnNumber(FID, FileOffset); 1142 if (offset) 1143 *offset = FileOffset; 1144 } 1145 1146 static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage L); 1147 static CXIdxEntityCXXTemplateKind 1148 getEntityKindFromSymbolProperties(SymbolPropertySet K); 1149 static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L); 1150 1151 void CXIndexDataConsumer::getEntityInfo(const NamedDecl *D, 1152 EntityInfo &EntityInfo, 1153 ScratchAlloc &SA) { 1154 if (!D) 1155 return; 1156 1157 D = getEntityDecl(D); 1158 EntityInfo.cursor = getCursor(D); 1159 EntityInfo.Dcl = D; 1160 EntityInfo.IndexCtx = this; 1161 1162 SymbolInfo SymInfo = getSymbolInfo(D); 1163 EntityInfo.kind = getEntityKindFromSymbolKind(SymInfo.Kind, SymInfo.Lang); 1164 EntityInfo.templateKind = getEntityKindFromSymbolProperties(SymInfo.Properties); 1165 EntityInfo.lang = getEntityLangFromSymbolLang(SymInfo.Lang); 1166 1167 if (D->hasAttrs()) { 1168 EntityInfo.AttrList = AttrListInfo::create(D, *this); 1169 EntityInfo.attributes = EntityInfo.AttrList->getAttrs(); 1170 EntityInfo.numAttributes = EntityInfo.AttrList->getNumAttrs(); 1171 } 1172 1173 if (EntityInfo.kind == CXIdxEntity_Unexposed) 1174 return; 1175 1176 if (IdentifierInfo *II = D->getIdentifier()) { 1177 EntityInfo.name = SA.toCStr(II->getName()); 1178 1179 } else if (isa<TagDecl>(D) || isa<FieldDecl>(D) || isa<NamespaceDecl>(D)) { 1180 EntityInfo.name = nullptr; // anonymous tag/field/namespace. 1181 1182 } else { 1183 SmallString<256> StrBuf; 1184 { 1185 llvm::raw_svector_ostream OS(StrBuf); 1186 D->printName(OS); 1187 } 1188 EntityInfo.name = SA.copyCStr(StrBuf.str()); 1189 } 1190 1191 { 1192 SmallString<512> StrBuf; 1193 bool Ignore = getDeclCursorUSR(D, StrBuf); 1194 if (Ignore) { 1195 EntityInfo.USR = nullptr; 1196 } else { 1197 EntityInfo.USR = SA.copyCStr(StrBuf.str()); 1198 } 1199 } 1200 } 1201 1202 void CXIndexDataConsumer::getContainerInfo(const DeclContext *DC, 1203 ContainerInfo &ContInfo) { 1204 ContInfo.cursor = getCursor(cast<Decl>(DC)); 1205 ContInfo.DC = DC; 1206 ContInfo.IndexCtx = this; 1207 } 1208 1209 CXCursor CXIndexDataConsumer::getRefCursor(const NamedDecl *D, SourceLocation Loc) { 1210 if (const TypeDecl *TD = dyn_cast<TypeDecl>(D)) 1211 return MakeCursorTypeRef(TD, Loc, CXTU); 1212 if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) 1213 return MakeCursorObjCClassRef(ID, Loc, CXTU); 1214 if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) 1215 return MakeCursorObjCProtocolRef(PD, Loc, CXTU); 1216 if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) 1217 return MakeCursorTemplateRef(Template, Loc, CXTU); 1218 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(D)) 1219 return MakeCursorNamespaceRef(Namespace, Loc, CXTU); 1220 if (const NamespaceAliasDecl *Namespace = dyn_cast<NamespaceAliasDecl>(D)) 1221 return MakeCursorNamespaceRef(Namespace, Loc, CXTU); 1222 if (const FieldDecl *Field = dyn_cast<FieldDecl>(D)) 1223 return MakeCursorMemberRef(Field, Loc, CXTU); 1224 if (const VarDecl *Var = dyn_cast<VarDecl>(D)) 1225 return MakeCursorVariableRef(Var, Loc, CXTU); 1226 1227 return clang_getNullCursor(); 1228 } 1229 1230 bool CXIndexDataConsumer::shouldIgnoreIfImplicit(const Decl *D) { 1231 if (isa<ObjCInterfaceDecl>(D)) 1232 return false; 1233 if (isa<ObjCCategoryDecl>(D)) 1234 return false; 1235 if (isa<ObjCIvarDecl>(D)) 1236 return false; 1237 if (isa<ObjCMethodDecl>(D)) 1238 return false; 1239 if (isa<ImportDecl>(D)) 1240 return false; 1241 return true; 1242 } 1243 1244 bool CXIndexDataConsumer::isTemplateImplicitInstantiation(const Decl *D) { 1245 if (const ClassTemplateSpecializationDecl * 1246 SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) { 1247 return SD->getSpecializationKind() == TSK_ImplicitInstantiation; 1248 } 1249 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 1250 return FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation; 1251 } 1252 return false; 1253 } 1254 1255 static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage Lang) { 1256 switch (K) { 1257 case SymbolKind::Unknown: 1258 case SymbolKind::Module: 1259 case SymbolKind::Macro: 1260 case SymbolKind::ClassProperty: 1261 case SymbolKind::Using: 1262 return CXIdxEntity_Unexposed; 1263 1264 case SymbolKind::Enum: return CXIdxEntity_Enum; 1265 case SymbolKind::Struct: return CXIdxEntity_Struct; 1266 case SymbolKind::Union: return CXIdxEntity_Union; 1267 case SymbolKind::TypeAlias: 1268 if (Lang == SymbolLanguage::CXX) 1269 return CXIdxEntity_CXXTypeAlias; 1270 return CXIdxEntity_Typedef; 1271 case SymbolKind::Function: return CXIdxEntity_Function; 1272 case SymbolKind::Variable: return CXIdxEntity_Variable; 1273 case SymbolKind::Field: 1274 if (Lang == SymbolLanguage::ObjC) 1275 return CXIdxEntity_ObjCIvar; 1276 return CXIdxEntity_Field; 1277 case SymbolKind::EnumConstant: return CXIdxEntity_EnumConstant; 1278 case SymbolKind::Class: 1279 if (Lang == SymbolLanguage::ObjC) 1280 return CXIdxEntity_ObjCClass; 1281 return CXIdxEntity_CXXClass; 1282 case SymbolKind::Protocol: 1283 if (Lang == SymbolLanguage::ObjC) 1284 return CXIdxEntity_ObjCProtocol; 1285 return CXIdxEntity_CXXInterface; 1286 case SymbolKind::Extension: return CXIdxEntity_ObjCCategory; 1287 case SymbolKind::InstanceMethod: 1288 if (Lang == SymbolLanguage::ObjC) 1289 return CXIdxEntity_ObjCInstanceMethod; 1290 return CXIdxEntity_CXXInstanceMethod; 1291 case SymbolKind::ClassMethod: return CXIdxEntity_ObjCClassMethod; 1292 case SymbolKind::StaticMethod: return CXIdxEntity_CXXStaticMethod; 1293 case SymbolKind::InstanceProperty: return CXIdxEntity_ObjCProperty; 1294 case SymbolKind::StaticProperty: return CXIdxEntity_CXXStaticVariable; 1295 case SymbolKind::Namespace: return CXIdxEntity_CXXNamespace; 1296 case SymbolKind::NamespaceAlias: return CXIdxEntity_CXXNamespaceAlias; 1297 case SymbolKind::Constructor: return CXIdxEntity_CXXConstructor; 1298 case SymbolKind::Destructor: return CXIdxEntity_CXXDestructor; 1299 case SymbolKind::ConversionFunction: return CXIdxEntity_CXXConversionFunction; 1300 case SymbolKind::Parameter: return CXIdxEntity_Variable; 1301 } 1302 llvm_unreachable("invalid symbol kind"); 1303 } 1304 1305 static CXIdxEntityCXXTemplateKind 1306 getEntityKindFromSymbolProperties(SymbolPropertySet K) { 1307 if (K & (unsigned)SymbolProperty::TemplatePartialSpecialization) 1308 return CXIdxEntity_TemplatePartialSpecialization; 1309 if (K & (unsigned)SymbolProperty::TemplateSpecialization) 1310 return CXIdxEntity_TemplateSpecialization; 1311 if (K & (unsigned)SymbolProperty::Generic) 1312 return CXIdxEntity_Template; 1313 return CXIdxEntity_NonTemplate; 1314 } 1315 1316 static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L) { 1317 switch (L) { 1318 case SymbolLanguage::C: return CXIdxEntityLang_C; 1319 case SymbolLanguage::ObjC: return CXIdxEntityLang_ObjC; 1320 case SymbolLanguage::CXX: return CXIdxEntityLang_CXX; 1321 case SymbolLanguage::Swift: return CXIdxEntityLang_Swift; 1322 } 1323 llvm_unreachable("invalid symbol language"); 1324 } 1325