503 lines · c
1//===- CXIndexDataConsumer.h - Index data consumer for libclang--*- C++ -*-===//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#ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXINDEXDATACONSUMER_H10#define LLVM_CLANG_TOOLS_LIBCLANG_CXINDEXDATACONSUMER_H11 12#include "CXCursor.h"13#include "Index_Internal.h"14#include "clang/Index/IndexDataConsumer.h"15#include "clang/AST/DeclGroup.h"16#include "clang/AST/DeclObjC.h"17#include "llvm/ADT/DenseSet.h"18 19namespace clang {20 class FileEntry;21 class MSPropertyDecl;22 class ObjCPropertyDecl;23 class ClassTemplateDecl;24 class FunctionTemplateDecl;25 class TypeAliasTemplateDecl;26 class ClassTemplateSpecializationDecl;27 28namespace cxindex {29 class CXIndexDataConsumer;30 class AttrListInfo;31 32class ScratchAlloc {33 CXIndexDataConsumer &IdxCtx;34 35public:36 explicit ScratchAlloc(CXIndexDataConsumer &indexCtx);37 ScratchAlloc(const ScratchAlloc &SA);38 39 ~ScratchAlloc();40 41 const char *toCStr(StringRef Str);42 const char *copyCStr(StringRef Str);43 44 template <typename T>45 T *allocate();46};47 48struct EntityInfo : public CXIdxEntityInfo {49 const NamedDecl *Dcl;50 CXIndexDataConsumer *IndexCtx;51 IntrusiveRefCntPtr<AttrListInfo> AttrList;52 53 EntityInfo() {54 name = USR = nullptr;55 attributes = nullptr;56 numAttributes = 0;57 }58};59 60struct ContainerInfo : public CXIdxContainerInfo {61 const DeclContext *DC;62 CXIndexDataConsumer *IndexCtx;63};64 65struct DeclInfo : public CXIdxDeclInfo {66 enum DInfoKind {67 Info_Decl,68 69 Info_ObjCContainer,70 Info_ObjCInterface,71 Info_ObjCProtocol,72 Info_ObjCCategory,73 74 Info_ObjCProperty,75 76 Info_CXXClass77 };78 79 DInfoKind Kind;80 81 EntityInfo EntInfo;82 ContainerInfo SemanticContainer;83 ContainerInfo LexicalContainer;84 ContainerInfo DeclAsContainer;85 86 DeclInfo(bool isRedeclaration, bool isDefinition, bool isContainer)87 : Kind(Info_Decl) {88 this->isRedeclaration = isRedeclaration;89 this->isDefinition = isDefinition;90 this->isContainer = isContainer;91 attributes = nullptr;92 numAttributes = 0;93 declAsContainer = semanticContainer = lexicalContainer = nullptr;94 flags = 0;95 }96 DeclInfo(DInfoKind K,97 bool isRedeclaration, bool isDefinition, bool isContainer)98 : Kind(K) {99 this->isRedeclaration = isRedeclaration;100 this->isDefinition = isDefinition;101 this->isContainer = isContainer;102 attributes = nullptr;103 numAttributes = 0;104 declAsContainer = semanticContainer = lexicalContainer = nullptr;105 flags = 0;106 }107};108 109struct ObjCContainerDeclInfo : public DeclInfo {110 CXIdxObjCContainerDeclInfo ObjCContDeclInfo;111 112 ObjCContainerDeclInfo(bool isForwardRef,113 bool isRedeclaration,114 bool isImplementation)115 : DeclInfo(Info_ObjCContainer, isRedeclaration,116 /*isDefinition=*/!isForwardRef, /*isContainer=*/!isForwardRef) {117 init(isForwardRef, isImplementation);118 }119 ObjCContainerDeclInfo(DInfoKind K,120 bool isForwardRef,121 bool isRedeclaration,122 bool isImplementation)123 : DeclInfo(K, isRedeclaration, /*isDefinition=*/!isForwardRef,124 /*isContainer=*/!isForwardRef) {125 init(isForwardRef, isImplementation);126 }127 128 static bool classof(const DeclInfo *D) {129 return Info_ObjCContainer <= D->Kind && D->Kind <= Info_ObjCCategory;130 }131 132private:133 void init(bool isForwardRef, bool isImplementation) {134 if (isForwardRef)135 ObjCContDeclInfo.kind = CXIdxObjCContainer_ForwardRef;136 else if (isImplementation)137 ObjCContDeclInfo.kind = CXIdxObjCContainer_Implementation;138 else139 ObjCContDeclInfo.kind = CXIdxObjCContainer_Interface;140 }141};142 143struct ObjCInterfaceDeclInfo : public ObjCContainerDeclInfo {144 CXIdxObjCInterfaceDeclInfo ObjCInterDeclInfo;145 CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;146 147 ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D)148 : ObjCContainerDeclInfo(Info_ObjCInterface,149 /*isForwardRef=*/false,150 /*isRedeclaration=*/D->getPreviousDecl() != nullptr,151 /*isImplementation=*/false) { }152 153 static bool classof(const DeclInfo *D) {154 return D->Kind == Info_ObjCInterface;155 }156};157 158struct ObjCProtocolDeclInfo : public ObjCContainerDeclInfo {159 CXIdxObjCProtocolRefListInfo ObjCProtoRefListInfo;160 161 ObjCProtocolDeclInfo(const ObjCProtocolDecl *D)162 : ObjCContainerDeclInfo(Info_ObjCProtocol,163 /*isForwardRef=*/false,164 /*isRedeclaration=*/D->getPreviousDecl(),165 /*isImplementation=*/false) { }166 167 static bool classof(const DeclInfo *D) {168 return D->Kind == Info_ObjCProtocol;169 }170};171 172struct ObjCCategoryDeclInfo : public ObjCContainerDeclInfo {173 CXIdxObjCCategoryDeclInfo ObjCCatDeclInfo;174 CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;175 176 explicit ObjCCategoryDeclInfo(bool isImplementation)177 : ObjCContainerDeclInfo(Info_ObjCCategory,178 /*isForwardRef=*/false,179 /*isRedeclaration=*/isImplementation,180 /*isImplementation=*/isImplementation) { }181 182 static bool classof(const DeclInfo *D) {183 return D->Kind == Info_ObjCCategory;184 }185};186 187struct ObjCPropertyDeclInfo : public DeclInfo {188 CXIdxObjCPropertyDeclInfo ObjCPropDeclInfo;189 190 ObjCPropertyDeclInfo()191 : DeclInfo(Info_ObjCProperty,192 /*isRedeclaration=*/false, /*isDefinition=*/false,193 /*isContainer=*/false) { }194 195 static bool classof(const DeclInfo *D) {196 return D->Kind == Info_ObjCProperty;197 }198};199 200struct CXXClassDeclInfo : public DeclInfo {201 CXIdxCXXClassDeclInfo CXXClassInfo;202 203 CXXClassDeclInfo(bool isRedeclaration, bool isDefinition)204 : DeclInfo(Info_CXXClass, isRedeclaration, isDefinition, isDefinition) { }205 206 static bool classof(const DeclInfo *D) {207 return D->Kind == Info_CXXClass;208 }209};210 211struct AttrInfo : public CXIdxAttrInfo {212 const Attr *A;213 214 AttrInfo(CXIdxAttrKind Kind, CXCursor C, CXIdxLoc Loc, const Attr *A) {215 kind = Kind;216 cursor = C;217 loc = Loc;218 this->A = A;219 }220};221 222struct IBOutletCollectionInfo : public AttrInfo {223 EntityInfo ClassInfo;224 CXIdxIBOutletCollectionAttrInfo IBCollInfo;225 226 IBOutletCollectionInfo(CXCursor C, CXIdxLoc Loc, const Attr *A) :227 AttrInfo(CXIdxAttr_IBOutletCollection, C, Loc, A) {228 assert(C.kind == CXCursor_IBOutletCollectionAttr);229 IBCollInfo.objcClass = nullptr;230 }231 232 IBOutletCollectionInfo(const IBOutletCollectionInfo &other);233 234 static bool classof(const AttrInfo *A) {235 return A->kind == CXIdxAttr_IBOutletCollection;236 }237};238 239class AttrListInfo {240 ScratchAlloc SA;241 242 SmallVector<AttrInfo, 2> Attrs;243 SmallVector<IBOutletCollectionInfo, 2> IBCollAttrs;244 SmallVector<CXIdxAttrInfo *, 2> CXAttrs;245 unsigned ref_cnt;246 247 AttrListInfo(const AttrListInfo &) = delete;248 void operator=(const AttrListInfo &) = delete;249public:250 AttrListInfo(const Decl *D, CXIndexDataConsumer &IdxCtx);251 252 static IntrusiveRefCntPtr<AttrListInfo> create(const Decl *D,253 CXIndexDataConsumer &IdxCtx);254 255 const CXIdxAttrInfo *const *getAttrs() const {256 if (CXAttrs.empty())257 return nullptr;258 return CXAttrs.data();259 }260 unsigned getNumAttrs() const { return (unsigned)CXAttrs.size(); }261 262 /// Retain/Release only useful when we allocate a AttrListInfo from the263 /// BumpPtrAllocator, and not from the stack; so that we keep a pointer264 // in the EntityInfo265 void Retain() { ++ref_cnt; }266 void Release() {267 assert (ref_cnt > 0 && "Reference count is already zero.");268 if (--ref_cnt == 0) {269 // Memory is allocated from a BumpPtrAllocator, no need to delete it.270 this->~AttrListInfo();271 }272 }273};274 275class CXIndexDataConsumer : public index::IndexDataConsumer {276 ASTContext *Ctx;277 CXClientData ClientData;278 IndexerCallbacks &CB;279 unsigned IndexOptions;280 CXTranslationUnit CXTU;281 282 typedef llvm::DenseMap<const FileEntry *, CXIdxClientFile> FileMapTy;283 typedef llvm::DenseMap<const DeclContext *, CXIdxClientContainer>284 ContainerMapTy;285 typedef llvm::DenseMap<const Decl *, CXIdxClientEntity> EntityMapTy;286 287 FileMapTy FileMap;288 ContainerMapTy ContainerMap;289 EntityMapTy EntityMap;290 291 typedef std::pair<const FileEntry *, const Decl *> RefFileOccurrence;292 llvm::DenseSet<RefFileOccurrence> RefFileOccurrences;293 294 llvm::BumpPtrAllocator StrScratch;295 unsigned StrAdapterCount;296 friend class ScratchAlloc;297 298 struct ObjCProtocolListInfo {299 SmallVector<CXIdxObjCProtocolRefInfo, 4> ProtInfos;300 SmallVector<EntityInfo, 4> ProtEntities;301 SmallVector<CXIdxObjCProtocolRefInfo *, 4> Prots;302 303 CXIdxObjCProtocolRefListInfo getListInfo() const {304 CXIdxObjCProtocolRefListInfo Info = { Prots.data(),305 (unsigned)Prots.size() };306 return Info;307 }308 309 ObjCProtocolListInfo(const ObjCProtocolList &ProtList,310 CXIndexDataConsumer &IdxCtx,311 ScratchAlloc &SA);312 };313 314 struct CXXBasesListInfo {315 SmallVector<CXIdxBaseClassInfo, 4> BaseInfos;316 SmallVector<EntityInfo, 4> BaseEntities;317 SmallVector<CXIdxBaseClassInfo *, 4> CXBases;318 319 const CXIdxBaseClassInfo *const *getBases() const {320 return CXBases.data();321 }322 unsigned getNumBases() const { return (unsigned)CXBases.size(); }323 324 CXXBasesListInfo(const CXXRecordDecl *D,325 CXIndexDataConsumer &IdxCtx, ScratchAlloc &SA);326 327 private:328 SourceLocation getBaseLoc(const CXXBaseSpecifier &Base) const;329 };330 331 friend class AttrListInfo;332 333public:334 CXIndexDataConsumer(CXClientData clientData, IndexerCallbacks &indexCallbacks,335 unsigned indexOptions, CXTranslationUnit cxTU)336 : Ctx(nullptr), ClientData(clientData), CB(indexCallbacks),337 IndexOptions(indexOptions), CXTU(cxTU), StrAdapterCount(0) {}338 339 ASTContext &getASTContext() const { return *Ctx; }340 CXTranslationUnit getCXTU() const { return CXTU; }341 342 void setASTContext(llvm::IntrusiveRefCntPtr<ASTContext> ctx);343 void setPreprocessor(std::shared_ptr<Preprocessor> PP) override;344 345 bool shouldSuppressRefs() const {346 return IndexOptions & CXIndexOpt_SuppressRedundantRefs;347 }348 349 bool shouldIndexFunctionLocalSymbols() const {350 return IndexOptions & CXIndexOpt_IndexFunctionLocalSymbols;351 }352 353 bool shouldIndexImplicitTemplateInsts() const {354 return IndexOptions & CXIndexOpt_IndexImplicitTemplateInstantiations;355 }356 357 static bool isFunctionLocalDecl(const Decl *D);358 359 bool shouldAbort();360 361 bool hasDiagnosticCallback() const { return CB.diagnostic; }362 363 void enteredMainFile(OptionalFileEntryRef File);364 365 void ppIncludedFile(SourceLocation hashLoc, StringRef filename,366 OptionalFileEntryRef File, bool isImport, bool isAngled,367 bool isModuleImport);368 369 void importedModule(const ImportDecl *ImportD);370 void importedPCH(FileEntryRef File);371 372 void startedTranslationUnit();373 374 void indexDiagnostics();375 376 void handleDiagnosticSet(CXDiagnosticSet CXDiagSet);377 378 bool handleFunction(const FunctionDecl *FD);379 380 bool handleVar(const VarDecl *D);381 382 bool handleField(const FieldDecl *D);383 384 bool handleEnumerator(const EnumConstantDecl *D);385 386 bool handleTagDecl(const TagDecl *D);387 388 bool handleTypedefName(const TypedefNameDecl *D);389 390 bool handleObjCInterface(const ObjCInterfaceDecl *D);391 bool handleObjCImplementation(const ObjCImplementationDecl *D);392 393 bool handleObjCProtocol(const ObjCProtocolDecl *D);394 395 bool handleObjCCategory(const ObjCCategoryDecl *D);396 bool handleObjCCategoryImpl(const ObjCCategoryImplDecl *D);397 398 bool handleObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc);399 400 bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl *D);401 bool handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc,402 const DeclContext *LexicalDC);403 404 bool handleObjCProperty(const ObjCPropertyDecl *D);405 406 bool handleNamespace(const NamespaceDecl *D);407 408 bool handleClassTemplate(const ClassTemplateDecl *D);409 bool handleFunctionTemplate(const FunctionTemplateDecl *D);410 bool handleTypeAliasTemplate(const TypeAliasTemplateDecl *D);411 412 bool handleConcept(const ConceptDecl *D);413 414 bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor,415 const NamedDecl *Parent,416 const DeclContext *DC,417 const Expr *E = nullptr,418 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct,419 CXSymbolRole Role = CXSymbolRole_None);420 421 bool isNotFromSourceFile(SourceLocation Loc) const;422 423 void translateLoc(SourceLocation Loc, CXIdxClientFile *indexFile, CXFile *file,424 unsigned *line, unsigned *column, unsigned *offset);425 426 CXIdxClientContainer getClientContainerForDC(const DeclContext *DC) const;427 void addContainerInMap(const DeclContext *DC, CXIdxClientContainer container);428 429 CXIdxClientEntity getClientEntity(const Decl *D) const;430 void setClientEntity(const Decl *D, CXIdxClientEntity client);431 432 static bool isTemplateImplicitInstantiation(const Decl *D);433 434private:435 bool handleDeclOccurrence(const Decl *D, index::SymbolRoleSet Roles,436 ArrayRef<index::SymbolRelation> Relations,437 SourceLocation Loc, ASTNodeInfo ASTNode) override;438 439 bool handleModuleOccurrence(const ImportDecl *ImportD, const Module *Mod,440 index::SymbolRoleSet Roles,441 SourceLocation Loc) override;442 443 void finish() override;444 445 bool handleDecl(const NamedDecl *D,446 SourceLocation Loc, CXCursor Cursor,447 DeclInfo &DInfo,448 const DeclContext *LexicalDC = nullptr,449 const DeclContext *SemaDC = nullptr);450 451 bool handleObjCContainer(const ObjCContainerDecl *D,452 SourceLocation Loc, CXCursor Cursor,453 ObjCContainerDeclInfo &ContDInfo);454 455 bool handleCXXRecordDecl(const CXXRecordDecl *RD, const NamedDecl *OrigD);456 457 bool markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc);458 459 const NamedDecl *getEntityDecl(const NamedDecl *D) const;460 461 const DeclContext *getEntityContainer(const Decl *D) const;462 463 CXIdxClientFile getIndexFile(OptionalFileEntryRef File);464 465 CXIdxLoc getIndexLoc(SourceLocation Loc) const;466 467 void getEntityInfo(const NamedDecl *D,468 EntityInfo &EntityInfo,469 ScratchAlloc &SA);470 471 void getContainerInfo(const DeclContext *DC, ContainerInfo &ContInfo);472 473 CXCursor getCursor(const Decl *D) {474 return cxcursor::MakeCXCursor(D, CXTU);475 }476 477 CXCursor getRefCursor(const NamedDecl *D, SourceLocation Loc);478 479 static bool shouldIgnoreIfImplicit(const Decl *D);480};481 482inline ScratchAlloc::ScratchAlloc(CXIndexDataConsumer &idxCtx) : IdxCtx(idxCtx) {483 ++IdxCtx.StrAdapterCount;484}485inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) {486 ++IdxCtx.StrAdapterCount;487}488 489inline ScratchAlloc::~ScratchAlloc() {490 --IdxCtx.StrAdapterCount;491 if (IdxCtx.StrAdapterCount == 0)492 IdxCtx.StrScratch.Reset();493}494 495template <typename T>496inline T *ScratchAlloc::allocate() {497 return IdxCtx.StrScratch.Allocate<T>();498}499 500}} // end clang::cxindex501 502#endif503