1 //===- IndexingContext.h - Higher level API functions -----------*- 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_INDEXINGCONTEXT_H
11 #define LLVM_CLANG_TOOLS_LIBCLANG_INDEXINGCONTEXT_H
14 #include "Index_Internal.h"
15 #include "clang/AST/DeclGroup.h"
16 #include "clang/AST/DeclObjC.h"
17 #include "llvm/ADT/DenseSet.h"
23 class ObjCPropertyDecl;
24 class ClassTemplateDecl;
25 class FunctionTemplateDecl;
26 class TypeAliasTemplateDecl;
27 class ClassTemplateSpecializationDecl;
30 class IndexingContext;
34 IndexingContext &IdxCtx;
37 explicit ScratchAlloc(IndexingContext &indexCtx);
38 ScratchAlloc(const ScratchAlloc &SA);
42 const char *toCStr(StringRef Str);
43 const char *copyCStr(StringRef Str);
49 struct EntityInfo : public CXIdxEntityInfo {
51 IndexingContext *IndexCtx;
52 IntrusiveRefCntPtr<AttrListInfo> AttrList;
61 struct ContainerInfo : public CXIdxContainerInfo {
62 const DeclContext *DC;
63 IndexingContext *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 &) LLVM_DELETED_FUNCTION;
249 void operator=(const AttrListInfo &) LLVM_DELETED_FUNCTION;
251 AttrListInfo(const Decl *D, IndexingContext &IdxCtx);
253 static IntrusiveRefCntPtr<AttrListInfo> create(const Decl *D,
254 IndexingContext &IdxCtx);
256 const CXIdxAttrInfo *const *getAttrs() const {
259 return CXAttrs.data();
261 unsigned getNumAttrs() const { return (unsigned)CXAttrs.size(); }
263 /// \brief 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 IndexingContext {
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 std::deque<DeclGroupRef> TUDeclsInObjCContainer;
297 llvm::BumpPtrAllocator StrScratch;
298 unsigned StrAdapterCount;
299 friend class ScratchAlloc;
301 struct ObjCProtocolListInfo {
302 SmallVector<CXIdxObjCProtocolRefInfo, 4> ProtInfos;
303 SmallVector<EntityInfo, 4> ProtEntities;
304 SmallVector<CXIdxObjCProtocolRefInfo *, 4> Prots;
306 CXIdxObjCProtocolRefListInfo getListInfo() const {
307 CXIdxObjCProtocolRefListInfo Info = { Prots.data(),
308 (unsigned)Prots.size() };
312 ObjCProtocolListInfo(const ObjCProtocolList &ProtList,
313 IndexingContext &IdxCtx,
317 struct CXXBasesListInfo {
318 SmallVector<CXIdxBaseClassInfo, 4> BaseInfos;
319 SmallVector<EntityInfo, 4> BaseEntities;
320 SmallVector<CXIdxBaseClassInfo *, 4> CXBases;
322 const CXIdxBaseClassInfo *const *getBases() const {
323 return CXBases.data();
325 unsigned getNumBases() const { return (unsigned)CXBases.size(); }
327 CXXBasesListInfo(const CXXRecordDecl *D,
328 IndexingContext &IdxCtx, ScratchAlloc &SA);
331 SourceLocation getBaseLoc(const CXXBaseSpecifier &Base) const;
334 friend class AttrListInfo;
337 IndexingContext(CXClientData clientData, IndexerCallbacks &indexCallbacks,
338 unsigned indexOptions, CXTranslationUnit cxTU)
339 : Ctx(nullptr), ClientData(clientData), CB(indexCallbacks),
340 IndexOptions(indexOptions), CXTU(cxTU),
341 StrScratch(), StrAdapterCount(0) { }
343 ASTContext &getASTContext() const { return *Ctx; }
345 void setASTContext(ASTContext &ctx);
346 void setPreprocessor(Preprocessor &PP);
348 bool shouldSuppressRefs() const {
349 return IndexOptions & CXIndexOpt_SuppressRedundantRefs;
352 bool shouldIndexFunctionLocalSymbols() const {
353 return IndexOptions & CXIndexOpt_IndexFunctionLocalSymbols;
356 bool shouldIndexImplicitTemplateInsts() const {
357 return IndexOptions & CXIndexOpt_IndexImplicitTemplateInstantiations;
360 static bool isFunctionLocalDecl(const Decl *D);
364 bool hasDiagnosticCallback() const { return CB.diagnostic; }
366 void enteredMainFile(const FileEntry *File);
368 void ppIncludedFile(SourceLocation hashLoc,
369 StringRef filename, const FileEntry *File,
370 bool isImport, bool isAngled, bool isModuleImport);
372 void importedModule(const ImportDecl *ImportD);
373 void importedPCH(const FileEntry *File);
375 void startedTranslationUnit();
377 void indexDecl(const Decl *D);
379 void indexTagDecl(const TagDecl *D);
381 void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent,
382 const DeclContext *DC = nullptr);
384 void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent,
385 const DeclContext *DC = nullptr);
387 void indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
388 const NamedDecl *Parent,
389 const DeclContext *DC = nullptr);
391 void indexDeclContext(const DeclContext *DC);
393 void indexBody(const Stmt *S, const NamedDecl *Parent,
394 const DeclContext *DC = nullptr);
396 void handleDiagnosticSet(CXDiagnosticSet CXDiagSet);
398 bool handleFunction(const FunctionDecl *FD);
400 bool handleVar(const VarDecl *D);
402 bool handleField(const FieldDecl *D);
404 bool handleMSProperty(const MSPropertyDecl *D);
406 bool handleEnumerator(const EnumConstantDecl *D);
408 bool handleTagDecl(const TagDecl *D);
410 bool handleTypedefName(const TypedefNameDecl *D);
412 bool handleObjCInterface(const ObjCInterfaceDecl *D);
413 bool handleObjCImplementation(const ObjCImplementationDecl *D);
415 bool handleObjCProtocol(const ObjCProtocolDecl *D);
417 bool handleObjCCategory(const ObjCCategoryDecl *D);
418 bool handleObjCCategoryImpl(const ObjCCategoryImplDecl *D);
420 bool handleObjCMethod(const ObjCMethodDecl *D);
422 bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl *D);
423 bool handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc,
424 const DeclContext *LexicalDC);
426 bool handleObjCProperty(const ObjCPropertyDecl *D);
428 bool handleNamespace(const NamespaceDecl *D);
430 bool handleClassTemplate(const ClassTemplateDecl *D);
431 bool handleFunctionTemplate(const FunctionTemplateDecl *D);
432 bool handleTypeAliasTemplate(const TypeAliasTemplateDecl *D);
434 bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor,
435 const NamedDecl *Parent,
436 const DeclContext *DC,
437 const Expr *E = nullptr,
438 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct);
440 bool handleReference(const NamedDecl *D, SourceLocation Loc,
441 const NamedDecl *Parent,
442 const DeclContext *DC,
443 const Expr *E = nullptr,
444 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct);
446 bool isNotFromSourceFile(SourceLocation Loc) const;
448 void indexTopLevelDecl(const Decl *D);
449 void indexTUDeclsInObjCContainer();
450 void indexDeclGroupRef(DeclGroupRef DG);
452 void addTUDeclInObjCContainer(DeclGroupRef DG) {
453 TUDeclsInObjCContainer.push_back(DG);
456 void translateLoc(SourceLocation Loc, CXIdxClientFile *indexFile, CXFile *file,
457 unsigned *line, unsigned *column, unsigned *offset);
459 CXIdxClientContainer getClientContainerForDC(const DeclContext *DC) const;
460 void addContainerInMap(const DeclContext *DC, CXIdxClientContainer container);
462 CXIdxClientEntity getClientEntity(const Decl *D) const;
463 void setClientEntity(const Decl *D, CXIdxClientEntity client);
465 static bool isTemplateImplicitInstantiation(const Decl *D);
468 bool handleDecl(const NamedDecl *D,
469 SourceLocation Loc, CXCursor Cursor,
471 const DeclContext *LexicalDC = nullptr);
473 bool handleObjCContainer(const ObjCContainerDecl *D,
474 SourceLocation Loc, CXCursor Cursor,
475 ObjCContainerDeclInfo &ContDInfo);
477 bool handleCXXRecordDecl(const CXXRecordDecl *RD, const NamedDecl *OrigD);
479 bool markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc);
481 const NamedDecl *getEntityDecl(const NamedDecl *D) const;
483 const DeclContext *getEntityContainer(const Decl *D) const;
485 CXIdxClientFile getIndexFile(const FileEntry *File);
487 CXIdxLoc getIndexLoc(SourceLocation Loc) const;
489 void getEntityInfo(const NamedDecl *D,
490 EntityInfo &EntityInfo,
493 void getContainerInfo(const DeclContext *DC, ContainerInfo &ContInfo);
495 CXCursor getCursor(const Decl *D) {
496 return cxcursor::MakeCXCursor(D, CXTU);
499 CXCursor getRefCursor(const NamedDecl *D, SourceLocation Loc);
501 static bool shouldIgnoreIfImplicit(const Decl *D);
504 inline ScratchAlloc::ScratchAlloc(IndexingContext &idxCtx) : IdxCtx(idxCtx) {
505 ++IdxCtx.StrAdapterCount;
507 inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) {
508 ++IdxCtx.StrAdapterCount;
511 inline ScratchAlloc::~ScratchAlloc() {
512 --IdxCtx.StrAdapterCount;
513 if (IdxCtx.StrAdapterCount == 0)
514 IdxCtx.StrScratch.Reset();
517 template <typename T>
518 inline T *ScratchAlloc::allocate() {
519 return IdxCtx.StrScratch.Allocate<T>();
522 }} // end clang::cxindex