1 //===- CXIndexDataConsumer.h - Index data consumer for libclang--*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef LLVM_CLANG_TOOLS_LIBCLANG_CXINDEXDATACONSUMER_H
11 #define LLVM_CLANG_TOOLS_LIBCLANG_CXINDEXDATACONSUMER_H
14 #include "Index_Internal.h"
15 #include "clang/Index/IndexDataConsumer.h"
16 #include "clang/AST/DeclGroup.h"
17 #include "clang/AST/DeclObjC.h"
18 #include "llvm/ADT/DenseSet.h"
23 class ObjCPropertyDecl;
24 class ClassTemplateDecl;
25 class FunctionTemplateDecl;
26 class TypeAliasTemplateDecl;
27 class ClassTemplateSpecializationDecl;
30 class CXIndexDataConsumer;
34 CXIndexDataConsumer &IdxCtx;
37 explicit ScratchAlloc(CXIndexDataConsumer &indexCtx);
38 ScratchAlloc(const ScratchAlloc &SA);
42 const char *toCStr(StringRef Str);
43 const char *copyCStr(StringRef Str);
49 struct EntityInfo : public CXIdxEntityInfo {
51 CXIndexDataConsumer *IndexCtx;
52 IntrusiveRefCntPtr<AttrListInfo> AttrList;
61 struct ContainerInfo : public CXIdxContainerInfo {
62 const DeclContext *DC;
63 CXIndexDataConsumer *IndexCtx;
66 struct DeclInfo : public CXIdxDeclInfo {
83 ContainerInfo SemanticContainer;
84 ContainerInfo LexicalContainer;
85 ContainerInfo DeclAsContainer;
87 DeclInfo(bool isRedeclaration, bool isDefinition, bool isContainer)
89 this->isRedeclaration = isRedeclaration;
90 this->isDefinition = isDefinition;
91 this->isContainer = isContainer;
94 declAsContainer = semanticContainer = lexicalContainer = nullptr;
98 bool isRedeclaration, bool isDefinition, bool isContainer)
100 this->isRedeclaration = isRedeclaration;
101 this->isDefinition = isDefinition;
102 this->isContainer = isContainer;
103 attributes = nullptr;
105 declAsContainer = semanticContainer = lexicalContainer = nullptr;
110 struct ObjCContainerDeclInfo : public DeclInfo {
111 CXIdxObjCContainerDeclInfo ObjCContDeclInfo;
113 ObjCContainerDeclInfo(bool isForwardRef,
114 bool isRedeclaration,
115 bool isImplementation)
116 : DeclInfo(Info_ObjCContainer, isRedeclaration,
117 /*isDefinition=*/!isForwardRef, /*isContainer=*/!isForwardRef) {
118 init(isForwardRef, isImplementation);
120 ObjCContainerDeclInfo(DInfoKind K,
122 bool isRedeclaration,
123 bool isImplementation)
124 : DeclInfo(K, isRedeclaration, /*isDefinition=*/!isForwardRef,
125 /*isContainer=*/!isForwardRef) {
126 init(isForwardRef, isImplementation);
129 static bool classof(const DeclInfo *D) {
130 return Info_ObjCContainer <= D->Kind && D->Kind <= Info_ObjCCategory;
134 void init(bool isForwardRef, bool isImplementation) {
136 ObjCContDeclInfo.kind = CXIdxObjCContainer_ForwardRef;
137 else if (isImplementation)
138 ObjCContDeclInfo.kind = CXIdxObjCContainer_Implementation;
140 ObjCContDeclInfo.kind = CXIdxObjCContainer_Interface;
144 struct ObjCInterfaceDeclInfo : public ObjCContainerDeclInfo {
145 CXIdxObjCInterfaceDeclInfo ObjCInterDeclInfo;
146 CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
148 ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D)
149 : ObjCContainerDeclInfo(Info_ObjCInterface,
150 /*isForwardRef=*/false,
151 /*isRedeclaration=*/D->getPreviousDecl() != nullptr,
152 /*isImplementation=*/false) { }
154 static bool classof(const DeclInfo *D) {
155 return D->Kind == Info_ObjCInterface;
159 struct ObjCProtocolDeclInfo : public ObjCContainerDeclInfo {
160 CXIdxObjCProtocolRefListInfo ObjCProtoRefListInfo;
162 ObjCProtocolDeclInfo(const ObjCProtocolDecl *D)
163 : ObjCContainerDeclInfo(Info_ObjCProtocol,
164 /*isForwardRef=*/false,
165 /*isRedeclaration=*/D->getPreviousDecl(),
166 /*isImplementation=*/false) { }
168 static bool classof(const DeclInfo *D) {
169 return D->Kind == Info_ObjCProtocol;
173 struct ObjCCategoryDeclInfo : public ObjCContainerDeclInfo {
174 CXIdxObjCCategoryDeclInfo ObjCCatDeclInfo;
175 CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
177 explicit ObjCCategoryDeclInfo(bool isImplementation)
178 : ObjCContainerDeclInfo(Info_ObjCCategory,
179 /*isForwardRef=*/false,
180 /*isRedeclaration=*/isImplementation,
181 /*isImplementation=*/isImplementation) { }
183 static bool classof(const DeclInfo *D) {
184 return D->Kind == Info_ObjCCategory;
188 struct ObjCPropertyDeclInfo : public DeclInfo {
189 CXIdxObjCPropertyDeclInfo ObjCPropDeclInfo;
191 ObjCPropertyDeclInfo()
192 : DeclInfo(Info_ObjCProperty,
193 /*isRedeclaration=*/false, /*isDefinition=*/false,
194 /*isContainer=*/false) { }
196 static bool classof(const DeclInfo *D) {
197 return D->Kind == Info_ObjCProperty;
201 struct CXXClassDeclInfo : public DeclInfo {
202 CXIdxCXXClassDeclInfo CXXClassInfo;
204 CXXClassDeclInfo(bool isRedeclaration, bool isDefinition)
205 : DeclInfo(Info_CXXClass, isRedeclaration, isDefinition, isDefinition) { }
207 static bool classof(const DeclInfo *D) {
208 return D->Kind == Info_CXXClass;
212 struct AttrInfo : public CXIdxAttrInfo {
215 AttrInfo(CXIdxAttrKind Kind, CXCursor C, CXIdxLoc Loc, const Attr *A) {
223 struct IBOutletCollectionInfo : public AttrInfo {
224 EntityInfo ClassInfo;
225 CXIdxIBOutletCollectionAttrInfo IBCollInfo;
227 IBOutletCollectionInfo(CXCursor C, CXIdxLoc Loc, const Attr *A) :
228 AttrInfo(CXIdxAttr_IBOutletCollection, C, Loc, A) {
229 assert(C.kind == CXCursor_IBOutletCollectionAttr);
230 IBCollInfo.objcClass = nullptr;
233 IBOutletCollectionInfo(const IBOutletCollectionInfo &other);
235 static bool classof(const AttrInfo *A) {
236 return A->kind == CXIdxAttr_IBOutletCollection;
243 SmallVector<AttrInfo, 2> Attrs;
244 SmallVector<IBOutletCollectionInfo, 2> IBCollAttrs;
245 SmallVector<CXIdxAttrInfo *, 2> CXAttrs;
248 AttrListInfo(const AttrListInfo &) = delete;
249 void operator=(const AttrListInfo &) = delete;
251 AttrListInfo(const Decl *D, CXIndexDataConsumer &IdxCtx);
253 static IntrusiveRefCntPtr<AttrListInfo> create(const Decl *D,
254 CXIndexDataConsumer &IdxCtx);
256 const CXIdxAttrInfo *const *getAttrs() const {
259 return CXAttrs.data();
261 unsigned getNumAttrs() const { return (unsigned)CXAttrs.size(); }
263 /// Retain/Release only useful when we allocate a AttrListInfo from the
264 /// BumpPtrAllocator, and not from the stack; so that we keep a pointer
266 void Retain() { ++ref_cnt; }
268 assert (ref_cnt > 0 && "Reference count is already zero.");
269 if (--ref_cnt == 0) {
270 // Memory is allocated from a BumpPtrAllocator, no need to delete it.
271 this->~AttrListInfo();
276 class CXIndexDataConsumer : public index::IndexDataConsumer {
278 CXClientData ClientData;
279 IndexerCallbacks &CB;
280 unsigned IndexOptions;
281 CXTranslationUnit CXTU;
283 typedef llvm::DenseMap<const FileEntry *, CXIdxClientFile> FileMapTy;
284 typedef llvm::DenseMap<const DeclContext *, CXIdxClientContainer>
286 typedef llvm::DenseMap<const Decl *, CXIdxClientEntity> EntityMapTy;
289 ContainerMapTy ContainerMap;
290 EntityMapTy EntityMap;
292 typedef std::pair<const FileEntry *, const Decl *> RefFileOccurrence;
293 llvm::DenseSet<RefFileOccurrence> RefFileOccurrences;
295 llvm::BumpPtrAllocator StrScratch;
296 unsigned StrAdapterCount;
297 friend class ScratchAlloc;
299 struct ObjCProtocolListInfo {
300 SmallVector<CXIdxObjCProtocolRefInfo, 4> ProtInfos;
301 SmallVector<EntityInfo, 4> ProtEntities;
302 SmallVector<CXIdxObjCProtocolRefInfo *, 4> Prots;
304 CXIdxObjCProtocolRefListInfo getListInfo() const {
305 CXIdxObjCProtocolRefListInfo Info = { Prots.data(),
306 (unsigned)Prots.size() };
310 ObjCProtocolListInfo(const ObjCProtocolList &ProtList,
311 CXIndexDataConsumer &IdxCtx,
315 struct CXXBasesListInfo {
316 SmallVector<CXIdxBaseClassInfo, 4> BaseInfos;
317 SmallVector<EntityInfo, 4> BaseEntities;
318 SmallVector<CXIdxBaseClassInfo *, 4> CXBases;
320 const CXIdxBaseClassInfo *const *getBases() const {
321 return CXBases.data();
323 unsigned getNumBases() const { return (unsigned)CXBases.size(); }
325 CXXBasesListInfo(const CXXRecordDecl *D,
326 CXIndexDataConsumer &IdxCtx, ScratchAlloc &SA);
329 SourceLocation getBaseLoc(const CXXBaseSpecifier &Base) const;
332 friend class AttrListInfo;
335 CXIndexDataConsumer(CXClientData clientData, IndexerCallbacks &indexCallbacks,
336 unsigned indexOptions, CXTranslationUnit cxTU)
337 : Ctx(nullptr), ClientData(clientData), CB(indexCallbacks),
338 IndexOptions(indexOptions), CXTU(cxTU),
339 StrScratch(), StrAdapterCount(0) { }
341 ASTContext &getASTContext() const { return *Ctx; }
342 CXTranslationUnit getCXTU() const { return CXTU; }
344 void setASTContext(ASTContext &ctx);
345 void setPreprocessor(std::shared_ptr<Preprocessor> PP) override;
347 bool shouldSuppressRefs() const {
348 return IndexOptions & CXIndexOpt_SuppressRedundantRefs;
351 bool shouldIndexFunctionLocalSymbols() const {
352 return IndexOptions & CXIndexOpt_IndexFunctionLocalSymbols;
355 bool shouldIndexImplicitTemplateInsts() const {
356 return IndexOptions & CXIndexOpt_IndexImplicitTemplateInstantiations;
359 static bool isFunctionLocalDecl(const Decl *D);
363 bool hasDiagnosticCallback() const { return CB.diagnostic; }
365 void enteredMainFile(const FileEntry *File);
367 void ppIncludedFile(SourceLocation hashLoc,
368 StringRef filename, const FileEntry *File,
369 bool isImport, bool isAngled, bool isModuleImport);
371 void importedModule(const ImportDecl *ImportD);
372 void importedPCH(const FileEntry *File);
374 void startedTranslationUnit();
376 void indexDecl(const Decl *D);
378 void indexTagDecl(const TagDecl *D);
380 void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent,
381 const DeclContext *DC = nullptr);
383 void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent,
384 const DeclContext *DC = nullptr);
386 void indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
387 const NamedDecl *Parent,
388 const DeclContext *DC = nullptr);
390 void indexDeclContext(const DeclContext *DC);
392 void indexBody(const Stmt *S, const NamedDecl *Parent,
393 const DeclContext *DC = nullptr);
395 void indexDiagnostics();
397 void handleDiagnosticSet(CXDiagnosticSet CXDiagSet);
399 bool handleFunction(const FunctionDecl *FD);
401 bool handleVar(const VarDecl *D);
403 bool handleField(const FieldDecl *D);
405 bool handleMSProperty(const MSPropertyDecl *D);
407 bool handleEnumerator(const EnumConstantDecl *D);
409 bool handleTagDecl(const TagDecl *D);
411 bool handleTypedefName(const TypedefNameDecl *D);
413 bool handleObjCInterface(const ObjCInterfaceDecl *D);
414 bool handleObjCImplementation(const ObjCImplementationDecl *D);
416 bool handleObjCProtocol(const ObjCProtocolDecl *D);
418 bool handleObjCCategory(const ObjCCategoryDecl *D);
419 bool handleObjCCategoryImpl(const ObjCCategoryImplDecl *D);
421 bool handleObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc);
423 bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl *D);
424 bool handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc,
425 const DeclContext *LexicalDC);
427 bool handleObjCProperty(const ObjCPropertyDecl *D);
429 bool handleNamespace(const NamespaceDecl *D);
431 bool handleClassTemplate(const ClassTemplateDecl *D);
432 bool handleFunctionTemplate(const FunctionTemplateDecl *D);
433 bool handleTypeAliasTemplate(const TypeAliasTemplateDecl *D);
435 bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor,
436 const NamedDecl *Parent,
437 const DeclContext *DC,
438 const Expr *E = nullptr,
439 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct,
440 CXSymbolRole Role = CXSymbolRole_None);
442 bool handleReference(const NamedDecl *D, SourceLocation Loc,
443 const NamedDecl *Parent,
444 const DeclContext *DC,
445 const Expr *E = nullptr,
446 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct,
447 CXSymbolRole Role = CXSymbolRole_None);
449 bool isNotFromSourceFile(SourceLocation Loc) const;
451 void indexTopLevelDecl(const Decl *D);
452 void indexDeclGroupRef(DeclGroupRef DG);
454 void translateLoc(SourceLocation Loc, CXIdxClientFile *indexFile, CXFile *file,
455 unsigned *line, unsigned *column, unsigned *offset);
457 CXIdxClientContainer getClientContainerForDC(const DeclContext *DC) const;
458 void addContainerInMap(const DeclContext *DC, CXIdxClientContainer container);
460 CXIdxClientEntity getClientEntity(const Decl *D) const;
461 void setClientEntity(const Decl *D, CXIdxClientEntity client);
463 static bool isTemplateImplicitInstantiation(const Decl *D);
466 bool handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles,
467 ArrayRef<index::SymbolRelation> Relations,
468 SourceLocation Loc, ASTNodeInfo ASTNode) override;
470 bool handleModuleOccurence(const ImportDecl *ImportD, const Module *Mod,
471 index::SymbolRoleSet Roles,
472 SourceLocation Loc) override;
474 void finish() override;
476 bool handleDecl(const NamedDecl *D,
477 SourceLocation Loc, CXCursor Cursor,
479 const DeclContext *LexicalDC = nullptr,
480 const DeclContext *SemaDC = nullptr);
482 bool handleObjCContainer(const ObjCContainerDecl *D,
483 SourceLocation Loc, CXCursor Cursor,
484 ObjCContainerDeclInfo &ContDInfo);
486 bool handleCXXRecordDecl(const CXXRecordDecl *RD, const NamedDecl *OrigD);
488 bool markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc);
490 const NamedDecl *getEntityDecl(const NamedDecl *D) const;
492 const DeclContext *getEntityContainer(const Decl *D) const;
494 CXIdxClientFile getIndexFile(const FileEntry *File);
496 CXIdxLoc getIndexLoc(SourceLocation Loc) const;
498 void getEntityInfo(const NamedDecl *D,
499 EntityInfo &EntityInfo,
502 void getContainerInfo(const DeclContext *DC, ContainerInfo &ContInfo);
504 CXCursor getCursor(const Decl *D) {
505 return cxcursor::MakeCXCursor(D, CXTU);
508 CXCursor getRefCursor(const NamedDecl *D, SourceLocation Loc);
510 static bool shouldIgnoreIfImplicit(const Decl *D);
513 inline ScratchAlloc::ScratchAlloc(CXIndexDataConsumer &idxCtx) : IdxCtx(idxCtx) {
514 ++IdxCtx.StrAdapterCount;
516 inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) {
517 ++IdxCtx.StrAdapterCount;
520 inline ScratchAlloc::~ScratchAlloc() {
521 --IdxCtx.StrAdapterCount;
522 if (IdxCtx.StrAdapterCount == 0)
523 IdxCtx.StrScratch.Reset();
526 template <typename T>
527 inline T *ScratchAlloc::allocate() {
528 return IdxCtx.StrScratch.Allocate<T>();
531 }} // end clang::cxindex