brintos

brintos / llvm-project-archived public Read only

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