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
9 #ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXINDEXDATACONSUMER_H
10 #define LLVM_CLANG_TOOLS_LIBCLANG_CXINDEXDATACONSUMER_H
11
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
19 namespace clang {
20 class FileEntry;
21 class MSPropertyDecl;
22 class ObjCPropertyDecl;
23 class ClassTemplateDecl;
24 class FunctionTemplateDecl;
25 class TypeAliasTemplateDecl;
26 class ClassTemplateSpecializationDecl;
27
28 namespace cxindex {
29 class CXIndexDataConsumer;
30 class AttrListInfo;
31
32 class ScratchAlloc {
33 CXIndexDataConsumer &IdxCtx;
34
35 public:
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
48 struct EntityInfo : public CXIdxEntityInfo {
49 const NamedDecl *Dcl;
50 CXIndexDataConsumer *IndexCtx;
51 IntrusiveRefCntPtr<AttrListInfo> AttrList;
52
EntityInfoEntityInfo53 EntityInfo() {
54 name = USR = nullptr;
55 attributes = nullptr;
56 numAttributes = 0;
57 }
58 };
59
60 struct ContainerInfo : public CXIdxContainerInfo {
61 const DeclContext *DC;
62 CXIndexDataConsumer *IndexCtx;
63 };
64
65 struct 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_CXXClass
77 };
78
79 DInfoKind Kind;
80
81 EntityInfo EntInfo;
82 ContainerInfo SemanticContainer;
83 ContainerInfo LexicalContainer;
84 ContainerInfo DeclAsContainer;
85
DeclInfoDeclInfo86 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 }
DeclInfoDeclInfo96 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
109 struct ObjCContainerDeclInfo : public DeclInfo {
110 CXIdxObjCContainerDeclInfo ObjCContDeclInfo;
111
ObjCContainerDeclInfoObjCContainerDeclInfo112 ObjCContainerDeclInfo(bool isForwardRef,
113 bool isRedeclaration,
114 bool isImplementation)
115 : DeclInfo(Info_ObjCContainer, isRedeclaration,
116 /*isDefinition=*/!isForwardRef, /*isContainer=*/!isForwardRef) {
117 init(isForwardRef, isImplementation);
118 }
ObjCContainerDeclInfoObjCContainerDeclInfo119 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
classofObjCContainerDeclInfo128 static bool classof(const DeclInfo *D) {
129 return Info_ObjCContainer <= D->Kind && D->Kind <= Info_ObjCCategory;
130 }
131
132 private:
initObjCContainerDeclInfo133 void init(bool isForwardRef, bool isImplementation) {
134 if (isForwardRef)
135 ObjCContDeclInfo.kind = CXIdxObjCContainer_ForwardRef;
136 else if (isImplementation)
137 ObjCContDeclInfo.kind = CXIdxObjCContainer_Implementation;
138 else
139 ObjCContDeclInfo.kind = CXIdxObjCContainer_Interface;
140 }
141 };
142
143 struct ObjCInterfaceDeclInfo : public ObjCContainerDeclInfo {
144 CXIdxObjCInterfaceDeclInfo ObjCInterDeclInfo;
145 CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
146
ObjCInterfaceDeclInfoObjCInterfaceDeclInfo147 ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D)
148 : ObjCContainerDeclInfo(Info_ObjCInterface,
149 /*isForwardRef=*/false,
150 /*isRedeclaration=*/D->getPreviousDecl() != nullptr,
151 /*isImplementation=*/false) { }
152
classofObjCInterfaceDeclInfo153 static bool classof(const DeclInfo *D) {
154 return D->Kind == Info_ObjCInterface;
155 }
156 };
157
158 struct ObjCProtocolDeclInfo : public ObjCContainerDeclInfo {
159 CXIdxObjCProtocolRefListInfo ObjCProtoRefListInfo;
160
ObjCProtocolDeclInfoObjCProtocolDeclInfo161 ObjCProtocolDeclInfo(const ObjCProtocolDecl *D)
162 : ObjCContainerDeclInfo(Info_ObjCProtocol,
163 /*isForwardRef=*/false,
164 /*isRedeclaration=*/D->getPreviousDecl(),
165 /*isImplementation=*/false) { }
166
classofObjCProtocolDeclInfo167 static bool classof(const DeclInfo *D) {
168 return D->Kind == Info_ObjCProtocol;
169 }
170 };
171
172 struct ObjCCategoryDeclInfo : public ObjCContainerDeclInfo {
173 CXIdxObjCCategoryDeclInfo ObjCCatDeclInfo;
174 CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
175
ObjCCategoryDeclInfoObjCCategoryDeclInfo176 explicit ObjCCategoryDeclInfo(bool isImplementation)
177 : ObjCContainerDeclInfo(Info_ObjCCategory,
178 /*isForwardRef=*/false,
179 /*isRedeclaration=*/isImplementation,
180 /*isImplementation=*/isImplementation) { }
181
classofObjCCategoryDeclInfo182 static bool classof(const DeclInfo *D) {
183 return D->Kind == Info_ObjCCategory;
184 }
185 };
186
187 struct ObjCPropertyDeclInfo : public DeclInfo {
188 CXIdxObjCPropertyDeclInfo ObjCPropDeclInfo;
189
ObjCPropertyDeclInfoObjCPropertyDeclInfo190 ObjCPropertyDeclInfo()
191 : DeclInfo(Info_ObjCProperty,
192 /*isRedeclaration=*/false, /*isDefinition=*/false,
193 /*isContainer=*/false) { }
194
classofObjCPropertyDeclInfo195 static bool classof(const DeclInfo *D) {
196 return D->Kind == Info_ObjCProperty;
197 }
198 };
199
200 struct CXXClassDeclInfo : public DeclInfo {
201 CXIdxCXXClassDeclInfo CXXClassInfo;
202
CXXClassDeclInfoCXXClassDeclInfo203 CXXClassDeclInfo(bool isRedeclaration, bool isDefinition)
204 : DeclInfo(Info_CXXClass, isRedeclaration, isDefinition, isDefinition) { }
205
classofCXXClassDeclInfo206 static bool classof(const DeclInfo *D) {
207 return D->Kind == Info_CXXClass;
208 }
209 };
210
211 struct AttrInfo : public CXIdxAttrInfo {
212 const Attr *A;
213
AttrInfoAttrInfo214 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
222 struct IBOutletCollectionInfo : public AttrInfo {
223 EntityInfo ClassInfo;
224 CXIdxIBOutletCollectionAttrInfo IBCollInfo;
225
IBOutletCollectionInfoIBOutletCollectionInfo226 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
classofIBOutletCollectionInfo234 static bool classof(const AttrInfo *A) {
235 return A->kind == CXIdxAttr_IBOutletCollection;
236 }
237 };
238
239 class 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;
249 public:
250 AttrListInfo(const Decl *D, CXIndexDataConsumer &IdxCtx);
251
252 static IntrusiveRefCntPtr<AttrListInfo> create(const Decl *D,
253 CXIndexDataConsumer &IdxCtx);
254
getAttrs()255 const CXIdxAttrInfo *const *getAttrs() const {
256 if (CXAttrs.empty())
257 return nullptr;
258 return CXAttrs.data();
259 }
getNumAttrs()260 unsigned getNumAttrs() const { return (unsigned)CXAttrs.size(); }
261
262 /// Retain/Release only useful when we allocate a AttrListInfo from the
263 /// BumpPtrAllocator, and not from the stack; so that we keep a pointer
264 // in the EntityInfo
Retain()265 void Retain() { ++ref_cnt; }
Release()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
275 class 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
getListInfoObjCProtocolListInfo303 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
getBasesCXXBasesListInfo319 const CXIdxBaseClassInfo *const *getBases() const {
320 return CXBases.data();
321 }
getNumBasesCXXBasesListInfo322 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
333 public:
CXIndexDataConsumer(CXClientData clientData,IndexerCallbacks & indexCallbacks,unsigned indexOptions,CXTranslationUnit cxTU)334 CXIndexDataConsumer(CXClientData clientData, IndexerCallbacks &indexCallbacks,
335 unsigned indexOptions, CXTranslationUnit cxTU)
336 : Ctx(nullptr), ClientData(clientData), CB(indexCallbacks),
337 IndexOptions(indexOptions), CXTU(cxTU),
338 StrScratch(), StrAdapterCount(0) { }
339
getASTContext()340 ASTContext &getASTContext() const { return *Ctx; }
getCXTU()341 CXTranslationUnit getCXTU() const { return CXTU; }
342
343 void setASTContext(ASTContext &ctx);
344 void setPreprocessor(std::shared_ptr<Preprocessor> PP) override;
345
shouldSuppressRefs()346 bool shouldSuppressRefs() const {
347 return IndexOptions & CXIndexOpt_SuppressRedundantRefs;
348 }
349
shouldIndexFunctionLocalSymbols()350 bool shouldIndexFunctionLocalSymbols() const {
351 return IndexOptions & CXIndexOpt_IndexFunctionLocalSymbols;
352 }
353
shouldIndexImplicitTemplateInsts()354 bool shouldIndexImplicitTemplateInsts() const {
355 return IndexOptions & CXIndexOpt_IndexImplicitTemplateInstantiations;
356 }
357
358 static bool isFunctionLocalDecl(const Decl *D);
359
360 bool shouldAbort();
361
hasDiagnosticCallback()362 bool hasDiagnosticCallback() const { return CB.diagnostic; }
363
364 void enteredMainFile(const FileEntry *File);
365
366 void ppIncludedFile(SourceLocation hashLoc,
367 StringRef filename, const FileEntry *File,
368 bool isImport, bool isAngled, bool isModuleImport);
369
370 void importedModule(const ImportDecl *ImportD);
371 void importedPCH(const FileEntry *File);
372
373 void startedTranslationUnit();
374
375 void indexDiagnostics();
376
377 void handleDiagnosticSet(CXDiagnosticSet CXDiagSet);
378
379 bool handleFunction(const FunctionDecl *FD);
380
381 bool handleVar(const VarDecl *D);
382
383 bool handleField(const FieldDecl *D);
384
385 bool handleEnumerator(const EnumConstantDecl *D);
386
387 bool handleTagDecl(const TagDecl *D);
388
389 bool handleTypedefName(const TypedefNameDecl *D);
390
391 bool handleObjCInterface(const ObjCInterfaceDecl *D);
392 bool handleObjCImplementation(const ObjCImplementationDecl *D);
393
394 bool handleObjCProtocol(const ObjCProtocolDecl *D);
395
396 bool handleObjCCategory(const ObjCCategoryDecl *D);
397 bool handleObjCCategoryImpl(const ObjCCategoryImplDecl *D);
398
399 bool handleObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc);
400
401 bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl *D);
402 bool handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc,
403 const DeclContext *LexicalDC);
404
405 bool handleObjCProperty(const ObjCPropertyDecl *D);
406
407 bool handleNamespace(const NamespaceDecl *D);
408
409 bool handleClassTemplate(const ClassTemplateDecl *D);
410 bool handleFunctionTemplate(const FunctionTemplateDecl *D);
411 bool handleTypeAliasTemplate(const TypeAliasTemplateDecl *D);
412
413 bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor,
414 const NamedDecl *Parent,
415 const DeclContext *DC,
416 const Expr *E = nullptr,
417 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct,
418 CXSymbolRole Role = CXSymbolRole_None);
419
420 bool isNotFromSourceFile(SourceLocation Loc) const;
421
422 void translateLoc(SourceLocation Loc, CXIdxClientFile *indexFile, CXFile *file,
423 unsigned *line, unsigned *column, unsigned *offset);
424
425 CXIdxClientContainer getClientContainerForDC(const DeclContext *DC) const;
426 void addContainerInMap(const DeclContext *DC, CXIdxClientContainer container);
427
428 CXIdxClientEntity getClientEntity(const Decl *D) const;
429 void setClientEntity(const Decl *D, CXIdxClientEntity client);
430
431 static bool isTemplateImplicitInstantiation(const Decl *D);
432
433 private:
434 bool handleDeclOccurrence(const Decl *D, index::SymbolRoleSet Roles,
435 ArrayRef<index::SymbolRelation> Relations,
436 SourceLocation Loc, ASTNodeInfo ASTNode) override;
437
438 bool handleModuleOccurrence(const ImportDecl *ImportD, const Module *Mod,
439 index::SymbolRoleSet Roles,
440 SourceLocation Loc) override;
441
442 void finish() override;
443
444 bool handleDecl(const NamedDecl *D,
445 SourceLocation Loc, CXCursor Cursor,
446 DeclInfo &DInfo,
447 const DeclContext *LexicalDC = nullptr,
448 const DeclContext *SemaDC = nullptr);
449
450 bool handleObjCContainer(const ObjCContainerDecl *D,
451 SourceLocation Loc, CXCursor Cursor,
452 ObjCContainerDeclInfo &ContDInfo);
453
454 bool handleCXXRecordDecl(const CXXRecordDecl *RD, const NamedDecl *OrigD);
455
456 bool markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc);
457
458 const NamedDecl *getEntityDecl(const NamedDecl *D) const;
459
460 const DeclContext *getEntityContainer(const Decl *D) const;
461
462 CXIdxClientFile getIndexFile(const FileEntry *File);
463
464 CXIdxLoc getIndexLoc(SourceLocation Loc) const;
465
466 void getEntityInfo(const NamedDecl *D,
467 EntityInfo &EntityInfo,
468 ScratchAlloc &SA);
469
470 void getContainerInfo(const DeclContext *DC, ContainerInfo &ContInfo);
471
getCursor(const Decl * D)472 CXCursor getCursor(const Decl *D) {
473 return cxcursor::MakeCXCursor(D, CXTU);
474 }
475
476 CXCursor getRefCursor(const NamedDecl *D, SourceLocation Loc);
477
478 static bool shouldIgnoreIfImplicit(const Decl *D);
479 };
480
ScratchAlloc(CXIndexDataConsumer & idxCtx)481 inline ScratchAlloc::ScratchAlloc(CXIndexDataConsumer &idxCtx) : IdxCtx(idxCtx) {
482 ++IdxCtx.StrAdapterCount;
483 }
ScratchAlloc(const ScratchAlloc & SA)484 inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) {
485 ++IdxCtx.StrAdapterCount;
486 }
487
~ScratchAlloc()488 inline ScratchAlloc::~ScratchAlloc() {
489 --IdxCtx.StrAdapterCount;
490 if (IdxCtx.StrAdapterCount == 0)
491 IdxCtx.StrScratch.Reset();
492 }
493
494 template <typename T>
allocate()495 inline T *ScratchAlloc::allocate() {
496 return IdxCtx.StrScratch.Allocate<T>();
497 }
498
499 }} // end clang::cxindex
500
501 #endif
502