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 //===----------------------------------------------------------------------===//
11 #include "Index_Internal.h"
12 #include "clang/AST/DeclGroup.h"
13 #include "clang/AST/DeclObjC.h"
14 #include "llvm/ADT/DenseSet.h"
20 class ObjCPropertyDecl;
21 class ClassTemplateDecl;
22 class FunctionTemplateDecl;
23 class TypeAliasTemplateDecl;
24 class ClassTemplateSpecializationDecl;
27 class IndexingContext;
31 IndexingContext &IdxCtx;
34 explicit ScratchAlloc(IndexingContext &indexCtx);
35 ScratchAlloc(const ScratchAlloc &SA);
39 const char *toCStr(StringRef Str);
40 const char *copyCStr(StringRef Str);
46 struct EntityInfo : public CXIdxEntityInfo {
48 IndexingContext *IndexCtx;
49 IntrusiveRefCntPtr<AttrListInfo> AttrList;
58 struct ContainerInfo : public CXIdxContainerInfo {
59 const DeclContext *DC;
60 IndexingContext *IndexCtx;
63 struct DeclInfo : public CXIdxDeclInfo {
80 ContainerInfo SemanticContainer;
81 ContainerInfo LexicalContainer;
82 ContainerInfo DeclAsContainer;
84 DeclInfo(bool isRedeclaration, bool isDefinition, bool isContainer)
86 this->isRedeclaration = isRedeclaration;
87 this->isDefinition = isDefinition;
88 this->isContainer = isContainer;
91 declAsContainer = semanticContainer = lexicalContainer = 0;
95 bool isRedeclaration, bool isDefinition, bool isContainer)
97 this->isRedeclaration = isRedeclaration;
98 this->isDefinition = isDefinition;
99 this->isContainer = isContainer;
102 declAsContainer = semanticContainer = lexicalContainer = 0;
107 struct ObjCContainerDeclInfo : public DeclInfo {
108 CXIdxObjCContainerDeclInfo ObjCContDeclInfo;
110 ObjCContainerDeclInfo(bool isForwardRef,
111 bool isRedeclaration,
112 bool isImplementation)
113 : DeclInfo(Info_ObjCContainer, isRedeclaration,
114 /*isDefinition=*/!isForwardRef, /*isContainer=*/!isForwardRef) {
115 init(isForwardRef, isImplementation);
117 ObjCContainerDeclInfo(DInfoKind K,
119 bool isRedeclaration,
120 bool isImplementation)
121 : DeclInfo(K, isRedeclaration, /*isDefinition=*/!isForwardRef,
122 /*isContainer=*/!isForwardRef) {
123 init(isForwardRef, isImplementation);
126 static bool classof(const DeclInfo *D) {
127 return Info_ObjCContainer <= D->Kind && D->Kind <= Info_ObjCCategory;
131 void init(bool isForwardRef, bool isImplementation) {
133 ObjCContDeclInfo.kind = CXIdxObjCContainer_ForwardRef;
134 else if (isImplementation)
135 ObjCContDeclInfo.kind = CXIdxObjCContainer_Implementation;
137 ObjCContDeclInfo.kind = CXIdxObjCContainer_Interface;
141 struct ObjCInterfaceDeclInfo : public ObjCContainerDeclInfo {
142 CXIdxObjCInterfaceDeclInfo ObjCInterDeclInfo;
143 CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
145 ObjCInterfaceDeclInfo(const ObjCInterfaceDecl *D)
146 : ObjCContainerDeclInfo(Info_ObjCInterface,
147 /*isForwardRef=*/false,
148 /*isRedeclaration=*/D->getPreviousDecl() != 0,
149 /*isImplementation=*/false) { }
151 static bool classof(const DeclInfo *D) {
152 return D->Kind == Info_ObjCInterface;
156 struct ObjCProtocolDeclInfo : public ObjCContainerDeclInfo {
157 CXIdxObjCProtocolRefListInfo ObjCProtoRefListInfo;
159 ObjCProtocolDeclInfo(const ObjCProtocolDecl *D)
160 : ObjCContainerDeclInfo(Info_ObjCProtocol,
161 /*isForwardRef=*/false,
162 /*isRedeclaration=*/D->getPreviousDecl(),
163 /*isImplementation=*/false) { }
165 static bool classof(const DeclInfo *D) {
166 return D->Kind == Info_ObjCProtocol;
170 struct ObjCCategoryDeclInfo : public ObjCContainerDeclInfo {
171 CXIdxObjCCategoryDeclInfo ObjCCatDeclInfo;
172 CXIdxObjCProtocolRefListInfo ObjCProtoListInfo;
174 explicit ObjCCategoryDeclInfo(bool isImplementation)
175 : ObjCContainerDeclInfo(Info_ObjCCategory,
176 /*isForwardRef=*/false,
177 /*isRedeclaration=*/isImplementation,
178 /*isImplementation=*/isImplementation) { }
180 static bool classof(const DeclInfo *D) {
181 return D->Kind == Info_ObjCCategory;
185 struct ObjCPropertyDeclInfo : public DeclInfo {
186 CXIdxObjCPropertyDeclInfo ObjCPropDeclInfo;
188 ObjCPropertyDeclInfo()
189 : DeclInfo(Info_ObjCProperty,
190 /*isRedeclaration=*/false, /*isDefinition=*/false,
191 /*isContainer=*/false) { }
193 static bool classof(const DeclInfo *D) {
194 return D->Kind == Info_ObjCProperty;
198 struct CXXClassDeclInfo : public DeclInfo {
199 CXIdxCXXClassDeclInfo CXXClassInfo;
201 CXXClassDeclInfo(bool isRedeclaration, bool isDefinition)
202 : DeclInfo(Info_CXXClass, isRedeclaration, isDefinition, isDefinition) { }
204 static bool classof(const DeclInfo *D) {
205 return D->Kind == Info_CXXClass;
209 struct AttrInfo : public CXIdxAttrInfo {
212 AttrInfo(CXIdxAttrKind Kind, CXCursor C, CXIdxLoc Loc, const Attr *A) {
220 struct IBOutletCollectionInfo : public AttrInfo {
221 EntityInfo ClassInfo;
222 CXIdxIBOutletCollectionAttrInfo IBCollInfo;
224 IBOutletCollectionInfo(CXCursor C, CXIdxLoc Loc, const Attr *A) :
225 AttrInfo(CXIdxAttr_IBOutletCollection, C, Loc, A) {
226 assert(C.kind == CXCursor_IBOutletCollectionAttr);
227 IBCollInfo.objcClass = 0;
230 IBOutletCollectionInfo(const IBOutletCollectionInfo &other);
232 static bool classof(const AttrInfo *A) {
233 return A->kind == CXIdxAttr_IBOutletCollection;
240 SmallVector<AttrInfo, 2> Attrs;
241 SmallVector<IBOutletCollectionInfo, 2> IBCollAttrs;
242 SmallVector<CXIdxAttrInfo *, 2> CXAttrs;
245 AttrListInfo(const AttrListInfo &) LLVM_DELETED_FUNCTION;
246 void operator=(const AttrListInfo &) LLVM_DELETED_FUNCTION;
248 AttrListInfo(const Decl *D, IndexingContext &IdxCtx);
250 static IntrusiveRefCntPtr<AttrListInfo> create(const Decl *D,
251 IndexingContext &IdxCtx);
253 const CXIdxAttrInfo *const *getAttrs() const {
256 return CXAttrs.data();
258 unsigned getNumAttrs() const { return (unsigned)CXAttrs.size(); }
260 /// \brief Retain/Release only useful when we allocate a AttrListInfo from the
261 /// BumpPtrAllocator, and not from the stack; so that we keep a pointer
263 void Retain() { ++ref_cnt; }
265 assert (ref_cnt > 0 && "Reference count is already zero.");
266 if (--ref_cnt == 0) {
267 // Memory is allocated from a BumpPtrAllocator, no need to delete it.
268 this->~AttrListInfo();
273 class IndexingContext {
275 CXClientData ClientData;
276 IndexerCallbacks &CB;
277 unsigned IndexOptions;
278 CXTranslationUnit CXTU;
280 typedef llvm::DenseMap<const FileEntry *, CXIdxClientFile> FileMapTy;
281 typedef llvm::DenseMap<const DeclContext *, CXIdxClientContainer>
283 typedef llvm::DenseMap<const Decl *, CXIdxClientEntity> EntityMapTy;
286 ContainerMapTy ContainerMap;
287 EntityMapTy EntityMap;
289 typedef std::pair<const FileEntry *, const Decl *> RefFileOccurence;
290 llvm::DenseSet<RefFileOccurence> RefFileOccurences;
292 std::deque<DeclGroupRef> TUDeclsInObjCContainer;
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 IndexingContext &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 IndexingContext &IdxCtx, ScratchAlloc &SA);
328 SourceLocation getBaseLoc(const CXXBaseSpecifier &Base) const;
331 friend class AttrListInfo;
334 IndexingContext(CXClientData clientData, IndexerCallbacks &indexCallbacks,
335 unsigned indexOptions, CXTranslationUnit cxTU)
336 : Ctx(0), ClientData(clientData), CB(indexCallbacks),
337 IndexOptions(indexOptions), CXTU(cxTU),
338 StrScratch(/*size=*/1024), StrAdapterCount(0) { }
340 ASTContext &getASTContext() const { return *Ctx; }
342 void setASTContext(ASTContext &ctx);
343 void setPreprocessor(Preprocessor &PP);
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(const FileEntry *File);
365 void ppIncludedFile(SourceLocation hashLoc,
366 StringRef filename, const FileEntry *File,
367 bool isImport, bool isAngled, bool isModuleImport);
369 void importedModule(const ImportDecl *ImportD);
370 void importedPCH(const FileEntry *File);
372 void startedTranslationUnit();
374 void indexDecl(const Decl *D);
376 void indexTagDecl(const TagDecl *D);
378 void indexTypeSourceInfo(TypeSourceInfo *TInfo, const NamedDecl *Parent,
379 const DeclContext *DC = 0);
381 void indexTypeLoc(TypeLoc TL, const NamedDecl *Parent,
382 const DeclContext *DC = 0);
384 void indexNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS,
385 const NamedDecl *Parent,
386 const DeclContext *DC = 0);
388 void indexDeclContext(const DeclContext *DC);
390 void indexBody(const Stmt *S, const NamedDecl *Parent,
391 const DeclContext *DC = 0);
393 void handleDiagnosticSet(CXDiagnosticSet CXDiagSet);
395 bool handleFunction(const FunctionDecl *FD);
397 bool handleVar(const VarDecl *D);
399 bool handleField(const FieldDecl *D);
401 bool handleMSProperty(const MSPropertyDecl *D);
403 bool handleEnumerator(const EnumConstantDecl *D);
405 bool handleTagDecl(const TagDecl *D);
407 bool handleTypedefName(const TypedefNameDecl *D);
409 bool handleObjCInterface(const ObjCInterfaceDecl *D);
410 bool handleObjCImplementation(const ObjCImplementationDecl *D);
412 bool handleObjCProtocol(const ObjCProtocolDecl *D);
414 bool handleObjCCategory(const ObjCCategoryDecl *D);
415 bool handleObjCCategoryImpl(const ObjCCategoryImplDecl *D);
417 bool handleObjCMethod(const ObjCMethodDecl *D);
419 bool handleSynthesizedObjCProperty(const ObjCPropertyImplDecl *D);
420 bool handleSynthesizedObjCMethod(const ObjCMethodDecl *D, SourceLocation Loc,
421 const DeclContext *LexicalDC);
423 bool handleObjCProperty(const ObjCPropertyDecl *D);
425 bool handleNamespace(const NamespaceDecl *D);
427 bool handleClassTemplate(const ClassTemplateDecl *D);
428 bool handleFunctionTemplate(const FunctionTemplateDecl *D);
429 bool handleTypeAliasTemplate(const TypeAliasTemplateDecl *D);
431 bool handleReference(const NamedDecl *D, SourceLocation Loc, CXCursor Cursor,
432 const NamedDecl *Parent,
433 const DeclContext *DC,
435 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct);
437 bool handleReference(const NamedDecl *D, SourceLocation Loc,
438 const NamedDecl *Parent,
439 const DeclContext *DC,
441 CXIdxEntityRefKind Kind = CXIdxEntityRef_Direct);
443 bool isNotFromSourceFile(SourceLocation Loc) const;
445 void indexTopLevelDecl(const Decl *D);
446 void indexTUDeclsInObjCContainer();
447 void indexDeclGroupRef(DeclGroupRef DG);
449 void addTUDeclInObjCContainer(DeclGroupRef DG) {
450 TUDeclsInObjCContainer.push_back(DG);
453 void translateLoc(SourceLocation Loc, CXIdxClientFile *indexFile, CXFile *file,
454 unsigned *line, unsigned *column, unsigned *offset);
456 CXIdxClientContainer getClientContainerForDC(const DeclContext *DC) const;
457 void addContainerInMap(const DeclContext *DC, CXIdxClientContainer container);
459 CXIdxClientEntity getClientEntity(const Decl *D) const;
460 void setClientEntity(const Decl *D, CXIdxClientEntity client);
462 static bool isTemplateImplicitInstantiation(const Decl *D);
465 bool handleDecl(const NamedDecl *D,
466 SourceLocation Loc, CXCursor Cursor,
468 const DeclContext *LexicalDC = 0);
470 bool handleObjCContainer(const ObjCContainerDecl *D,
471 SourceLocation Loc, CXCursor Cursor,
472 ObjCContainerDeclInfo &ContDInfo);
474 bool handleCXXRecordDecl(const CXXRecordDecl *RD, const NamedDecl *OrigD);
476 bool markEntityOccurrenceInFile(const NamedDecl *D, SourceLocation Loc);
478 const NamedDecl *getEntityDecl(const NamedDecl *D) const;
480 const DeclContext *getEntityContainer(const Decl *D) const;
482 CXIdxClientFile getIndexFile(const FileEntry *File);
484 CXIdxLoc getIndexLoc(SourceLocation Loc) const;
486 void getEntityInfo(const NamedDecl *D,
487 EntityInfo &EntityInfo,
490 void getContainerInfo(const DeclContext *DC, ContainerInfo &ContInfo);
492 CXCursor getCursor(const Decl *D) {
493 return cxcursor::MakeCXCursor(D, CXTU);
496 CXCursor getRefCursor(const NamedDecl *D, SourceLocation Loc);
498 static bool shouldIgnoreIfImplicit(const Decl *D);
501 inline ScratchAlloc::ScratchAlloc(IndexingContext &idxCtx) : IdxCtx(idxCtx) {
502 ++IdxCtx.StrAdapterCount;
504 inline ScratchAlloc::ScratchAlloc(const ScratchAlloc &SA) : IdxCtx(SA.IdxCtx) {
505 ++IdxCtx.StrAdapterCount;
508 inline ScratchAlloc::~ScratchAlloc() {
509 --IdxCtx.StrAdapterCount;
510 if (IdxCtx.StrAdapterCount == 0)
511 IdxCtx.StrScratch.Reset();
514 template <typename T>
515 inline T *ScratchAlloc::allocate() {
516 return IdxCtx.StrScratch.Allocate<T>();
519 }} // end clang::cxindex