17330f729Sjoerg //===- CXIndexDataConsumer.cpp - Index data consumer for libclang----------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg
97330f729Sjoerg #include "CXIndexDataConsumer.h"
107330f729Sjoerg #include "CIndexDiagnostic.h"
117330f729Sjoerg #include "CXTranslationUnit.h"
127330f729Sjoerg #include "clang/AST/Attr.h"
137330f729Sjoerg #include "clang/AST/DeclCXX.h"
147330f729Sjoerg #include "clang/AST/DeclTemplate.h"
157330f729Sjoerg #include "clang/AST/DeclVisitor.h"
167330f729Sjoerg #include "clang/Frontend/ASTUnit.h"
177330f729Sjoerg
187330f729Sjoerg using namespace clang;
197330f729Sjoerg using namespace clang::index;
207330f729Sjoerg using namespace cxindex;
217330f729Sjoerg using namespace cxcursor;
227330f729Sjoerg
237330f729Sjoerg namespace {
247330f729Sjoerg class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
257330f729Sjoerg CXIndexDataConsumer &DataConsumer;
267330f729Sjoerg SourceLocation DeclLoc;
277330f729Sjoerg const DeclContext *LexicalDC;
287330f729Sjoerg
297330f729Sjoerg public:
IndexingDeclVisitor(CXIndexDataConsumer & dataConsumer,SourceLocation Loc,const DeclContext * lexicalDC)307330f729Sjoerg IndexingDeclVisitor(CXIndexDataConsumer &dataConsumer, SourceLocation Loc,
317330f729Sjoerg const DeclContext *lexicalDC)
327330f729Sjoerg : DataConsumer(dataConsumer), DeclLoc(Loc), LexicalDC(lexicalDC) { }
337330f729Sjoerg
VisitFunctionDecl(const FunctionDecl * D)347330f729Sjoerg bool VisitFunctionDecl(const FunctionDecl *D) {
357330f729Sjoerg DataConsumer.handleFunction(D);
367330f729Sjoerg return true;
377330f729Sjoerg }
387330f729Sjoerg
VisitVarDecl(const VarDecl * D)397330f729Sjoerg bool VisitVarDecl(const VarDecl *D) {
407330f729Sjoerg DataConsumer.handleVar(D);
417330f729Sjoerg return true;
427330f729Sjoerg }
437330f729Sjoerg
VisitFieldDecl(const FieldDecl * D)447330f729Sjoerg bool VisitFieldDecl(const FieldDecl *D) {
457330f729Sjoerg DataConsumer.handleField(D);
467330f729Sjoerg return true;
477330f729Sjoerg }
487330f729Sjoerg
VisitMSPropertyDecl(const MSPropertyDecl * D)497330f729Sjoerg bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
507330f729Sjoerg return true;
517330f729Sjoerg }
527330f729Sjoerg
VisitEnumConstantDecl(const EnumConstantDecl * D)537330f729Sjoerg bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
547330f729Sjoerg DataConsumer.handleEnumerator(D);
557330f729Sjoerg return true;
567330f729Sjoerg }
577330f729Sjoerg
VisitTypedefNameDecl(const TypedefNameDecl * D)587330f729Sjoerg bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
597330f729Sjoerg DataConsumer.handleTypedefName(D);
607330f729Sjoerg return true;
617330f729Sjoerg }
627330f729Sjoerg
VisitTagDecl(const TagDecl * D)637330f729Sjoerg bool VisitTagDecl(const TagDecl *D) {
647330f729Sjoerg DataConsumer.handleTagDecl(D);
657330f729Sjoerg return true;
667330f729Sjoerg }
677330f729Sjoerg
VisitObjCInterfaceDecl(const ObjCInterfaceDecl * D)687330f729Sjoerg bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
697330f729Sjoerg DataConsumer.handleObjCInterface(D);
707330f729Sjoerg return true;
717330f729Sjoerg }
727330f729Sjoerg
VisitObjCProtocolDecl(const ObjCProtocolDecl * D)737330f729Sjoerg bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
747330f729Sjoerg DataConsumer.handleObjCProtocol(D);
757330f729Sjoerg return true;
767330f729Sjoerg }
777330f729Sjoerg
VisitObjCImplementationDecl(const ObjCImplementationDecl * D)787330f729Sjoerg bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
797330f729Sjoerg DataConsumer.handleObjCImplementation(D);
807330f729Sjoerg return true;
817330f729Sjoerg }
827330f729Sjoerg
VisitObjCCategoryDecl(const ObjCCategoryDecl * D)837330f729Sjoerg bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
847330f729Sjoerg DataConsumer.handleObjCCategory(D);
857330f729Sjoerg return true;
867330f729Sjoerg }
877330f729Sjoerg
VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl * D)887330f729Sjoerg bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
897330f729Sjoerg DataConsumer.handleObjCCategoryImpl(D);
907330f729Sjoerg return true;
917330f729Sjoerg }
927330f729Sjoerg
VisitObjCMethodDecl(const ObjCMethodDecl * D)937330f729Sjoerg bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
947330f729Sjoerg if (isa<ObjCImplDecl>(LexicalDC) && !D->isThisDeclarationADefinition())
957330f729Sjoerg DataConsumer.handleSynthesizedObjCMethod(D, DeclLoc, LexicalDC);
967330f729Sjoerg else
977330f729Sjoerg DataConsumer.handleObjCMethod(D, DeclLoc);
987330f729Sjoerg return true;
997330f729Sjoerg }
1007330f729Sjoerg
VisitObjCPropertyDecl(const ObjCPropertyDecl * D)1017330f729Sjoerg bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
1027330f729Sjoerg DataConsumer.handleObjCProperty(D);
1037330f729Sjoerg return true;
1047330f729Sjoerg }
1057330f729Sjoerg
VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl * D)1067330f729Sjoerg bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
1077330f729Sjoerg DataConsumer.handleSynthesizedObjCProperty(D);
1087330f729Sjoerg return true;
1097330f729Sjoerg }
1107330f729Sjoerg
VisitNamespaceDecl(const NamespaceDecl * D)1117330f729Sjoerg bool VisitNamespaceDecl(const NamespaceDecl *D) {
1127330f729Sjoerg DataConsumer.handleNamespace(D);
1137330f729Sjoerg return true;
1147330f729Sjoerg }
1157330f729Sjoerg
VisitUsingDecl(const UsingDecl * D)1167330f729Sjoerg bool VisitUsingDecl(const UsingDecl *D) {
1177330f729Sjoerg return true;
1187330f729Sjoerg }
1197330f729Sjoerg
VisitUsingDirectiveDecl(const UsingDirectiveDecl * D)1207330f729Sjoerg bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
1217330f729Sjoerg return true;
1227330f729Sjoerg }
1237330f729Sjoerg
VisitClassTemplateDecl(const ClassTemplateDecl * D)1247330f729Sjoerg bool VisitClassTemplateDecl(const ClassTemplateDecl *D) {
1257330f729Sjoerg DataConsumer.handleClassTemplate(D);
1267330f729Sjoerg return true;
1277330f729Sjoerg }
1287330f729Sjoerg
VisitClassTemplateSpecializationDecl(const ClassTemplateSpecializationDecl * D)1297330f729Sjoerg bool VisitClassTemplateSpecializationDecl(const
1307330f729Sjoerg ClassTemplateSpecializationDecl *D) {
1317330f729Sjoerg DataConsumer.handleTagDecl(D);
1327330f729Sjoerg return true;
1337330f729Sjoerg }
1347330f729Sjoerg
VisitFunctionTemplateDecl(const FunctionTemplateDecl * D)1357330f729Sjoerg bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
1367330f729Sjoerg DataConsumer.handleFunctionTemplate(D);
1377330f729Sjoerg return true;
1387330f729Sjoerg }
1397330f729Sjoerg
VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl * D)1407330f729Sjoerg bool VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) {
1417330f729Sjoerg DataConsumer.handleTypeAliasTemplate(D);
1427330f729Sjoerg return true;
1437330f729Sjoerg }
1447330f729Sjoerg
VisitImportDecl(const ImportDecl * D)1457330f729Sjoerg bool VisitImportDecl(const ImportDecl *D) {
1467330f729Sjoerg DataConsumer.importedModule(D);
1477330f729Sjoerg return true;
1487330f729Sjoerg }
1497330f729Sjoerg };
1507330f729Sjoerg
getSymbolRole(SymbolRoleSet Role)1517330f729Sjoerg CXSymbolRole getSymbolRole(SymbolRoleSet Role) {
1527330f729Sjoerg // CXSymbolRole mirrors low 9 bits of clang::index::SymbolRole.
1537330f729Sjoerg return CXSymbolRole(static_cast<uint32_t>(Role) & ((1 << 9) - 1));
1547330f729Sjoerg }
1557330f729Sjoerg }
1567330f729Sjoerg
handleDeclOccurrence(const Decl * D,SymbolRoleSet Roles,ArrayRef<SymbolRelation> Relations,SourceLocation Loc,ASTNodeInfo ASTNode)157*e038c9c4Sjoerg bool CXIndexDataConsumer::handleDeclOccurrence(
1587330f729Sjoerg const Decl *D, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations,
1597330f729Sjoerg SourceLocation Loc, ASTNodeInfo ASTNode) {
1607330f729Sjoerg Loc = getASTContext().getSourceManager().getFileLoc(Loc);
1617330f729Sjoerg
1627330f729Sjoerg if (Roles & (unsigned)SymbolRole::Reference) {
1637330f729Sjoerg const NamedDecl *ND = dyn_cast<NamedDecl>(D);
1647330f729Sjoerg if (!ND)
1657330f729Sjoerg return true;
1667330f729Sjoerg
1677330f729Sjoerg if (auto *ObjCID = dyn_cast_or_null<ObjCInterfaceDecl>(ASTNode.OrigD)) {
1687330f729Sjoerg if (!ObjCID->isThisDeclarationADefinition() &&
1697330f729Sjoerg ObjCID->getLocation() == Loc) {
1707330f729Sjoerg // The libclang API treats this as ObjCClassRef declaration.
1717330f729Sjoerg IndexingDeclVisitor(*this, Loc, nullptr).Visit(ObjCID);
1727330f729Sjoerg return true;
1737330f729Sjoerg }
1747330f729Sjoerg }
1757330f729Sjoerg if (auto *ObjCPD = dyn_cast_or_null<ObjCProtocolDecl>(ASTNode.OrigD)) {
1767330f729Sjoerg if (!ObjCPD->isThisDeclarationADefinition() &&
1777330f729Sjoerg ObjCPD->getLocation() == Loc) {
1787330f729Sjoerg // The libclang API treats this as ObjCProtocolRef declaration.
1797330f729Sjoerg IndexingDeclVisitor(*this, Loc, nullptr).Visit(ObjCPD);
1807330f729Sjoerg return true;
1817330f729Sjoerg }
1827330f729Sjoerg }
1837330f729Sjoerg
1847330f729Sjoerg CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct;
1857330f729Sjoerg if (Roles & (unsigned)SymbolRole::Implicit) {
1867330f729Sjoerg Kind = CXIdxEntityRef_Implicit;
1877330f729Sjoerg }
1887330f729Sjoerg CXSymbolRole CXRole = getSymbolRole(Roles);
1897330f729Sjoerg
1907330f729Sjoerg CXCursor Cursor;
1917330f729Sjoerg if (ASTNode.OrigE) {
1927330f729Sjoerg Cursor = cxcursor::MakeCXCursor(ASTNode.OrigE,
1937330f729Sjoerg cast<Decl>(ASTNode.ContainerDC),
1947330f729Sjoerg getCXTU());
1957330f729Sjoerg } else {
1967330f729Sjoerg if (ASTNode.OrigD) {
1977330f729Sjoerg if (auto *OrigND = dyn_cast<NamedDecl>(ASTNode.OrigD))
1987330f729Sjoerg Cursor = getRefCursor(OrigND, Loc);
1997330f729Sjoerg else
2007330f729Sjoerg Cursor = MakeCXCursor(ASTNode.OrigD, CXTU);
2017330f729Sjoerg } else {
2027330f729Sjoerg Cursor = getRefCursor(ND, Loc);
2037330f729Sjoerg }
2047330f729Sjoerg }
2057330f729Sjoerg handleReference(ND, Loc, Cursor,
2067330f729Sjoerg dyn_cast_or_null<NamedDecl>(ASTNode.Parent),
2077330f729Sjoerg ASTNode.ContainerDC, ASTNode.OrigE, Kind, CXRole);
2087330f729Sjoerg
2097330f729Sjoerg } else {
2107330f729Sjoerg const DeclContext *LexicalDC = ASTNode.ContainerDC;
2117330f729Sjoerg if (!LexicalDC) {
2127330f729Sjoerg for (const auto &SymRel : Relations) {
2137330f729Sjoerg if (SymRel.Roles & (unsigned)SymbolRole::RelationChildOf)
2147330f729Sjoerg LexicalDC = dyn_cast<DeclContext>(SymRel.RelatedSymbol);
2157330f729Sjoerg }
2167330f729Sjoerg }
2177330f729Sjoerg IndexingDeclVisitor(*this, Loc, LexicalDC).Visit(ASTNode.OrigD);
2187330f729Sjoerg }
2197330f729Sjoerg
2207330f729Sjoerg return !shouldAbort();
2217330f729Sjoerg }
2227330f729Sjoerg
handleModuleOccurrence(const ImportDecl * ImportD,const Module * Mod,SymbolRoleSet Roles,SourceLocation Loc)223*e038c9c4Sjoerg bool CXIndexDataConsumer::handleModuleOccurrence(const ImportDecl *ImportD,
2247330f729Sjoerg const Module *Mod,
2257330f729Sjoerg SymbolRoleSet Roles,
2267330f729Sjoerg SourceLocation Loc) {
2277330f729Sjoerg if (Roles & (SymbolRoleSet)SymbolRole::Declaration)
2287330f729Sjoerg IndexingDeclVisitor(*this, SourceLocation(), nullptr).Visit(ImportD);
2297330f729Sjoerg return !shouldAbort();
2307330f729Sjoerg }
2317330f729Sjoerg
finish()2327330f729Sjoerg void CXIndexDataConsumer::finish() {
2337330f729Sjoerg indexDiagnostics();
2347330f729Sjoerg }
2357330f729Sjoerg
2367330f729Sjoerg
ObjCProtocolListInfo(const ObjCProtocolList & ProtList,CXIndexDataConsumer & IdxCtx,ScratchAlloc & SA)2377330f729Sjoerg CXIndexDataConsumer::ObjCProtocolListInfo::ObjCProtocolListInfo(
2387330f729Sjoerg const ObjCProtocolList &ProtList,
2397330f729Sjoerg CXIndexDataConsumer &IdxCtx,
2407330f729Sjoerg ScratchAlloc &SA) {
2417330f729Sjoerg ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
2427330f729Sjoerg for (ObjCInterfaceDecl::protocol_iterator
2437330f729Sjoerg I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
2447330f729Sjoerg SourceLocation Loc = *LI;
2457330f729Sjoerg ObjCProtocolDecl *PD = *I;
2467330f729Sjoerg ProtEntities.push_back(EntityInfo());
2477330f729Sjoerg IdxCtx.getEntityInfo(PD, ProtEntities.back(), SA);
2487330f729Sjoerg CXIdxObjCProtocolRefInfo ProtInfo = { nullptr,
2497330f729Sjoerg MakeCursorObjCProtocolRef(PD, Loc, IdxCtx.CXTU),
2507330f729Sjoerg IdxCtx.getIndexLoc(Loc) };
2517330f729Sjoerg ProtInfos.push_back(ProtInfo);
2527330f729Sjoerg
2537330f729Sjoerg if (IdxCtx.shouldSuppressRefs())
2547330f729Sjoerg IdxCtx.markEntityOccurrenceInFile(PD, Loc);
2557330f729Sjoerg }
2567330f729Sjoerg
2577330f729Sjoerg for (unsigned i = 0, e = ProtInfos.size(); i != e; ++i)
2587330f729Sjoerg ProtInfos[i].protocol = &ProtEntities[i];
2597330f729Sjoerg
2607330f729Sjoerg for (unsigned i = 0, e = ProtInfos.size(); i != e; ++i)
2617330f729Sjoerg Prots.push_back(&ProtInfos[i]);
2627330f729Sjoerg }
2637330f729Sjoerg
2647330f729Sjoerg
IBOutletCollectionInfo(const IBOutletCollectionInfo & other)2657330f729Sjoerg IBOutletCollectionInfo::IBOutletCollectionInfo(
2667330f729Sjoerg const IBOutletCollectionInfo &other)
2677330f729Sjoerg : AttrInfo(CXIdxAttr_IBOutletCollection, other.cursor, other.loc, other.A) {
2687330f729Sjoerg
2697330f729Sjoerg IBCollInfo.attrInfo = this;
2707330f729Sjoerg IBCollInfo.classCursor = other.IBCollInfo.classCursor;
2717330f729Sjoerg IBCollInfo.classLoc = other.IBCollInfo.classLoc;
2727330f729Sjoerg if (other.IBCollInfo.objcClass) {
2737330f729Sjoerg ClassInfo = other.ClassInfo;
2747330f729Sjoerg IBCollInfo.objcClass = &ClassInfo;
2757330f729Sjoerg } else
2767330f729Sjoerg IBCollInfo.objcClass = nullptr;
2777330f729Sjoerg }
2787330f729Sjoerg
AttrListInfo(const Decl * D,CXIndexDataConsumer & IdxCtx)2797330f729Sjoerg AttrListInfo::AttrListInfo(const Decl *D, CXIndexDataConsumer &IdxCtx)
2807330f729Sjoerg : SA(IdxCtx), ref_cnt(0) {
2817330f729Sjoerg
2827330f729Sjoerg if (!D->hasAttrs())
2837330f729Sjoerg return;
2847330f729Sjoerg
2857330f729Sjoerg for (const auto *A : D->attrs()) {
2867330f729Sjoerg CXCursor C = MakeCXCursor(A, D, IdxCtx.CXTU);
2877330f729Sjoerg CXIdxLoc Loc = IdxCtx.getIndexLoc(A->getLocation());
2887330f729Sjoerg switch (C.kind) {
2897330f729Sjoerg default:
2907330f729Sjoerg Attrs.push_back(AttrInfo(CXIdxAttr_Unexposed, C, Loc, A));
2917330f729Sjoerg break;
2927330f729Sjoerg case CXCursor_IBActionAttr:
2937330f729Sjoerg Attrs.push_back(AttrInfo(CXIdxAttr_IBAction, C, Loc, A));
2947330f729Sjoerg break;
2957330f729Sjoerg case CXCursor_IBOutletAttr:
2967330f729Sjoerg Attrs.push_back(AttrInfo(CXIdxAttr_IBOutlet, C, Loc, A));
2977330f729Sjoerg break;
2987330f729Sjoerg case CXCursor_IBOutletCollectionAttr:
2997330f729Sjoerg IBCollAttrs.push_back(IBOutletCollectionInfo(C, Loc, A));
3007330f729Sjoerg break;
3017330f729Sjoerg }
3027330f729Sjoerg }
3037330f729Sjoerg
3047330f729Sjoerg for (unsigned i = 0, e = IBCollAttrs.size(); i != e; ++i) {
3057330f729Sjoerg IBOutletCollectionInfo &IBInfo = IBCollAttrs[i];
3067330f729Sjoerg CXAttrs.push_back(&IBInfo);
3077330f729Sjoerg
3087330f729Sjoerg const IBOutletCollectionAttr *
3097330f729Sjoerg IBAttr = cast<IBOutletCollectionAttr>(IBInfo.A);
3107330f729Sjoerg SourceLocation InterfaceLocStart =
3117330f729Sjoerg IBAttr->getInterfaceLoc()->getTypeLoc().getBeginLoc();
3127330f729Sjoerg IBInfo.IBCollInfo.attrInfo = &IBInfo;
3137330f729Sjoerg IBInfo.IBCollInfo.classLoc = IdxCtx.getIndexLoc(InterfaceLocStart);
3147330f729Sjoerg IBInfo.IBCollInfo.objcClass = nullptr;
3157330f729Sjoerg IBInfo.IBCollInfo.classCursor = clang_getNullCursor();
3167330f729Sjoerg QualType Ty = IBAttr->getInterface();
3177330f729Sjoerg if (const ObjCObjectType *ObjectTy = Ty->getAs<ObjCObjectType>()) {
3187330f729Sjoerg if (const ObjCInterfaceDecl *InterD = ObjectTy->getInterface()) {
3197330f729Sjoerg IdxCtx.getEntityInfo(InterD, IBInfo.ClassInfo, SA);
3207330f729Sjoerg IBInfo.IBCollInfo.objcClass = &IBInfo.ClassInfo;
3217330f729Sjoerg IBInfo.IBCollInfo.classCursor =
3227330f729Sjoerg MakeCursorObjCClassRef(InterD, InterfaceLocStart, IdxCtx.CXTU);
3237330f729Sjoerg }
3247330f729Sjoerg }
3257330f729Sjoerg }
3267330f729Sjoerg
3277330f729Sjoerg for (unsigned i = 0, e = Attrs.size(); i != e; ++i)
3287330f729Sjoerg CXAttrs.push_back(&Attrs[i]);
3297330f729Sjoerg }
3307330f729Sjoerg
3317330f729Sjoerg IntrusiveRefCntPtr<AttrListInfo>
create(const Decl * D,CXIndexDataConsumer & IdxCtx)3327330f729Sjoerg AttrListInfo::create(const Decl *D, CXIndexDataConsumer &IdxCtx) {
3337330f729Sjoerg ScratchAlloc SA(IdxCtx);
3347330f729Sjoerg AttrListInfo *attrs = SA.allocate<AttrListInfo>();
3357330f729Sjoerg return new (attrs) AttrListInfo(D, IdxCtx);
3367330f729Sjoerg }
3377330f729Sjoerg
CXXBasesListInfo(const CXXRecordDecl * D,CXIndexDataConsumer & IdxCtx,ScratchAlloc & SA)3387330f729Sjoerg CXIndexDataConsumer::CXXBasesListInfo::CXXBasesListInfo(const CXXRecordDecl *D,
3397330f729Sjoerg CXIndexDataConsumer &IdxCtx,
3407330f729Sjoerg ScratchAlloc &SA) {
3417330f729Sjoerg for (const auto &Base : D->bases()) {
3427330f729Sjoerg BaseEntities.push_back(EntityInfo());
3437330f729Sjoerg const NamedDecl *BaseD = nullptr;
3447330f729Sjoerg QualType T = Base.getType();
3457330f729Sjoerg SourceLocation Loc = getBaseLoc(Base);
3467330f729Sjoerg
3477330f729Sjoerg if (const TypedefType *TDT = T->getAs<TypedefType>()) {
3487330f729Sjoerg BaseD = TDT->getDecl();
3497330f729Sjoerg } else if (const TemplateSpecializationType *
3507330f729Sjoerg TST = T->getAs<TemplateSpecializationType>()) {
3517330f729Sjoerg BaseD = TST->getTemplateName().getAsTemplateDecl();
3527330f729Sjoerg } else if (const RecordType *RT = T->getAs<RecordType>()) {
3537330f729Sjoerg BaseD = RT->getDecl();
3547330f729Sjoerg }
3557330f729Sjoerg
3567330f729Sjoerg if (BaseD)
3577330f729Sjoerg IdxCtx.getEntityInfo(BaseD, BaseEntities.back(), SA);
3587330f729Sjoerg CXIdxBaseClassInfo BaseInfo = { nullptr,
3597330f729Sjoerg MakeCursorCXXBaseSpecifier(&Base, IdxCtx.CXTU),
3607330f729Sjoerg IdxCtx.getIndexLoc(Loc) };
3617330f729Sjoerg BaseInfos.push_back(BaseInfo);
3627330f729Sjoerg }
3637330f729Sjoerg
3647330f729Sjoerg for (unsigned i = 0, e = BaseInfos.size(); i != e; ++i) {
3657330f729Sjoerg if (BaseEntities[i].name && BaseEntities[i].USR)
3667330f729Sjoerg BaseInfos[i].base = &BaseEntities[i];
3677330f729Sjoerg }
3687330f729Sjoerg
3697330f729Sjoerg for (unsigned i = 0, e = BaseInfos.size(); i != e; ++i)
3707330f729Sjoerg CXBases.push_back(&BaseInfos[i]);
3717330f729Sjoerg }
3727330f729Sjoerg
getBaseLoc(const CXXBaseSpecifier & Base) const3737330f729Sjoerg SourceLocation CXIndexDataConsumer::CXXBasesListInfo::getBaseLoc(
3747330f729Sjoerg const CXXBaseSpecifier &Base) const {
3757330f729Sjoerg SourceLocation Loc = Base.getSourceRange().getBegin();
3767330f729Sjoerg TypeLoc TL;
3777330f729Sjoerg if (Base.getTypeSourceInfo())
3787330f729Sjoerg TL = Base.getTypeSourceInfo()->getTypeLoc();
3797330f729Sjoerg if (TL.isNull())
3807330f729Sjoerg return Loc;
3817330f729Sjoerg
3827330f729Sjoerg if (QualifiedTypeLoc QL = TL.getAs<QualifiedTypeLoc>())
3837330f729Sjoerg TL = QL.getUnqualifiedLoc();
3847330f729Sjoerg
3857330f729Sjoerg if (ElaboratedTypeLoc EL = TL.getAs<ElaboratedTypeLoc>())
3867330f729Sjoerg return EL.getNamedTypeLoc().getBeginLoc();
3877330f729Sjoerg if (DependentNameTypeLoc DL = TL.getAs<DependentNameTypeLoc>())
3887330f729Sjoerg return DL.getNameLoc();
3897330f729Sjoerg if (DependentTemplateSpecializationTypeLoc DTL =
3907330f729Sjoerg TL.getAs<DependentTemplateSpecializationTypeLoc>())
3917330f729Sjoerg return DTL.getTemplateNameLoc();
3927330f729Sjoerg
3937330f729Sjoerg return Loc;
3947330f729Sjoerg }
3957330f729Sjoerg
toCStr(StringRef Str)3967330f729Sjoerg const char *ScratchAlloc::toCStr(StringRef Str) {
3977330f729Sjoerg if (Str.empty())
3987330f729Sjoerg return "";
3997330f729Sjoerg if (Str.data()[Str.size()] == '\0')
4007330f729Sjoerg return Str.data();
4017330f729Sjoerg return copyCStr(Str);
4027330f729Sjoerg }
4037330f729Sjoerg
copyCStr(StringRef Str)4047330f729Sjoerg const char *ScratchAlloc::copyCStr(StringRef Str) {
4057330f729Sjoerg char *buf = IdxCtx.StrScratch.Allocate<char>(Str.size() + 1);
4067330f729Sjoerg std::uninitialized_copy(Str.begin(), Str.end(), buf);
4077330f729Sjoerg buf[Str.size()] = '\0';
4087330f729Sjoerg return buf;
4097330f729Sjoerg }
4107330f729Sjoerg
setASTContext(ASTContext & ctx)4117330f729Sjoerg void CXIndexDataConsumer::setASTContext(ASTContext &ctx) {
4127330f729Sjoerg Ctx = &ctx;
4137330f729Sjoerg cxtu::getASTUnit(CXTU)->setASTContext(&ctx);
4147330f729Sjoerg }
4157330f729Sjoerg
setPreprocessor(std::shared_ptr<Preprocessor> PP)4167330f729Sjoerg void CXIndexDataConsumer::setPreprocessor(std::shared_ptr<Preprocessor> PP) {
4177330f729Sjoerg cxtu::getASTUnit(CXTU)->setPreprocessor(std::move(PP));
4187330f729Sjoerg }
4197330f729Sjoerg
isFunctionLocalDecl(const Decl * D)4207330f729Sjoerg bool CXIndexDataConsumer::isFunctionLocalDecl(const Decl *D) {
4217330f729Sjoerg assert(D);
4227330f729Sjoerg
4237330f729Sjoerg if (!D->getParentFunctionOrMethod())
4247330f729Sjoerg return false;
4257330f729Sjoerg
4267330f729Sjoerg if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
4277330f729Sjoerg switch (ND->getFormalLinkage()) {
4287330f729Sjoerg case NoLinkage:
4297330f729Sjoerg case InternalLinkage:
4307330f729Sjoerg return true;
4317330f729Sjoerg case VisibleNoLinkage:
4327330f729Sjoerg case ModuleInternalLinkage:
4337330f729Sjoerg case UniqueExternalLinkage:
4347330f729Sjoerg llvm_unreachable("Not a sema linkage");
4357330f729Sjoerg case ModuleLinkage:
4367330f729Sjoerg case ExternalLinkage:
4377330f729Sjoerg return false;
4387330f729Sjoerg }
4397330f729Sjoerg }
4407330f729Sjoerg
4417330f729Sjoerg return true;
4427330f729Sjoerg }
4437330f729Sjoerg
shouldAbort()4447330f729Sjoerg bool CXIndexDataConsumer::shouldAbort() {
4457330f729Sjoerg if (!CB.abortQuery)
4467330f729Sjoerg return false;
4477330f729Sjoerg return CB.abortQuery(ClientData, nullptr);
4487330f729Sjoerg }
4497330f729Sjoerg
enteredMainFile(const FileEntry * File)4507330f729Sjoerg void CXIndexDataConsumer::enteredMainFile(const FileEntry *File) {
4517330f729Sjoerg if (File && CB.enteredMainFile) {
4527330f729Sjoerg CXIdxClientFile idxFile =
4537330f729Sjoerg CB.enteredMainFile(ClientData,
4547330f729Sjoerg static_cast<CXFile>(const_cast<FileEntry *>(File)),
4557330f729Sjoerg nullptr);
4567330f729Sjoerg FileMap[File] = idxFile;
4577330f729Sjoerg }
4587330f729Sjoerg }
4597330f729Sjoerg
ppIncludedFile(SourceLocation hashLoc,StringRef filename,const FileEntry * File,bool isImport,bool isAngled,bool isModuleImport)4607330f729Sjoerg void CXIndexDataConsumer::ppIncludedFile(SourceLocation hashLoc,
4617330f729Sjoerg StringRef filename,
4627330f729Sjoerg const FileEntry *File,
4637330f729Sjoerg bool isImport, bool isAngled,
4647330f729Sjoerg bool isModuleImport) {
4657330f729Sjoerg if (!CB.ppIncludedFile)
4667330f729Sjoerg return;
4677330f729Sjoerg
4687330f729Sjoerg ScratchAlloc SA(*this);
4697330f729Sjoerg CXIdxIncludedFileInfo Info = { getIndexLoc(hashLoc),
4707330f729Sjoerg SA.toCStr(filename),
4717330f729Sjoerg static_cast<CXFile>(
4727330f729Sjoerg const_cast<FileEntry *>(File)),
4737330f729Sjoerg isImport, isAngled, isModuleImport };
4747330f729Sjoerg CXIdxClientFile idxFile = CB.ppIncludedFile(ClientData, &Info);
4757330f729Sjoerg FileMap[File] = idxFile;
4767330f729Sjoerg }
4777330f729Sjoerg
importedModule(const ImportDecl * ImportD)4787330f729Sjoerg void CXIndexDataConsumer::importedModule(const ImportDecl *ImportD) {
4797330f729Sjoerg if (!CB.importedASTFile)
4807330f729Sjoerg return;
4817330f729Sjoerg
4827330f729Sjoerg Module *Mod = ImportD->getImportedModule();
4837330f729Sjoerg if (!Mod)
4847330f729Sjoerg return;
4857330f729Sjoerg
4867330f729Sjoerg // If the imported module is part of the top-level module that we're
4877330f729Sjoerg // indexing, it doesn't correspond to an imported AST file.
4887330f729Sjoerg // FIXME: This assumes that AST files and top-level modules directly
4897330f729Sjoerg // correspond, which is unlikely to remain true forever.
4907330f729Sjoerg if (Module *SrcMod = ImportD->getImportedOwningModule())
4917330f729Sjoerg if (SrcMod->getTopLevelModule() == Mod->getTopLevelModule())
4927330f729Sjoerg return;
4937330f729Sjoerg
494*e038c9c4Sjoerg FileEntry *FE = nullptr;
495*e038c9c4Sjoerg if (auto File = Mod->getASTFile())
496*e038c9c4Sjoerg FE = const_cast<FileEntry *>(&File->getFileEntry());
497*e038c9c4Sjoerg CXIdxImportedASTFileInfo Info = {static_cast<CXFile>(FE), Mod,
4987330f729Sjoerg getIndexLoc(ImportD->getLocation()),
499*e038c9c4Sjoerg ImportD->isImplicit()};
5007330f729Sjoerg CXIdxClientASTFile astFile = CB.importedASTFile(ClientData, &Info);
5017330f729Sjoerg (void)astFile;
5027330f729Sjoerg }
5037330f729Sjoerg
importedPCH(const FileEntry * File)5047330f729Sjoerg void CXIndexDataConsumer::importedPCH(const FileEntry *File) {
5057330f729Sjoerg if (!CB.importedASTFile)
5067330f729Sjoerg return;
5077330f729Sjoerg
5087330f729Sjoerg CXIdxImportedASTFileInfo Info = {
5097330f729Sjoerg static_cast<CXFile>(
5107330f729Sjoerg const_cast<FileEntry *>(File)),
5117330f729Sjoerg /*module=*/nullptr,
5127330f729Sjoerg getIndexLoc(SourceLocation()),
5137330f729Sjoerg /*isImplicit=*/false
5147330f729Sjoerg };
5157330f729Sjoerg CXIdxClientASTFile astFile = CB.importedASTFile(ClientData, &Info);
5167330f729Sjoerg (void)astFile;
5177330f729Sjoerg }
5187330f729Sjoerg
startedTranslationUnit()5197330f729Sjoerg void CXIndexDataConsumer::startedTranslationUnit() {
5207330f729Sjoerg CXIdxClientContainer idxCont = nullptr;
5217330f729Sjoerg if (CB.startedTranslationUnit)
5227330f729Sjoerg idxCont = CB.startedTranslationUnit(ClientData, nullptr);
5237330f729Sjoerg addContainerInMap(Ctx->getTranslationUnitDecl(), idxCont);
5247330f729Sjoerg }
5257330f729Sjoerg
indexDiagnostics()5267330f729Sjoerg void CXIndexDataConsumer::indexDiagnostics() {
5277330f729Sjoerg if (!hasDiagnosticCallback())
5287330f729Sjoerg return;
5297330f729Sjoerg
5307330f729Sjoerg CXDiagnosticSetImpl *DiagSet = cxdiag::lazyCreateDiags(getCXTU());
5317330f729Sjoerg handleDiagnosticSet(DiagSet);
5327330f729Sjoerg }
5337330f729Sjoerg
handleDiagnosticSet(CXDiagnostic CXDiagSet)5347330f729Sjoerg void CXIndexDataConsumer::handleDiagnosticSet(CXDiagnostic CXDiagSet) {
5357330f729Sjoerg if (!CB.diagnostic)
5367330f729Sjoerg return;
5377330f729Sjoerg
5387330f729Sjoerg CB.diagnostic(ClientData, CXDiagSet, nullptr);
5397330f729Sjoerg }
5407330f729Sjoerg
handleDecl(const NamedDecl * D,SourceLocation Loc,CXCursor Cursor,DeclInfo & DInfo,const DeclContext * LexicalDC,const DeclContext * SemaDC)5417330f729Sjoerg bool CXIndexDataConsumer::handleDecl(const NamedDecl *D,
5427330f729Sjoerg SourceLocation Loc, CXCursor Cursor,
5437330f729Sjoerg DeclInfo &DInfo,
5447330f729Sjoerg const DeclContext *LexicalDC,
5457330f729Sjoerg const DeclContext *SemaDC) {
5467330f729Sjoerg if (!CB.indexDeclaration || !D)
5477330f729Sjoerg return false;
5487330f729Sjoerg if (D->isImplicit() && shouldIgnoreIfImplicit(D))
5497330f729Sjoerg return false;
5507330f729Sjoerg
5517330f729Sjoerg ScratchAlloc SA(*this);
5527330f729Sjoerg getEntityInfo(D, DInfo.EntInfo, SA);
5537330f729Sjoerg if ((!shouldIndexFunctionLocalSymbols() && !DInfo.EntInfo.USR)
5547330f729Sjoerg || Loc.isInvalid())
5557330f729Sjoerg return false;
5567330f729Sjoerg
5577330f729Sjoerg if (!LexicalDC)
5587330f729Sjoerg LexicalDC = D->getLexicalDeclContext();
5597330f729Sjoerg
5607330f729Sjoerg if (shouldSuppressRefs())
5617330f729Sjoerg markEntityOccurrenceInFile(D, Loc);
5627330f729Sjoerg
5637330f729Sjoerg DInfo.entityInfo = &DInfo.EntInfo;
5647330f729Sjoerg DInfo.cursor = Cursor;
5657330f729Sjoerg DInfo.loc = getIndexLoc(Loc);
5667330f729Sjoerg DInfo.isImplicit = D->isImplicit();
5677330f729Sjoerg
5687330f729Sjoerg DInfo.attributes = DInfo.EntInfo.attributes;
5697330f729Sjoerg DInfo.numAttributes = DInfo.EntInfo.numAttributes;
5707330f729Sjoerg
5717330f729Sjoerg if (!SemaDC)
5727330f729Sjoerg SemaDC = D->getDeclContext();
5737330f729Sjoerg getContainerInfo(SemaDC, DInfo.SemanticContainer);
5747330f729Sjoerg DInfo.semanticContainer = &DInfo.SemanticContainer;
5757330f729Sjoerg
5767330f729Sjoerg if (LexicalDC == SemaDC) {
5777330f729Sjoerg DInfo.lexicalContainer = &DInfo.SemanticContainer;
5787330f729Sjoerg } else if (isTemplateImplicitInstantiation(D)) {
5797330f729Sjoerg // Implicit instantiations have the lexical context of where they were
5807330f729Sjoerg // instantiated first. We choose instead the semantic context because:
5817330f729Sjoerg // 1) at the time that we see the instantiation we have not seen the
5827330f729Sjoerg // function where it occurred yet.
5837330f729Sjoerg // 2) the lexical context of the first instantiation is not useful
5847330f729Sjoerg // information anyway.
5857330f729Sjoerg DInfo.lexicalContainer = &DInfo.SemanticContainer;
5867330f729Sjoerg } else {
5877330f729Sjoerg getContainerInfo(LexicalDC, DInfo.LexicalContainer);
5887330f729Sjoerg DInfo.lexicalContainer = &DInfo.LexicalContainer;
5897330f729Sjoerg }
5907330f729Sjoerg
5917330f729Sjoerg if (DInfo.isContainer) {
5927330f729Sjoerg getContainerInfo(getEntityContainer(D), DInfo.DeclAsContainer);
5937330f729Sjoerg DInfo.declAsContainer = &DInfo.DeclAsContainer;
5947330f729Sjoerg }
5957330f729Sjoerg
5967330f729Sjoerg CB.indexDeclaration(ClientData, &DInfo);
5977330f729Sjoerg return true;
5987330f729Sjoerg }
5997330f729Sjoerg
handleObjCContainer(const ObjCContainerDecl * D,SourceLocation Loc,CXCursor Cursor,ObjCContainerDeclInfo & ContDInfo)6007330f729Sjoerg bool CXIndexDataConsumer::handleObjCContainer(const ObjCContainerDecl *D,
6017330f729Sjoerg SourceLocation Loc, CXCursor Cursor,
6027330f729Sjoerg ObjCContainerDeclInfo &ContDInfo) {
6037330f729Sjoerg ContDInfo.ObjCContDeclInfo.declInfo = &ContDInfo;
6047330f729Sjoerg return handleDecl(D, Loc, Cursor, ContDInfo);
6057330f729Sjoerg }
6067330f729Sjoerg
handleFunction(const FunctionDecl * D)6077330f729Sjoerg bool CXIndexDataConsumer::handleFunction(const FunctionDecl *D) {
6087330f729Sjoerg bool isDef = D->isThisDeclarationADefinition();
6097330f729Sjoerg bool isContainer = isDef;
6107330f729Sjoerg bool isSkipped = false;
6117330f729Sjoerg if (D->hasSkippedBody()) {
6127330f729Sjoerg isSkipped = true;
6137330f729Sjoerg isDef = true;
6147330f729Sjoerg isContainer = false;
6157330f729Sjoerg }
6167330f729Sjoerg
6177330f729Sjoerg DeclInfo DInfo(!D->isFirstDecl(), isDef, isContainer);
6187330f729Sjoerg if (isSkipped)
6197330f729Sjoerg DInfo.flags |= CXIdxDeclFlag_Skipped;
6207330f729Sjoerg return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
6217330f729Sjoerg }
6227330f729Sjoerg
handleVar(const VarDecl * D)6237330f729Sjoerg bool CXIndexDataConsumer::handleVar(const VarDecl *D) {
6247330f729Sjoerg DeclInfo DInfo(!D->isFirstDecl(), D->isThisDeclarationADefinition(),
6257330f729Sjoerg /*isContainer=*/false);
6267330f729Sjoerg return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
6277330f729Sjoerg }
6287330f729Sjoerg
handleField(const FieldDecl * D)6297330f729Sjoerg bool CXIndexDataConsumer::handleField(const FieldDecl *D) {
6307330f729Sjoerg DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
6317330f729Sjoerg /*isContainer=*/false);
6327330f729Sjoerg return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
6337330f729Sjoerg }
6347330f729Sjoerg
handleEnumerator(const EnumConstantDecl * D)6357330f729Sjoerg bool CXIndexDataConsumer::handleEnumerator(const EnumConstantDecl *D) {
6367330f729Sjoerg DeclInfo DInfo(/*isRedeclaration=*/false, /*isDefinition=*/true,
6377330f729Sjoerg /*isContainer=*/false);
6387330f729Sjoerg return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
6397330f729Sjoerg }
6407330f729Sjoerg
handleTagDecl(const TagDecl * D)6417330f729Sjoerg bool CXIndexDataConsumer::handleTagDecl(const TagDecl *D) {
6427330f729Sjoerg if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(D))
6437330f729Sjoerg return handleCXXRecordDecl(CXXRD, D);
6447330f729Sjoerg
6457330f729Sjoerg DeclInfo DInfo(!D->isFirstDecl(), D->isThisDeclarationADefinition(),
6467330f729Sjoerg D->isThisDeclarationADefinition());
6477330f729Sjoerg return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
6487330f729Sjoerg }
6497330f729Sjoerg
handleTypedefName(const TypedefNameDecl * D)6507330f729Sjoerg bool CXIndexDataConsumer::handleTypedefName(const TypedefNameDecl *D) {
6517330f729Sjoerg DeclInfo DInfo(!D->isFirstDecl(), /*isDefinition=*/true,
6527330f729Sjoerg /*isContainer=*/false);
6537330f729Sjoerg return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
6547330f729Sjoerg }
6557330f729Sjoerg
handleObjCInterface(const ObjCInterfaceDecl * D)6567330f729Sjoerg bool CXIndexDataConsumer::handleObjCInterface(const ObjCInterfaceDecl *D) {
6577330f729Sjoerg // For @class forward declarations, suppress them the same way as references.
6587330f729Sjoerg if (!D->isThisDeclarationADefinition()) {
6597330f729Sjoerg if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, D->getLocation()))
6607330f729Sjoerg return false; // already occurred.
6617330f729Sjoerg
6627330f729Sjoerg // FIXME: This seems like the wrong definition for redeclaration.
6637330f729Sjoerg bool isRedeclaration = D->hasDefinition() || D->getPreviousDecl();
6647330f729Sjoerg ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true, isRedeclaration,
6657330f729Sjoerg /*isImplementation=*/false);
6667330f729Sjoerg return handleObjCContainer(D, D->getLocation(),
6677330f729Sjoerg MakeCursorObjCClassRef(D, D->getLocation(),
6687330f729Sjoerg CXTU),
6697330f729Sjoerg ContDInfo);
6707330f729Sjoerg }
6717330f729Sjoerg
6727330f729Sjoerg ScratchAlloc SA(*this);
6737330f729Sjoerg
6747330f729Sjoerg CXIdxBaseClassInfo BaseClass;
6757330f729Sjoerg EntityInfo BaseEntity;
6767330f729Sjoerg BaseClass.cursor = clang_getNullCursor();
6777330f729Sjoerg if (ObjCInterfaceDecl *SuperD = D->getSuperClass()) {
6787330f729Sjoerg getEntityInfo(SuperD, BaseEntity, SA);
6797330f729Sjoerg SourceLocation SuperLoc = D->getSuperClassLoc();
6807330f729Sjoerg BaseClass.base = &BaseEntity;
6817330f729Sjoerg BaseClass.cursor = MakeCursorObjCSuperClassRef(SuperD, SuperLoc, CXTU);
6827330f729Sjoerg BaseClass.loc = getIndexLoc(SuperLoc);
6837330f729Sjoerg
6847330f729Sjoerg if (shouldSuppressRefs())
6857330f729Sjoerg markEntityOccurrenceInFile(SuperD, SuperLoc);
6867330f729Sjoerg }
6877330f729Sjoerg
6887330f729Sjoerg ObjCProtocolList EmptyProtoList;
6897330f729Sjoerg ObjCProtocolListInfo ProtInfo(D->isThisDeclarationADefinition()
6907330f729Sjoerg ? D->getReferencedProtocols()
6917330f729Sjoerg : EmptyProtoList,
6927330f729Sjoerg *this, SA);
6937330f729Sjoerg
6947330f729Sjoerg ObjCInterfaceDeclInfo InterInfo(D);
6957330f729Sjoerg InterInfo.ObjCProtoListInfo = ProtInfo.getListInfo();
6967330f729Sjoerg InterInfo.ObjCInterDeclInfo.containerInfo = &InterInfo.ObjCContDeclInfo;
6977330f729Sjoerg InterInfo.ObjCInterDeclInfo.superInfo = D->getSuperClass() ? &BaseClass
6987330f729Sjoerg : nullptr;
6997330f729Sjoerg InterInfo.ObjCInterDeclInfo.protocols = &InterInfo.ObjCProtoListInfo;
7007330f729Sjoerg
7017330f729Sjoerg return handleObjCContainer(D, D->getLocation(), getCursor(D), InterInfo);
7027330f729Sjoerg }
7037330f729Sjoerg
handleObjCImplementation(const ObjCImplementationDecl * D)7047330f729Sjoerg bool CXIndexDataConsumer::handleObjCImplementation(
7057330f729Sjoerg const ObjCImplementationDecl *D) {
7067330f729Sjoerg ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/false,
7077330f729Sjoerg /*isRedeclaration=*/true,
7087330f729Sjoerg /*isImplementation=*/true);
7097330f729Sjoerg return handleObjCContainer(D, D->getLocation(), getCursor(D), ContDInfo);
7107330f729Sjoerg }
7117330f729Sjoerg
handleObjCProtocol(const ObjCProtocolDecl * D)7127330f729Sjoerg bool CXIndexDataConsumer::handleObjCProtocol(const ObjCProtocolDecl *D) {
7137330f729Sjoerg if (!D->isThisDeclarationADefinition()) {
7147330f729Sjoerg if (shouldSuppressRefs() && markEntityOccurrenceInFile(D, D->getLocation()))
7157330f729Sjoerg return false; // already occurred.
7167330f729Sjoerg
7177330f729Sjoerg // FIXME: This seems like the wrong definition for redeclaration.
7187330f729Sjoerg bool isRedeclaration = D->hasDefinition() || D->getPreviousDecl();
7197330f729Sjoerg ObjCContainerDeclInfo ContDInfo(/*isForwardRef=*/true,
7207330f729Sjoerg isRedeclaration,
7217330f729Sjoerg /*isImplementation=*/false);
7227330f729Sjoerg return handleObjCContainer(D, D->getLocation(),
7237330f729Sjoerg MakeCursorObjCProtocolRef(D, D->getLocation(),
7247330f729Sjoerg CXTU),
7257330f729Sjoerg ContDInfo);
7267330f729Sjoerg }
7277330f729Sjoerg
7287330f729Sjoerg ScratchAlloc SA(*this);
7297330f729Sjoerg ObjCProtocolList EmptyProtoList;
7307330f729Sjoerg ObjCProtocolListInfo ProtListInfo(D->isThisDeclarationADefinition()
7317330f729Sjoerg ? D->getReferencedProtocols()
7327330f729Sjoerg : EmptyProtoList,
7337330f729Sjoerg *this, SA);
7347330f729Sjoerg
7357330f729Sjoerg ObjCProtocolDeclInfo ProtInfo(D);
7367330f729Sjoerg ProtInfo.ObjCProtoRefListInfo = ProtListInfo.getListInfo();
7377330f729Sjoerg
7387330f729Sjoerg return handleObjCContainer(D, D->getLocation(), getCursor(D), ProtInfo);
7397330f729Sjoerg }
7407330f729Sjoerg
handleObjCCategory(const ObjCCategoryDecl * D)7417330f729Sjoerg bool CXIndexDataConsumer::handleObjCCategory(const ObjCCategoryDecl *D) {
7427330f729Sjoerg ScratchAlloc SA(*this);
7437330f729Sjoerg
7447330f729Sjoerg ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/false);
7457330f729Sjoerg EntityInfo ClassEntity;
7467330f729Sjoerg const ObjCInterfaceDecl *IFaceD = D->getClassInterface();
7477330f729Sjoerg SourceLocation ClassLoc = D->getLocation();
7487330f729Sjoerg SourceLocation CategoryLoc = D->IsClassExtension() ? ClassLoc
7497330f729Sjoerg : D->getCategoryNameLoc();
7507330f729Sjoerg getEntityInfo(IFaceD, ClassEntity, SA);
7517330f729Sjoerg
7527330f729Sjoerg if (shouldSuppressRefs())
7537330f729Sjoerg markEntityOccurrenceInFile(IFaceD, ClassLoc);
7547330f729Sjoerg
7557330f729Sjoerg ObjCProtocolListInfo ProtInfo(D->getReferencedProtocols(), *this, SA);
7567330f729Sjoerg
7577330f729Sjoerg CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo;
7587330f729Sjoerg if (IFaceD) {
7597330f729Sjoerg CatDInfo.ObjCCatDeclInfo.objcClass = &ClassEntity;
7607330f729Sjoerg CatDInfo.ObjCCatDeclInfo.classCursor =
7617330f729Sjoerg MakeCursorObjCClassRef(IFaceD, ClassLoc, CXTU);
7627330f729Sjoerg } else {
7637330f729Sjoerg CatDInfo.ObjCCatDeclInfo.objcClass = nullptr;
7647330f729Sjoerg CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor();
7657330f729Sjoerg }
7667330f729Sjoerg CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(ClassLoc);
7677330f729Sjoerg CatDInfo.ObjCProtoListInfo = ProtInfo.getListInfo();
7687330f729Sjoerg CatDInfo.ObjCCatDeclInfo.protocols = &CatDInfo.ObjCProtoListInfo;
7697330f729Sjoerg
7707330f729Sjoerg return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo);
7717330f729Sjoerg }
7727330f729Sjoerg
handleObjCCategoryImpl(const ObjCCategoryImplDecl * D)7737330f729Sjoerg bool CXIndexDataConsumer::handleObjCCategoryImpl(const ObjCCategoryImplDecl *D) {
7747330f729Sjoerg ScratchAlloc SA(*this);
7757330f729Sjoerg
7767330f729Sjoerg const ObjCCategoryDecl *CatD = D->getCategoryDecl();
7777330f729Sjoerg ObjCCategoryDeclInfo CatDInfo(/*isImplementation=*/true);
7787330f729Sjoerg EntityInfo ClassEntity;
7797330f729Sjoerg const ObjCInterfaceDecl *IFaceD = CatD->getClassInterface();
7807330f729Sjoerg SourceLocation ClassLoc = D->getLocation();
7817330f729Sjoerg SourceLocation CategoryLoc = D->getCategoryNameLoc();
7827330f729Sjoerg getEntityInfo(IFaceD, ClassEntity, SA);
7837330f729Sjoerg
7847330f729Sjoerg if (shouldSuppressRefs())
7857330f729Sjoerg markEntityOccurrenceInFile(IFaceD, ClassLoc);
7867330f729Sjoerg
7877330f729Sjoerg CatDInfo.ObjCCatDeclInfo.containerInfo = &CatDInfo.ObjCContDeclInfo;
7887330f729Sjoerg if (IFaceD) {
7897330f729Sjoerg CatDInfo.ObjCCatDeclInfo.objcClass = &ClassEntity;
7907330f729Sjoerg CatDInfo.ObjCCatDeclInfo.classCursor =
7917330f729Sjoerg MakeCursorObjCClassRef(IFaceD, ClassLoc, CXTU);
7927330f729Sjoerg } else {
7937330f729Sjoerg CatDInfo.ObjCCatDeclInfo.objcClass = nullptr;
7947330f729Sjoerg CatDInfo.ObjCCatDeclInfo.classCursor = clang_getNullCursor();
7957330f729Sjoerg }
7967330f729Sjoerg CatDInfo.ObjCCatDeclInfo.classLoc = getIndexLoc(ClassLoc);
7977330f729Sjoerg CatDInfo.ObjCCatDeclInfo.protocols = nullptr;
7987330f729Sjoerg
7997330f729Sjoerg return handleObjCContainer(D, CategoryLoc, getCursor(D), CatDInfo);
8007330f729Sjoerg }
8017330f729Sjoerg
handleObjCMethod(const ObjCMethodDecl * D,SourceLocation Loc)8027330f729Sjoerg bool CXIndexDataConsumer::handleObjCMethod(const ObjCMethodDecl *D,
8037330f729Sjoerg SourceLocation Loc) {
8047330f729Sjoerg bool isDef = D->isThisDeclarationADefinition();
8057330f729Sjoerg bool isContainer = isDef;
8067330f729Sjoerg bool isSkipped = false;
8077330f729Sjoerg if (D->hasSkippedBody()) {
8087330f729Sjoerg isSkipped = true;
8097330f729Sjoerg isDef = true;
8107330f729Sjoerg isContainer = false;
8117330f729Sjoerg }
8127330f729Sjoerg
8137330f729Sjoerg DeclInfo DInfo(!D->isCanonicalDecl(), isDef, isContainer);
8147330f729Sjoerg if (isSkipped)
8157330f729Sjoerg DInfo.flags |= CXIdxDeclFlag_Skipped;
8167330f729Sjoerg return handleDecl(D, Loc, getCursor(D), DInfo);
8177330f729Sjoerg }
8187330f729Sjoerg
handleSynthesizedObjCProperty(const ObjCPropertyImplDecl * D)8197330f729Sjoerg bool CXIndexDataConsumer::handleSynthesizedObjCProperty(
8207330f729Sjoerg const ObjCPropertyImplDecl *D) {
8217330f729Sjoerg ObjCPropertyDecl *PD = D->getPropertyDecl();
8227330f729Sjoerg auto *DC = D->getDeclContext();
8237330f729Sjoerg return handleReference(PD, D->getLocation(), getCursor(D),
8247330f729Sjoerg dyn_cast<NamedDecl>(DC), DC);
8257330f729Sjoerg }
8267330f729Sjoerg
handleSynthesizedObjCMethod(const ObjCMethodDecl * D,SourceLocation Loc,const DeclContext * LexicalDC)8277330f729Sjoerg bool CXIndexDataConsumer::handleSynthesizedObjCMethod(const ObjCMethodDecl *D,
8287330f729Sjoerg SourceLocation Loc,
8297330f729Sjoerg const DeclContext *LexicalDC) {
8307330f729Sjoerg DeclInfo DInfo(/*isRedeclaration=*/true, /*isDefinition=*/true,
8317330f729Sjoerg /*isContainer=*/false);
8327330f729Sjoerg return handleDecl(D, Loc, getCursor(D), DInfo, LexicalDC, D->getDeclContext());
8337330f729Sjoerg }
8347330f729Sjoerg
handleObjCProperty(const ObjCPropertyDecl * D)8357330f729Sjoerg bool CXIndexDataConsumer::handleObjCProperty(const ObjCPropertyDecl *D) {
8367330f729Sjoerg ScratchAlloc SA(*this);
8377330f729Sjoerg
8387330f729Sjoerg ObjCPropertyDeclInfo DInfo;
8397330f729Sjoerg EntityInfo GetterEntity;
8407330f729Sjoerg EntityInfo SetterEntity;
8417330f729Sjoerg
8427330f729Sjoerg DInfo.ObjCPropDeclInfo.declInfo = &DInfo;
8437330f729Sjoerg
8447330f729Sjoerg if (ObjCMethodDecl *Getter = D->getGetterMethodDecl()) {
8457330f729Sjoerg getEntityInfo(Getter, GetterEntity, SA);
8467330f729Sjoerg DInfo.ObjCPropDeclInfo.getter = &GetterEntity;
8477330f729Sjoerg } else {
8487330f729Sjoerg DInfo.ObjCPropDeclInfo.getter = nullptr;
8497330f729Sjoerg }
8507330f729Sjoerg if (ObjCMethodDecl *Setter = D->getSetterMethodDecl()) {
8517330f729Sjoerg getEntityInfo(Setter, SetterEntity, SA);
8527330f729Sjoerg DInfo.ObjCPropDeclInfo.setter = &SetterEntity;
8537330f729Sjoerg } else {
8547330f729Sjoerg DInfo.ObjCPropDeclInfo.setter = nullptr;
8557330f729Sjoerg }
8567330f729Sjoerg
8577330f729Sjoerg return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
8587330f729Sjoerg }
8597330f729Sjoerg
handleNamespace(const NamespaceDecl * D)8607330f729Sjoerg bool CXIndexDataConsumer::handleNamespace(const NamespaceDecl *D) {
8617330f729Sjoerg DeclInfo DInfo(/*isRedeclaration=*/!D->isOriginalNamespace(),
8627330f729Sjoerg /*isDefinition=*/true,
8637330f729Sjoerg /*isContainer=*/true);
8647330f729Sjoerg return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
8657330f729Sjoerg }
8667330f729Sjoerg
handleClassTemplate(const ClassTemplateDecl * D)8677330f729Sjoerg bool CXIndexDataConsumer::handleClassTemplate(const ClassTemplateDecl *D) {
8687330f729Sjoerg return handleCXXRecordDecl(D->getTemplatedDecl(), D);
8697330f729Sjoerg }
8707330f729Sjoerg
handleFunctionTemplate(const FunctionTemplateDecl * D)8717330f729Sjoerg bool CXIndexDataConsumer::handleFunctionTemplate(const FunctionTemplateDecl *D) {
8727330f729Sjoerg DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(),
8737330f729Sjoerg /*isDefinition=*/D->isThisDeclarationADefinition(),
8747330f729Sjoerg /*isContainer=*/D->isThisDeclarationADefinition());
8757330f729Sjoerg return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
8767330f729Sjoerg }
8777330f729Sjoerg
handleTypeAliasTemplate(const TypeAliasTemplateDecl * D)8787330f729Sjoerg bool CXIndexDataConsumer::handleTypeAliasTemplate(const TypeAliasTemplateDecl *D) {
8797330f729Sjoerg DeclInfo DInfo(/*isRedeclaration=*/!D->isCanonicalDecl(),
8807330f729Sjoerg /*isDefinition=*/true, /*isContainer=*/false);
8817330f729Sjoerg return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
8827330f729Sjoerg }
8837330f729Sjoerg
handleReference(const NamedDecl * D,SourceLocation Loc,CXCursor Cursor,const NamedDecl * Parent,const DeclContext * DC,const Expr * E,CXIdxEntityRefKind Kind,CXSymbolRole Role)8847330f729Sjoerg bool CXIndexDataConsumer::handleReference(const NamedDecl *D, SourceLocation Loc,
8857330f729Sjoerg CXCursor Cursor,
8867330f729Sjoerg const NamedDecl *Parent,
8877330f729Sjoerg const DeclContext *DC,
8887330f729Sjoerg const Expr *E,
8897330f729Sjoerg CXIdxEntityRefKind Kind,
8907330f729Sjoerg CXSymbolRole Role) {
8917330f729Sjoerg if (!CB.indexEntityReference)
8927330f729Sjoerg return false;
8937330f729Sjoerg
8947330f729Sjoerg if (!D || !DC)
8957330f729Sjoerg return false;
8967330f729Sjoerg if (Loc.isInvalid())
8977330f729Sjoerg return false;
8987330f729Sjoerg if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D))
8997330f729Sjoerg return false;
9007330f729Sjoerg if (isNotFromSourceFile(D->getLocation()))
9017330f729Sjoerg return false;
9027330f729Sjoerg if (D->isImplicit() && shouldIgnoreIfImplicit(D))
9037330f729Sjoerg return false;
9047330f729Sjoerg
9057330f729Sjoerg if (shouldSuppressRefs()) {
9067330f729Sjoerg if (markEntityOccurrenceInFile(D, Loc))
9077330f729Sjoerg return false; // already occurred.
9087330f729Sjoerg }
9097330f729Sjoerg
9107330f729Sjoerg ScratchAlloc SA(*this);
9117330f729Sjoerg EntityInfo RefEntity, ParentEntity;
9127330f729Sjoerg getEntityInfo(D, RefEntity, SA);
9137330f729Sjoerg if (!RefEntity.USR)
9147330f729Sjoerg return false;
9157330f729Sjoerg
9167330f729Sjoerg getEntityInfo(Parent, ParentEntity, SA);
9177330f729Sjoerg
9187330f729Sjoerg ContainerInfo Container;
9197330f729Sjoerg getContainerInfo(DC, Container);
9207330f729Sjoerg
9217330f729Sjoerg CXIdxEntityRefInfo Info = { Kind,
9227330f729Sjoerg Cursor,
9237330f729Sjoerg getIndexLoc(Loc),
9247330f729Sjoerg &RefEntity,
9257330f729Sjoerg Parent ? &ParentEntity : nullptr,
9267330f729Sjoerg &Container,
9277330f729Sjoerg Role };
9287330f729Sjoerg CB.indexEntityReference(ClientData, &Info);
9297330f729Sjoerg return true;
9307330f729Sjoerg }
9317330f729Sjoerg
isNotFromSourceFile(SourceLocation Loc) const9327330f729Sjoerg bool CXIndexDataConsumer::isNotFromSourceFile(SourceLocation Loc) const {
9337330f729Sjoerg if (Loc.isInvalid())
9347330f729Sjoerg return true;
9357330f729Sjoerg SourceManager &SM = Ctx->getSourceManager();
9367330f729Sjoerg SourceLocation FileLoc = SM.getFileLoc(Loc);
9377330f729Sjoerg FileID FID = SM.getFileID(FileLoc);
9387330f729Sjoerg return SM.getFileEntryForID(FID) == nullptr;
9397330f729Sjoerg }
9407330f729Sjoerg
addContainerInMap(const DeclContext * DC,CXIdxClientContainer container)9417330f729Sjoerg void CXIndexDataConsumer::addContainerInMap(const DeclContext *DC,
9427330f729Sjoerg CXIdxClientContainer container) {
9437330f729Sjoerg if (!DC)
9447330f729Sjoerg return;
9457330f729Sjoerg
9467330f729Sjoerg ContainerMapTy::iterator I = ContainerMap.find(DC);
9477330f729Sjoerg if (I == ContainerMap.end()) {
9487330f729Sjoerg if (container)
9497330f729Sjoerg ContainerMap[DC] = container;
9507330f729Sjoerg return;
9517330f729Sjoerg }
9527330f729Sjoerg // Allow changing the container of a previously seen DeclContext so we
9537330f729Sjoerg // can handle invalid user code, like a function re-definition.
9547330f729Sjoerg if (container)
9557330f729Sjoerg I->second = container;
9567330f729Sjoerg else
9577330f729Sjoerg ContainerMap.erase(I);
9587330f729Sjoerg }
9597330f729Sjoerg
getClientEntity(const Decl * D) const9607330f729Sjoerg CXIdxClientEntity CXIndexDataConsumer::getClientEntity(const Decl *D) const {
9617330f729Sjoerg if (!D)
9627330f729Sjoerg return nullptr;
9637330f729Sjoerg EntityMapTy::const_iterator I = EntityMap.find(D);
9647330f729Sjoerg if (I == EntityMap.end())
9657330f729Sjoerg return nullptr;
9667330f729Sjoerg return I->second;
9677330f729Sjoerg }
9687330f729Sjoerg
setClientEntity(const Decl * D,CXIdxClientEntity client)9697330f729Sjoerg void CXIndexDataConsumer::setClientEntity(const Decl *D, CXIdxClientEntity client) {
9707330f729Sjoerg if (!D)
9717330f729Sjoerg return;
9727330f729Sjoerg EntityMap[D] = client;
9737330f729Sjoerg }
9747330f729Sjoerg
handleCXXRecordDecl(const CXXRecordDecl * RD,const NamedDecl * OrigD)9757330f729Sjoerg bool CXIndexDataConsumer::handleCXXRecordDecl(const CXXRecordDecl *RD,
9767330f729Sjoerg const NamedDecl *OrigD) {
9777330f729Sjoerg if (RD->isThisDeclarationADefinition()) {
9787330f729Sjoerg ScratchAlloc SA(*this);
9797330f729Sjoerg CXXClassDeclInfo CXXDInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(),
9807330f729Sjoerg /*isDefinition=*/RD->isThisDeclarationADefinition());
9817330f729Sjoerg CXXBasesListInfo BaseList(RD, *this, SA);
9827330f729Sjoerg CXXDInfo.CXXClassInfo.declInfo = &CXXDInfo;
9837330f729Sjoerg CXXDInfo.CXXClassInfo.bases = BaseList.getBases();
9847330f729Sjoerg CXXDInfo.CXXClassInfo.numBases = BaseList.getNumBases();
9857330f729Sjoerg
9867330f729Sjoerg if (shouldSuppressRefs()) {
9877330f729Sjoerg // Go through bases and mark them as referenced.
9887330f729Sjoerg for (unsigned i = 0, e = BaseList.getNumBases(); i != e; ++i) {
9897330f729Sjoerg const CXIdxBaseClassInfo *baseInfo = BaseList.getBases()[i];
9907330f729Sjoerg if (baseInfo->base) {
9917330f729Sjoerg const NamedDecl *BaseD = BaseList.BaseEntities[i].Dcl;
9927330f729Sjoerg SourceLocation
9937330f729Sjoerg Loc = SourceLocation::getFromRawEncoding(baseInfo->loc.int_data);
9947330f729Sjoerg markEntityOccurrenceInFile(BaseD, Loc);
9957330f729Sjoerg }
9967330f729Sjoerg }
9977330f729Sjoerg }
9987330f729Sjoerg
9997330f729Sjoerg return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), CXXDInfo);
10007330f729Sjoerg }
10017330f729Sjoerg
10027330f729Sjoerg DeclInfo DInfo(/*isRedeclaration=*/!OrigD->isCanonicalDecl(),
10037330f729Sjoerg /*isDefinition=*/RD->isThisDeclarationADefinition(),
10047330f729Sjoerg /*isContainer=*/RD->isThisDeclarationADefinition());
10057330f729Sjoerg return handleDecl(OrigD, OrigD->getLocation(), getCursor(OrigD), DInfo);
10067330f729Sjoerg }
10077330f729Sjoerg
markEntityOccurrenceInFile(const NamedDecl * D,SourceLocation Loc)10087330f729Sjoerg bool CXIndexDataConsumer::markEntityOccurrenceInFile(const NamedDecl *D,
10097330f729Sjoerg SourceLocation Loc) {
10107330f729Sjoerg if (!D || Loc.isInvalid())
10117330f729Sjoerg return true;
10127330f729Sjoerg
10137330f729Sjoerg SourceManager &SM = Ctx->getSourceManager();
10147330f729Sjoerg D = getEntityDecl(D);
10157330f729Sjoerg
10167330f729Sjoerg std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(SM.getFileLoc(Loc));
10177330f729Sjoerg FileID FID = LocInfo.first;
10187330f729Sjoerg if (FID.isInvalid())
10197330f729Sjoerg return true;
10207330f729Sjoerg
10217330f729Sjoerg const FileEntry *FE = SM.getFileEntryForID(FID);
10227330f729Sjoerg if (!FE)
10237330f729Sjoerg return true;
10247330f729Sjoerg RefFileOccurrence RefOccur(FE, D);
10257330f729Sjoerg std::pair<llvm::DenseSet<RefFileOccurrence>::iterator, bool>
10267330f729Sjoerg res = RefFileOccurrences.insert(RefOccur);
10277330f729Sjoerg return !res.second; // already in map
10287330f729Sjoerg }
10297330f729Sjoerg
getEntityDecl(const NamedDecl * D) const10307330f729Sjoerg const NamedDecl *CXIndexDataConsumer::getEntityDecl(const NamedDecl *D) const {
10317330f729Sjoerg assert(D);
10327330f729Sjoerg D = cast<NamedDecl>(D->getCanonicalDecl());
10337330f729Sjoerg
10347330f729Sjoerg if (const ObjCImplementationDecl *
10357330f729Sjoerg ImplD = dyn_cast<ObjCImplementationDecl>(D)) {
10367330f729Sjoerg return getEntityDecl(ImplD->getClassInterface());
10377330f729Sjoerg
10387330f729Sjoerg } else if (const ObjCCategoryImplDecl *
10397330f729Sjoerg CatImplD = dyn_cast<ObjCCategoryImplDecl>(D)) {
10407330f729Sjoerg return getEntityDecl(CatImplD->getCategoryDecl());
10417330f729Sjoerg } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
10427330f729Sjoerg if (FunctionTemplateDecl *TemplD = FD->getDescribedFunctionTemplate())
10437330f729Sjoerg return getEntityDecl(TemplD);
10447330f729Sjoerg } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
10457330f729Sjoerg if (ClassTemplateDecl *TemplD = RD->getDescribedClassTemplate())
10467330f729Sjoerg return getEntityDecl(TemplD);
10477330f729Sjoerg }
10487330f729Sjoerg
10497330f729Sjoerg return D;
10507330f729Sjoerg }
10517330f729Sjoerg
10527330f729Sjoerg const DeclContext *
getEntityContainer(const Decl * D) const10537330f729Sjoerg CXIndexDataConsumer::getEntityContainer(const Decl *D) const {
10547330f729Sjoerg const DeclContext *DC = dyn_cast<DeclContext>(D);
10557330f729Sjoerg if (DC)
10567330f729Sjoerg return DC;
10577330f729Sjoerg
10587330f729Sjoerg if (const ClassTemplateDecl *ClassTempl = dyn_cast<ClassTemplateDecl>(D)) {
10597330f729Sjoerg DC = ClassTempl->getTemplatedDecl();
10607330f729Sjoerg } else if (const FunctionTemplateDecl *
10617330f729Sjoerg FuncTempl = dyn_cast<FunctionTemplateDecl>(D)) {
10627330f729Sjoerg DC = FuncTempl->getTemplatedDecl();
10637330f729Sjoerg }
10647330f729Sjoerg
10657330f729Sjoerg return DC;
10667330f729Sjoerg }
10677330f729Sjoerg
10687330f729Sjoerg CXIdxClientContainer
getClientContainerForDC(const DeclContext * DC) const10697330f729Sjoerg CXIndexDataConsumer::getClientContainerForDC(const DeclContext *DC) const {
10707330f729Sjoerg if (!DC)
10717330f729Sjoerg return nullptr;
10727330f729Sjoerg
10737330f729Sjoerg ContainerMapTy::const_iterator I = ContainerMap.find(DC);
10747330f729Sjoerg if (I == ContainerMap.end())
10757330f729Sjoerg return nullptr;
10767330f729Sjoerg
10777330f729Sjoerg return I->second;
10787330f729Sjoerg }
10797330f729Sjoerg
getIndexFile(const FileEntry * File)10807330f729Sjoerg CXIdxClientFile CXIndexDataConsumer::getIndexFile(const FileEntry *File) {
10817330f729Sjoerg if (!File)
10827330f729Sjoerg return nullptr;
10837330f729Sjoerg
10847330f729Sjoerg FileMapTy::iterator FI = FileMap.find(File);
10857330f729Sjoerg if (FI != FileMap.end())
10867330f729Sjoerg return FI->second;
10877330f729Sjoerg
10887330f729Sjoerg return nullptr;
10897330f729Sjoerg }
10907330f729Sjoerg
getIndexLoc(SourceLocation Loc) const10917330f729Sjoerg CXIdxLoc CXIndexDataConsumer::getIndexLoc(SourceLocation Loc) const {
10927330f729Sjoerg CXIdxLoc idxLoc = { {nullptr, nullptr}, 0 };
10937330f729Sjoerg if (Loc.isInvalid())
10947330f729Sjoerg return idxLoc;
10957330f729Sjoerg
10967330f729Sjoerg idxLoc.ptr_data[0] = const_cast<CXIndexDataConsumer *>(this);
10977330f729Sjoerg idxLoc.int_data = Loc.getRawEncoding();
10987330f729Sjoerg return idxLoc;
10997330f729Sjoerg }
11007330f729Sjoerg
translateLoc(SourceLocation Loc,CXIdxClientFile * indexFile,CXFile * file,unsigned * line,unsigned * column,unsigned * offset)11017330f729Sjoerg void CXIndexDataConsumer::translateLoc(SourceLocation Loc,
11027330f729Sjoerg CXIdxClientFile *indexFile, CXFile *file,
11037330f729Sjoerg unsigned *line, unsigned *column,
11047330f729Sjoerg unsigned *offset) {
11057330f729Sjoerg if (Loc.isInvalid())
11067330f729Sjoerg return;
11077330f729Sjoerg
11087330f729Sjoerg SourceManager &SM = Ctx->getSourceManager();
11097330f729Sjoerg Loc = SM.getFileLoc(Loc);
11107330f729Sjoerg
11117330f729Sjoerg std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
11127330f729Sjoerg FileID FID = LocInfo.first;
11137330f729Sjoerg unsigned FileOffset = LocInfo.second;
11147330f729Sjoerg
11157330f729Sjoerg if (FID.isInvalid())
11167330f729Sjoerg return;
11177330f729Sjoerg
11187330f729Sjoerg const FileEntry *FE = SM.getFileEntryForID(FID);
11197330f729Sjoerg if (indexFile)
11207330f729Sjoerg *indexFile = getIndexFile(FE);
11217330f729Sjoerg if (file)
11227330f729Sjoerg *file = const_cast<FileEntry *>(FE);
11237330f729Sjoerg if (line)
11247330f729Sjoerg *line = SM.getLineNumber(FID, FileOffset);
11257330f729Sjoerg if (column)
11267330f729Sjoerg *column = SM.getColumnNumber(FID, FileOffset);
11277330f729Sjoerg if (offset)
11287330f729Sjoerg *offset = FileOffset;
11297330f729Sjoerg }
11307330f729Sjoerg
11317330f729Sjoerg static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage L);
11327330f729Sjoerg static CXIdxEntityCXXTemplateKind
11337330f729Sjoerg getEntityKindFromSymbolProperties(SymbolPropertySet K);
11347330f729Sjoerg static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L);
11357330f729Sjoerg
getEntityInfo(const NamedDecl * D,EntityInfo & EntityInfo,ScratchAlloc & SA)11367330f729Sjoerg void CXIndexDataConsumer::getEntityInfo(const NamedDecl *D,
11377330f729Sjoerg EntityInfo &EntityInfo,
11387330f729Sjoerg ScratchAlloc &SA) {
11397330f729Sjoerg if (!D)
11407330f729Sjoerg return;
11417330f729Sjoerg
11427330f729Sjoerg D = getEntityDecl(D);
11437330f729Sjoerg EntityInfo.cursor = getCursor(D);
11447330f729Sjoerg EntityInfo.Dcl = D;
11457330f729Sjoerg EntityInfo.IndexCtx = this;
11467330f729Sjoerg
11477330f729Sjoerg SymbolInfo SymInfo = getSymbolInfo(D);
11487330f729Sjoerg EntityInfo.kind = getEntityKindFromSymbolKind(SymInfo.Kind, SymInfo.Lang);
11497330f729Sjoerg EntityInfo.templateKind = getEntityKindFromSymbolProperties(SymInfo.Properties);
11507330f729Sjoerg EntityInfo.lang = getEntityLangFromSymbolLang(SymInfo.Lang);
11517330f729Sjoerg
11527330f729Sjoerg if (D->hasAttrs()) {
11537330f729Sjoerg EntityInfo.AttrList = AttrListInfo::create(D, *this);
11547330f729Sjoerg EntityInfo.attributes = EntityInfo.AttrList->getAttrs();
11557330f729Sjoerg EntityInfo.numAttributes = EntityInfo.AttrList->getNumAttrs();
11567330f729Sjoerg }
11577330f729Sjoerg
11587330f729Sjoerg if (EntityInfo.kind == CXIdxEntity_Unexposed)
11597330f729Sjoerg return;
11607330f729Sjoerg
11617330f729Sjoerg if (IdentifierInfo *II = D->getIdentifier()) {
11627330f729Sjoerg EntityInfo.name = SA.toCStr(II->getName());
11637330f729Sjoerg
11647330f729Sjoerg } else if (isa<TagDecl>(D) || isa<FieldDecl>(D) || isa<NamespaceDecl>(D)) {
11657330f729Sjoerg EntityInfo.name = nullptr; // anonymous tag/field/namespace.
11667330f729Sjoerg
11677330f729Sjoerg } else {
11687330f729Sjoerg SmallString<256> StrBuf;
11697330f729Sjoerg {
11707330f729Sjoerg llvm::raw_svector_ostream OS(StrBuf);
11717330f729Sjoerg D->printName(OS);
11727330f729Sjoerg }
11737330f729Sjoerg EntityInfo.name = SA.copyCStr(StrBuf.str());
11747330f729Sjoerg }
11757330f729Sjoerg
11767330f729Sjoerg {
11777330f729Sjoerg SmallString<512> StrBuf;
11787330f729Sjoerg bool Ignore = getDeclCursorUSR(D, StrBuf);
11797330f729Sjoerg if (Ignore) {
11807330f729Sjoerg EntityInfo.USR = nullptr;
11817330f729Sjoerg } else {
11827330f729Sjoerg EntityInfo.USR = SA.copyCStr(StrBuf.str());
11837330f729Sjoerg }
11847330f729Sjoerg }
11857330f729Sjoerg }
11867330f729Sjoerg
getContainerInfo(const DeclContext * DC,ContainerInfo & ContInfo)11877330f729Sjoerg void CXIndexDataConsumer::getContainerInfo(const DeclContext *DC,
11887330f729Sjoerg ContainerInfo &ContInfo) {
11897330f729Sjoerg ContInfo.cursor = getCursor(cast<Decl>(DC));
11907330f729Sjoerg ContInfo.DC = DC;
11917330f729Sjoerg ContInfo.IndexCtx = this;
11927330f729Sjoerg }
11937330f729Sjoerg
getRefCursor(const NamedDecl * D,SourceLocation Loc)11947330f729Sjoerg CXCursor CXIndexDataConsumer::getRefCursor(const NamedDecl *D, SourceLocation Loc) {
11957330f729Sjoerg if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
11967330f729Sjoerg return MakeCursorTypeRef(TD, Loc, CXTU);
11977330f729Sjoerg if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
11987330f729Sjoerg return MakeCursorObjCClassRef(ID, Loc, CXTU);
11997330f729Sjoerg if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
12007330f729Sjoerg return MakeCursorObjCProtocolRef(PD, Loc, CXTU);
12017330f729Sjoerg if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
12027330f729Sjoerg return MakeCursorTemplateRef(Template, Loc, CXTU);
12037330f729Sjoerg if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(D))
12047330f729Sjoerg return MakeCursorNamespaceRef(Namespace, Loc, CXTU);
12057330f729Sjoerg if (const NamespaceAliasDecl *Namespace = dyn_cast<NamespaceAliasDecl>(D))
12067330f729Sjoerg return MakeCursorNamespaceRef(Namespace, Loc, CXTU);
12077330f729Sjoerg if (const FieldDecl *Field = dyn_cast<FieldDecl>(D))
12087330f729Sjoerg return MakeCursorMemberRef(Field, Loc, CXTU);
12097330f729Sjoerg if (const VarDecl *Var = dyn_cast<VarDecl>(D))
12107330f729Sjoerg return MakeCursorVariableRef(Var, Loc, CXTU);
12117330f729Sjoerg
12127330f729Sjoerg return clang_getNullCursor();
12137330f729Sjoerg }
12147330f729Sjoerg
shouldIgnoreIfImplicit(const Decl * D)12157330f729Sjoerg bool CXIndexDataConsumer::shouldIgnoreIfImplicit(const Decl *D) {
12167330f729Sjoerg if (isa<ObjCInterfaceDecl>(D))
12177330f729Sjoerg return false;
12187330f729Sjoerg if (isa<ObjCCategoryDecl>(D))
12197330f729Sjoerg return false;
12207330f729Sjoerg if (isa<ObjCIvarDecl>(D))
12217330f729Sjoerg return false;
12227330f729Sjoerg if (isa<ObjCMethodDecl>(D))
12237330f729Sjoerg return false;
12247330f729Sjoerg if (isa<ImportDecl>(D))
12257330f729Sjoerg return false;
12267330f729Sjoerg return true;
12277330f729Sjoerg }
12287330f729Sjoerg
isTemplateImplicitInstantiation(const Decl * D)12297330f729Sjoerg bool CXIndexDataConsumer::isTemplateImplicitInstantiation(const Decl *D) {
12307330f729Sjoerg if (const ClassTemplateSpecializationDecl *
12317330f729Sjoerg SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
12327330f729Sjoerg return SD->getSpecializationKind() == TSK_ImplicitInstantiation;
12337330f729Sjoerg }
12347330f729Sjoerg if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
12357330f729Sjoerg return FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation;
12367330f729Sjoerg }
12377330f729Sjoerg return false;
12387330f729Sjoerg }
12397330f729Sjoerg
getEntityKindFromSymbolKind(SymbolKind K,SymbolLanguage Lang)12407330f729Sjoerg static CXIdxEntityKind getEntityKindFromSymbolKind(SymbolKind K, SymbolLanguage Lang) {
12417330f729Sjoerg switch (K) {
12427330f729Sjoerg case SymbolKind::Unknown:
12437330f729Sjoerg case SymbolKind::Module:
12447330f729Sjoerg case SymbolKind::Macro:
12457330f729Sjoerg case SymbolKind::ClassProperty:
12467330f729Sjoerg case SymbolKind::Using:
1247*e038c9c4Sjoerg case SymbolKind::TemplateTypeParm:
1248*e038c9c4Sjoerg case SymbolKind::TemplateTemplateParm:
1249*e038c9c4Sjoerg case SymbolKind::NonTypeTemplateParm:
12507330f729Sjoerg return CXIdxEntity_Unexposed;
12517330f729Sjoerg
12527330f729Sjoerg case SymbolKind::Enum: return CXIdxEntity_Enum;
12537330f729Sjoerg case SymbolKind::Struct: return CXIdxEntity_Struct;
12547330f729Sjoerg case SymbolKind::Union: return CXIdxEntity_Union;
12557330f729Sjoerg case SymbolKind::TypeAlias:
12567330f729Sjoerg if (Lang == SymbolLanguage::CXX)
12577330f729Sjoerg return CXIdxEntity_CXXTypeAlias;
12587330f729Sjoerg return CXIdxEntity_Typedef;
12597330f729Sjoerg case SymbolKind::Function: return CXIdxEntity_Function;
12607330f729Sjoerg case SymbolKind::Variable: return CXIdxEntity_Variable;
12617330f729Sjoerg case SymbolKind::Field:
12627330f729Sjoerg if (Lang == SymbolLanguage::ObjC)
12637330f729Sjoerg return CXIdxEntity_ObjCIvar;
12647330f729Sjoerg return CXIdxEntity_Field;
12657330f729Sjoerg case SymbolKind::EnumConstant: return CXIdxEntity_EnumConstant;
12667330f729Sjoerg case SymbolKind::Class:
12677330f729Sjoerg if (Lang == SymbolLanguage::ObjC)
12687330f729Sjoerg return CXIdxEntity_ObjCClass;
12697330f729Sjoerg return CXIdxEntity_CXXClass;
12707330f729Sjoerg case SymbolKind::Protocol:
12717330f729Sjoerg if (Lang == SymbolLanguage::ObjC)
12727330f729Sjoerg return CXIdxEntity_ObjCProtocol;
12737330f729Sjoerg return CXIdxEntity_CXXInterface;
12747330f729Sjoerg case SymbolKind::Extension: return CXIdxEntity_ObjCCategory;
12757330f729Sjoerg case SymbolKind::InstanceMethod:
12767330f729Sjoerg if (Lang == SymbolLanguage::ObjC)
12777330f729Sjoerg return CXIdxEntity_ObjCInstanceMethod;
12787330f729Sjoerg return CXIdxEntity_CXXInstanceMethod;
12797330f729Sjoerg case SymbolKind::ClassMethod: return CXIdxEntity_ObjCClassMethod;
12807330f729Sjoerg case SymbolKind::StaticMethod: return CXIdxEntity_CXXStaticMethod;
12817330f729Sjoerg case SymbolKind::InstanceProperty: return CXIdxEntity_ObjCProperty;
12827330f729Sjoerg case SymbolKind::StaticProperty: return CXIdxEntity_CXXStaticVariable;
12837330f729Sjoerg case SymbolKind::Namespace: return CXIdxEntity_CXXNamespace;
12847330f729Sjoerg case SymbolKind::NamespaceAlias: return CXIdxEntity_CXXNamespaceAlias;
12857330f729Sjoerg case SymbolKind::Constructor: return CXIdxEntity_CXXConstructor;
12867330f729Sjoerg case SymbolKind::Destructor: return CXIdxEntity_CXXDestructor;
12877330f729Sjoerg case SymbolKind::ConversionFunction: return CXIdxEntity_CXXConversionFunction;
12887330f729Sjoerg case SymbolKind::Parameter: return CXIdxEntity_Variable;
12897330f729Sjoerg }
12907330f729Sjoerg llvm_unreachable("invalid symbol kind");
12917330f729Sjoerg }
12927330f729Sjoerg
12937330f729Sjoerg static CXIdxEntityCXXTemplateKind
getEntityKindFromSymbolProperties(SymbolPropertySet K)12947330f729Sjoerg getEntityKindFromSymbolProperties(SymbolPropertySet K) {
12957330f729Sjoerg if (K & (SymbolPropertySet)SymbolProperty::TemplatePartialSpecialization)
12967330f729Sjoerg return CXIdxEntity_TemplatePartialSpecialization;
12977330f729Sjoerg if (K & (SymbolPropertySet)SymbolProperty::TemplateSpecialization)
12987330f729Sjoerg return CXIdxEntity_TemplateSpecialization;
12997330f729Sjoerg if (K & (SymbolPropertySet)SymbolProperty::Generic)
13007330f729Sjoerg return CXIdxEntity_Template;
13017330f729Sjoerg return CXIdxEntity_NonTemplate;
13027330f729Sjoerg }
13037330f729Sjoerg
getEntityLangFromSymbolLang(SymbolLanguage L)13047330f729Sjoerg static CXIdxEntityLanguage getEntityLangFromSymbolLang(SymbolLanguage L) {
13057330f729Sjoerg switch (L) {
13067330f729Sjoerg case SymbolLanguage::C: return CXIdxEntityLang_C;
13077330f729Sjoerg case SymbolLanguage::ObjC: return CXIdxEntityLang_ObjC;
13087330f729Sjoerg case SymbolLanguage::CXX: return CXIdxEntityLang_CXX;
13097330f729Sjoerg case SymbolLanguage::Swift: return CXIdxEntityLang_Swift;
13107330f729Sjoerg }
13117330f729Sjoerg llvm_unreachable("invalid symbol language");
13127330f729Sjoerg }
1313