1 //===- CXIndexDataConsumer.h - Index data consumer for libclang--*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXINDEXDATACONSUMER_H
10 #define LLVM_CLANG_TOOLS_LIBCLANG_CXINDEXDATACONSUMER_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"
22 class ObjCPropertyDecl
;
23 class ClassTemplateDecl
;
24 class FunctionTemplateDecl
;
25 class TypeAliasTemplateDecl
;
26 class ClassTemplateSpecializationDecl
;
29 class CXIndexDataConsumer
;
33 CXIndexDataConsumer
&IdxCtx
;
36 explicit ScratchAlloc(CXIndexDataConsumer
&indexCtx
);
37 ScratchAlloc(const ScratchAlloc
&SA
);
41 const char *toCStr(StringRef Str
);
42 const char *copyCStr(StringRef Str
);
48 struct EntityInfo
: public CXIdxEntityInfo
{
50 CXIndexDataConsumer
*IndexCtx
;
51 IntrusiveRefCntPtr
<AttrListInfo
> AttrList
;
60 struct ContainerInfo
: public CXIdxContainerInfo
{
61 const DeclContext
*DC
;
62 CXIndexDataConsumer
*IndexCtx
;
65 struct DeclInfo
: public CXIdxDeclInfo
{
82 ContainerInfo SemanticContainer
;
83 ContainerInfo LexicalContainer
;
84 ContainerInfo DeclAsContainer
;
86 DeclInfo(bool isRedeclaration
, bool isDefinition
, bool isContainer
)
88 this->isRedeclaration
= isRedeclaration
;
89 this->isDefinition
= isDefinition
;
90 this->isContainer
= isContainer
;
93 declAsContainer
= semanticContainer
= lexicalContainer
= nullptr;
97 bool isRedeclaration
, bool isDefinition
, bool isContainer
)
99 this->isRedeclaration
= isRedeclaration
;
100 this->isDefinition
= isDefinition
;
101 this->isContainer
= isContainer
;
102 attributes
= nullptr;
104 declAsContainer
= semanticContainer
= lexicalContainer
= nullptr;
109 struct ObjCContainerDeclInfo
: public DeclInfo
{
110 CXIdxObjCContainerDeclInfo ObjCContDeclInfo
;
112 ObjCContainerDeclInfo(bool isForwardRef
,
113 bool isRedeclaration
,
114 bool isImplementation
)
115 : DeclInfo(Info_ObjCContainer
, isRedeclaration
,
116 /*isDefinition=*/!isForwardRef
, /*isContainer=*/!isForwardRef
) {
117 init(isForwardRef
, isImplementation
);
119 ObjCContainerDeclInfo(DInfoKind K
,
121 bool isRedeclaration
,
122 bool isImplementation
)
123 : DeclInfo(K
, isRedeclaration
, /*isDefinition=*/!isForwardRef
,
124 /*isContainer=*/!isForwardRef
) {
125 init(isForwardRef
, isImplementation
);
128 static bool classof(const DeclInfo
*D
) {
129 return Info_ObjCContainer
<= D
->Kind
&& D
->Kind
<= Info_ObjCCategory
;
133 void init(bool isForwardRef
, bool isImplementation
) {
135 ObjCContDeclInfo
.kind
= CXIdxObjCContainer_ForwardRef
;
136 else if (isImplementation
)
137 ObjCContDeclInfo
.kind
= CXIdxObjCContainer_Implementation
;
139 ObjCContDeclInfo
.kind
= CXIdxObjCContainer_Interface
;
143 struct ObjCInterfaceDeclInfo
: public ObjCContainerDeclInfo
{
144 CXIdxObjCInterfaceDeclInfo ObjCInterDeclInfo
;
145 CXIdxObjCProtocolRefListInfo ObjCProtoListInfo
;
147 ObjCInterfaceDeclInfo(const ObjCInterfaceDecl
*D
)
148 : ObjCContainerDeclInfo(Info_ObjCInterface
,
149 /*isForwardRef=*/false,
150 /*isRedeclaration=*/D
->getPreviousDecl() != nullptr,
151 /*isImplementation=*/false) { }
153 static bool classof(const DeclInfo
*D
) {
154 return D
->Kind
== Info_ObjCInterface
;
158 struct ObjCProtocolDeclInfo
: public ObjCContainerDeclInfo
{
159 CXIdxObjCProtocolRefListInfo ObjCProtoRefListInfo
;
161 ObjCProtocolDeclInfo(const ObjCProtocolDecl
*D
)
162 : ObjCContainerDeclInfo(Info_ObjCProtocol
,
163 /*isForwardRef=*/false,
164 /*isRedeclaration=*/D
->getPreviousDecl(),
165 /*isImplementation=*/false) { }
167 static bool classof(const DeclInfo
*D
) {
168 return D
->Kind
== Info_ObjCProtocol
;
172 struct ObjCCategoryDeclInfo
: public ObjCContainerDeclInfo
{
173 CXIdxObjCCategoryDeclInfo ObjCCatDeclInfo
;
174 CXIdxObjCProtocolRefListInfo ObjCProtoListInfo
;
176 explicit ObjCCategoryDeclInfo(bool isImplementation
)
177 : ObjCContainerDeclInfo(Info_ObjCCategory
,
178 /*isForwardRef=*/false,
179 /*isRedeclaration=*/isImplementation
,
180 /*isImplementation=*/isImplementation
) { }
182 static bool classof(const DeclInfo
*D
) {
183 return D
->Kind
== Info_ObjCCategory
;
187 struct ObjCPropertyDeclInfo
: public DeclInfo
{
188 CXIdxObjCPropertyDeclInfo ObjCPropDeclInfo
;
190 ObjCPropertyDeclInfo()
191 : DeclInfo(Info_ObjCProperty
,
192 /*isRedeclaration=*/false, /*isDefinition=*/false,
193 /*isContainer=*/false) { }
195 static bool classof(const DeclInfo
*D
) {
196 return D
->Kind
== Info_ObjCProperty
;
200 struct CXXClassDeclInfo
: public DeclInfo
{
201 CXIdxCXXClassDeclInfo CXXClassInfo
;
203 CXXClassDeclInfo(bool isRedeclaration
, bool isDefinition
)
204 : DeclInfo(Info_CXXClass
, isRedeclaration
, isDefinition
, isDefinition
) { }
206 static bool classof(const DeclInfo
*D
) {
207 return D
->Kind
== Info_CXXClass
;
211 struct AttrInfo
: public CXIdxAttrInfo
{
214 AttrInfo(CXIdxAttrKind Kind
, CXCursor C
, CXIdxLoc Loc
, const Attr
*A
) {
222 struct IBOutletCollectionInfo
: public AttrInfo
{
223 EntityInfo ClassInfo
;
224 CXIdxIBOutletCollectionAttrInfo IBCollInfo
;
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;
232 IBOutletCollectionInfo(const IBOutletCollectionInfo
&other
);
234 static bool classof(const AttrInfo
*A
) {
235 return A
->kind
== CXIdxAttr_IBOutletCollection
;
242 SmallVector
<AttrInfo
, 2> Attrs
;
243 SmallVector
<IBOutletCollectionInfo
, 2> IBCollAttrs
;
244 SmallVector
<CXIdxAttrInfo
*, 2> CXAttrs
;
247 AttrListInfo(const AttrListInfo
&) = delete;
248 void operator=(const AttrListInfo
&) = delete;
250 AttrListInfo(const Decl
*D
, CXIndexDataConsumer
&IdxCtx
);
252 static IntrusiveRefCntPtr
<AttrListInfo
> create(const Decl
*D
,
253 CXIndexDataConsumer
&IdxCtx
);
255 const CXIdxAttrInfo
*const *getAttrs() const {
258 return CXAttrs
.data();
260 unsigned getNumAttrs() const { return (unsigned)CXAttrs
.size(); }
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
265 void Retain() { ++ref_cnt
; }
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();
275 class CXIndexDataConsumer
: public index::IndexDataConsumer
{
277 CXClientData ClientData
;
278 IndexerCallbacks
&CB
;
279 unsigned IndexOptions
;
280 CXTranslationUnit CXTU
;
282 typedef llvm::DenseMap
<const FileEntry
*, CXIdxClientFile
> FileMapTy
;
283 typedef llvm::DenseMap
<const DeclContext
*, CXIdxClientContainer
>
285 typedef llvm::DenseMap
<const Decl
*, CXIdxClientEntity
> EntityMapTy
;
288 ContainerMapTy ContainerMap
;
289 EntityMapTy EntityMap
;
291 typedef std::pair
<const FileEntry
*, const Decl
*> RefFileOccurrence
;
292 llvm::DenseSet
<RefFileOccurrence
> RefFileOccurrences
;
294 llvm::BumpPtrAllocator StrScratch
;
295 unsigned StrAdapterCount
;
296 friend class ScratchAlloc
;
298 struct ObjCProtocolListInfo
{
299 SmallVector
<CXIdxObjCProtocolRefInfo
, 4> ProtInfos
;
300 SmallVector
<EntityInfo
, 4> ProtEntities
;
301 SmallVector
<CXIdxObjCProtocolRefInfo
*, 4> Prots
;
303 CXIdxObjCProtocolRefListInfo
getListInfo() const {
304 CXIdxObjCProtocolRefListInfo Info
= { Prots
.data(),
305 (unsigned)Prots
.size() };
309 ObjCProtocolListInfo(const ObjCProtocolList
&ProtList
,
310 CXIndexDataConsumer
&IdxCtx
,
314 struct CXXBasesListInfo
{
315 SmallVector
<CXIdxBaseClassInfo
, 4> BaseInfos
;
316 SmallVector
<EntityInfo
, 4> BaseEntities
;
317 SmallVector
<CXIdxBaseClassInfo
*, 4> CXBases
;
319 const CXIdxBaseClassInfo
*const *getBases() const {
320 return CXBases
.data();
322 unsigned getNumBases() const { return (unsigned)CXBases
.size(); }
324 CXXBasesListInfo(const CXXRecordDecl
*D
,
325 CXIndexDataConsumer
&IdxCtx
, ScratchAlloc
&SA
);
328 SourceLocation
getBaseLoc(const CXXBaseSpecifier
&Base
) const;
331 friend class AttrListInfo
;
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) {}
339 ASTContext
&getASTContext() const { return *Ctx
; }
340 CXTranslationUnit
getCXTU() const { return CXTU
; }
342 void setASTContext(ASTContext
&ctx
);
343 void setPreprocessor(std::shared_ptr
<Preprocessor
> PP
) override
;
345 bool shouldSuppressRefs() const {
346 return IndexOptions
& CXIndexOpt_SuppressRedundantRefs
;
349 bool shouldIndexFunctionLocalSymbols() const {
350 return IndexOptions
& CXIndexOpt_IndexFunctionLocalSymbols
;
353 bool shouldIndexImplicitTemplateInsts() const {
354 return IndexOptions
& CXIndexOpt_IndexImplicitTemplateInstantiations
;
357 static bool isFunctionLocalDecl(const Decl
*D
);
361 bool hasDiagnosticCallback() const { return CB
.diagnostic
; }
363 void enteredMainFile(OptionalFileEntryRef File
);
365 void ppIncludedFile(SourceLocation hashLoc
, StringRef filename
,
366 OptionalFileEntryRef File
, bool isImport
, bool isAngled
,
367 bool isModuleImport
);
369 void importedModule(const ImportDecl
*ImportD
);
370 void importedPCH(FileEntryRef File
);
372 void startedTranslationUnit();
374 void indexDiagnostics();
376 void handleDiagnosticSet(CXDiagnosticSet CXDiagSet
);
378 bool handleFunction(const FunctionDecl
*FD
);
380 bool handleVar(const VarDecl
*D
);
382 bool handleField(const FieldDecl
*D
);
384 bool handleEnumerator(const EnumConstantDecl
*D
);
386 bool handleTagDecl(const TagDecl
*D
);
388 bool handleTypedefName(const TypedefNameDecl
*D
);
390 bool handleObjCInterface(const ObjCInterfaceDecl
*D
);
391 bool handleObjCImplementation(const ObjCImplementationDecl
*D
);
393 bool handleObjCProtocol(const ObjCProtocolDecl
*D
);
395 bool handleObjCCategory(const ObjCCategoryDecl
*D
);
396 bool handleObjCCategoryImpl(const ObjCCategoryImplDecl
*D
);
398 bool handleObjCMethod(const ObjCMethodDecl
*D
, SourceLocation Loc
);
400 bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl
*D
);
401 bool handleSynthesizedObjCMethod(const ObjCMethodDecl
*D
, SourceLocation Loc
,
402 const DeclContext
*LexicalDC
);
404 bool handleObjCProperty(const ObjCPropertyDecl
*D
);
406 bool handleNamespace(const NamespaceDecl
*D
);
408 bool handleClassTemplate(const ClassTemplateDecl
*D
);
409 bool handleFunctionTemplate(const FunctionTemplateDecl
*D
);
410 bool handleTypeAliasTemplate(const TypeAliasTemplateDecl
*D
);
412 bool handleConcept(const ConceptDecl
*D
);
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
);
421 bool isNotFromSourceFile(SourceLocation Loc
) const;
423 void translateLoc(SourceLocation Loc
, CXIdxClientFile
*indexFile
, CXFile
*file
,
424 unsigned *line
, unsigned *column
, unsigned *offset
);
426 CXIdxClientContainer
getClientContainerForDC(const DeclContext
*DC
) const;
427 void addContainerInMap(const DeclContext
*DC
, CXIdxClientContainer container
);
429 CXIdxClientEntity
getClientEntity(const Decl
*D
) const;
430 void setClientEntity(const Decl
*D
, CXIdxClientEntity client
);
432 static bool isTemplateImplicitInstantiation(const Decl
*D
);
435 bool handleDeclOccurrence(const Decl
*D
, index::SymbolRoleSet Roles
,
436 ArrayRef
<index::SymbolRelation
> Relations
,
437 SourceLocation Loc
, ASTNodeInfo ASTNode
) override
;
439 bool handleModuleOccurrence(const ImportDecl
*ImportD
, const Module
*Mod
,
440 index::SymbolRoleSet Roles
,
441 SourceLocation Loc
) override
;
443 void finish() override
;
445 bool handleDecl(const NamedDecl
*D
,
446 SourceLocation Loc
, CXCursor Cursor
,
448 const DeclContext
*LexicalDC
= nullptr,
449 const DeclContext
*SemaDC
= nullptr);
451 bool handleObjCContainer(const ObjCContainerDecl
*D
,
452 SourceLocation Loc
, CXCursor Cursor
,
453 ObjCContainerDeclInfo
&ContDInfo
);
455 bool handleCXXRecordDecl(const CXXRecordDecl
*RD
, const NamedDecl
*OrigD
);
457 bool markEntityOccurrenceInFile(const NamedDecl
*D
, SourceLocation Loc
);
459 const NamedDecl
*getEntityDecl(const NamedDecl
*D
) const;
461 const DeclContext
*getEntityContainer(const Decl
*D
) const;
463 CXIdxClientFile
getIndexFile(const FileEntry
*File
);
465 CXIdxLoc
getIndexLoc(SourceLocation Loc
) const;
467 void getEntityInfo(const NamedDecl
*D
,
468 EntityInfo
&EntityInfo
,
471 void getContainerInfo(const DeclContext
*DC
, ContainerInfo
&ContInfo
);
473 CXCursor
getCursor(const Decl
*D
) {
474 return cxcursor::MakeCXCursor(D
, CXTU
);
477 CXCursor
getRefCursor(const NamedDecl
*D
, SourceLocation Loc
);
479 static bool shouldIgnoreIfImplicit(const Decl
*D
);
482 inline ScratchAlloc::ScratchAlloc(CXIndexDataConsumer
&idxCtx
) : IdxCtx(idxCtx
) {
483 ++IdxCtx
.StrAdapterCount
;
485 inline ScratchAlloc::ScratchAlloc(const ScratchAlloc
&SA
) : IdxCtx(SA
.IdxCtx
) {
486 ++IdxCtx
.StrAdapterCount
;
489 inline ScratchAlloc::~ScratchAlloc() {
490 --IdxCtx
.StrAdapterCount
;
491 if (IdxCtx
.StrAdapterCount
== 0)
492 IdxCtx
.StrScratch
.Reset();
495 template <typename T
>
496 inline T
*ScratchAlloc::allocate() {
497 return IdxCtx
.StrScratch
.Allocate
<T
>();
500 }} // end clang::cxindex