CXIndexDataConsumer.h 15 KB

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